duke@435: /* dlong@7598: * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #ifndef SHARE_VM_RUNTIME_FRAME_HPP stefank@2314: #define SHARE_VM_RUNTIME_FRAME_HPP stefank@2314: coleenp@4037: #include "oops/method.hpp" stefank@2314: #include "runtime/basicLock.hpp" stefank@2314: #include "runtime/monitorChunk.hpp" stefank@2314: #include "runtime/registerMap.hpp" stefank@2314: #include "utilities/top.hpp" stefank@2314: #ifdef COMPILER2 dlong@7598: #if defined ADGLOBALS_MD_HPP dlong@7598: # include ADGLOBALS_MD_HPP dlong@7598: #elif defined TARGET_ARCH_MODEL_x86_32 stefank@2314: # include "adfiles/adGlobals_x86_32.hpp" dlong@7598: #elif defined TARGET_ARCH_MODEL_x86_64 stefank@2314: # include "adfiles/adGlobals_x86_64.hpp" dlong@7598: #elif defined TARGET_ARCH_MODEL_sparc stefank@2314: # include "adfiles/adGlobals_sparc.hpp" dlong@7598: #elif defined TARGET_ARCH_MODEL_zero stefank@2314: # include "adfiles/adGlobals_zero.hpp" dlong@7598: #elif defined TARGET_ARCH_MODEL_ppc_64 goetz@6441: # include "adfiles/adGlobals_ppc_64.hpp" stefank@2314: #endif goetz@6441: #endif // COMPILER2 stefank@2314: #ifdef ZERO stefank@2314: #ifdef TARGET_ARCH_zero stefank@2314: # include "stack_zero.hpp" stefank@2314: #endif stefank@2314: #endif stefank@2314: duke@435: typedef class BytecodeInterpreter* interpreterState; duke@435: duke@435: class CodeBlob; never@2868: class FrameValues; bobv@2036: class vframeArray; duke@435: duke@435: duke@435: // A frame represents a physical stack frame (an activation). Frames duke@435: // can be C or Java frames, and the Java frames can be interpreted or duke@435: // compiled. In contrast, vframes represent source-level activations, duke@435: // so that one physical frame can correspond to multiple source level duke@435: // frames because of inlining. duke@435: duke@435: class frame VALUE_OBJ_CLASS_SPEC { duke@435: private: duke@435: // Instance variables: duke@435: intptr_t* _sp; // stack pointer (from Thread::last_Java_sp) duke@435: address _pc; // program counter (the next instruction after the call) duke@435: duke@435: CodeBlob* _cb; // CodeBlob that "owns" pc duke@435: enum deopt_state { duke@435: not_deoptimized, duke@435: is_deoptimized, duke@435: unknown duke@435: }; duke@435: duke@435: deopt_state _deopt_state; duke@435: duke@435: public: duke@435: // Constructors duke@435: frame(); duke@435: simonis@7553: #ifndef PRODUCT simonis@7553: // This is a generic constructor which is only used by pns() in debug.cpp. simonis@7553: // pns (i.e. print native stack) uses this constructor to create a starting simonis@7553: // frame for stack walking. The implementation of this constructor is platform simonis@7553: // dependent (i.e. SPARC doesn't need an 'fp' argument an will ignore it) but simonis@7553: // we want to keep the signature generic because pns() is shared code. simonis@7553: frame(void* sp, void* fp, void* pc); simonis@7553: #endif simonis@7553: duke@435: // Accessors duke@435: duke@435: // pc: Returns the pc at which this frame will continue normally. duke@435: // It must point at the beginning of the next instruction to execute. duke@435: address pc() const { return _pc; } duke@435: duke@435: // This returns the pc that if you were in the debugger you'd see. Not duke@435: // the idealized value in the frame object. This undoes the magic conversion duke@435: // that happens for deoptimized frames. In addition it makes the value the duke@435: // hardware would want to see in the native frame. The only user (at this point) duke@435: // is deoptimization. It likely no one else should ever use it. duke@435: address raw_pc() const; duke@435: duke@435: void set_pc( address newpc ); duke@435: duke@435: intptr_t* sp() const { return _sp; } duke@435: void set_sp( intptr_t* newsp ) { _sp = newsp; } duke@435: duke@435: duke@435: CodeBlob* cb() const { return _cb; } duke@435: duke@435: // patching operations duke@435: void patch_pc(Thread* thread, address pc); duke@435: duke@435: // Every frame needs to return a unique id which distinguishes it from all other frames. duke@435: // For sparc and ia32 use sp. ia64 can have memory frames that are empty so multiple frames duke@435: // will have identical sp values. For ia64 the bsp (fp) value will serve. No real frame duke@435: // should have an id() of NULL so it is a distinguishing value for an unmatchable frame. duke@435: // We also have relationals which allow comparing a frame to anoth frame's id() allow duke@435: // us to distinguish younger (more recent activation) from older (less recent activations) duke@435: // A NULL id is only valid when comparing for equality. duke@435: duke@435: intptr_t* id(void) const; duke@435: bool is_younger(intptr_t* id) const; duke@435: bool is_older(intptr_t* id) const; duke@435: duke@435: // testers duke@435: duke@435: // Compares for strict equality. Rarely used or needed. duke@435: // It can return a different result than f1.id() == f2.id() duke@435: bool equal(frame other) const; duke@435: duke@435: // type testers duke@435: bool is_interpreted_frame() const; duke@435: bool is_java_frame() const; duke@435: bool is_entry_frame() const; // Java frame called from C? sla@5237: bool is_stub_frame() const; twisti@3969: bool is_ignored_frame() const; duke@435: bool is_native_frame() const; duke@435: bool is_runtime_frame() const; duke@435: bool is_compiled_frame() const; duke@435: bool is_safepoint_blob_frame() const; duke@435: bool is_deoptimized_frame() const; duke@435: duke@435: // testers duke@435: bool is_first_frame() const; // oldest frame? (has no sender) duke@435: bool is_first_java_frame() const; // same for Java frame duke@435: sgoldman@542: bool is_interpreted_frame_valid(JavaThread* thread) const; // performs sanity checks on interpreted frames. duke@435: duke@435: // tells whether this frame is marked for deoptimization duke@435: bool should_be_deoptimized() const; duke@435: duke@435: // tells whether this frame can be deoptimized duke@435: bool can_be_deoptimized() const; duke@435: duke@435: // returns the frame size in stack slots cfang@1228: int frame_size(RegisterMap* map) const; duke@435: duke@435: // returns the sending frame duke@435: frame sender(RegisterMap* map) const; duke@435: duke@435: // for Profiling - acting on another frame. walks sender frames duke@435: // if valid. duke@435: frame profile_find_Java_sender_frame(JavaThread *thread); duke@435: bool safe_for_sender(JavaThread *thread); duke@435: duke@435: // returns the sender, but skips conversion frames duke@435: frame real_sender(RegisterMap* map) const; duke@435: duke@435: // returns the the sending Java frame, skipping any intermediate C frames duke@435: // NB: receiver must not be first frame duke@435: frame java_sender() const; duke@435: duke@435: private: duke@435: // Helper methods for better factored code in frame::sender duke@435: frame sender_for_compiled_frame(RegisterMap* map) const; duke@435: frame sender_for_entry_frame(RegisterMap* map) const; duke@435: frame sender_for_interpreter_frame(RegisterMap* map) const; duke@435: frame sender_for_native_frame(RegisterMap* map) const; duke@435: duke@435: // All frames: duke@435: duke@435: // A low-level interface for vframes: duke@435: duke@435: public: duke@435: duke@435: intptr_t* addr_at(int index) const { return &fp()[index]; } duke@435: intptr_t at(int index) const { return *addr_at(index); } duke@435: duke@435: // accessors for locals duke@435: oop obj_at(int offset) const { return *obj_at_addr(offset); } duke@435: void obj_at_put(int offset, oop value) { *obj_at_addr(offset) = value; } duke@435: duke@435: jint int_at(int offset) const { return *int_at_addr(offset); } duke@435: void int_at_put(int offset, jint value) { *int_at_addr(offset) = value; } duke@435: duke@435: oop* obj_at_addr(int offset) const { return (oop*) addr_at(offset); } duke@435: coleenp@4037: oop* adjusted_obj_at_addr(Method* method, int index) { return obj_at_addr(adjust_offset(method, index)); } duke@435: duke@435: private: duke@435: jint* int_at_addr(int offset) const { return (jint*) addr_at(offset); } duke@435: duke@435: public: duke@435: // Link (i.e., the pointer to the previous frame) duke@435: intptr_t* link() const; duke@435: void set_link(intptr_t* addr); duke@435: duke@435: // Return address duke@435: address sender_pc() const; duke@435: duke@435: // Support for deoptimization never@2082: void deoptimize(JavaThread* thread); duke@435: duke@435: // The frame's original SP, before any extension by an interpreted callee; duke@435: // used for packing debug info into vframeArray objects and vframeArray lookup. duke@435: intptr_t* unextended_sp() const; duke@435: duke@435: // returns the stack pointer of the calling frame duke@435: intptr_t* sender_sp() const; duke@435: bdelsart@3433: // Returns the real 'frame pointer' for the current frame. bdelsart@3433: // This is the value expected by the platform ABI when it defines a bdelsart@3433: // frame pointer register. It may differ from the effective value of bdelsart@3433: // the FP register when that register is used in the JVM for other bdelsart@3433: // purposes (like compiled frames on some platforms). bdelsart@3433: // On other platforms, it is defined so that the stack area used by bdelsart@3433: // this frame goes from real_fp() to sp(). bdelsart@3433: intptr_t* real_fp() const; bdelsart@3433: bdelsart@3130: // Deoptimization info, if needed (platform dependent). bdelsart@3130: // Stored in the initial_info field of the unroll info, to be used by bdelsart@3130: // the platform dependent deoptimization blobs. bdelsart@3130: intptr_t *initial_deoptimization_info(); duke@435: duke@435: // Interpreter frames: duke@435: duke@435: private: duke@435: intptr_t** interpreter_frame_locals_addr() const; duke@435: intptr_t* interpreter_frame_bcx_addr() const; duke@435: intptr_t* interpreter_frame_mdx_addr() const; duke@435: duke@435: public: duke@435: // Locals duke@435: duke@435: // The _at version returns a pointer because the address is used for GC. duke@435: intptr_t* interpreter_frame_local_at(int index) const; duke@435: duke@435: void interpreter_frame_set_locals(intptr_t* locs); duke@435: duke@435: // byte code index/pointer (use these functions for unchecked frame access only!) duke@435: intptr_t interpreter_frame_bcx() const { return *interpreter_frame_bcx_addr(); } duke@435: void interpreter_frame_set_bcx(intptr_t bcx); duke@435: duke@435: // byte code index duke@435: jint interpreter_frame_bci() const; duke@435: void interpreter_frame_set_bci(jint bci); duke@435: duke@435: // byte code pointer duke@435: address interpreter_frame_bcp() const; duke@435: void interpreter_frame_set_bcp(address bcp); duke@435: duke@435: // Unchecked access to the method data index/pointer. duke@435: // Only use this if you know what you are doing. duke@435: intptr_t interpreter_frame_mdx() const { return *interpreter_frame_mdx_addr(); } duke@435: void interpreter_frame_set_mdx(intptr_t mdx); duke@435: duke@435: // method data pointer duke@435: address interpreter_frame_mdp() const; duke@435: void interpreter_frame_set_mdp(address dp); duke@435: duke@435: // Find receiver out of caller's (compiled) argument list duke@435: oop retrieve_receiver(RegisterMap *reg_map); duke@435: duke@435: // Return the monitor owner and BasicLock for compiled synchronized duke@435: // native methods so that biased locking can revoke the receiver's kamg@2361: // bias if necessary. This is also used by JVMTI's GetLocalInstance method kamg@2361: // (via VM_GetReceiver) to retrieve the receiver from a native wrapper frame. kamg@2361: BasicLock* get_native_monitor(); kamg@2361: oop get_native_receiver(); duke@435: duke@435: // Find receiver for an invoke when arguments are just pushed on stack (i.e., callee stack-frame is duke@435: // not setup) coleenp@2497: oop interpreter_callee_receiver(Symbol* signature) { return *interpreter_callee_receiver_addr(signature); } duke@435: duke@435: coleenp@2497: oop* interpreter_callee_receiver_addr(Symbol* signature); duke@435: duke@435: duke@435: // expression stack (may go up or down, direction == 1 or -1) duke@435: public: duke@435: intptr_t* interpreter_frame_expression_stack() const; duke@435: static jint interpreter_frame_expression_stack_direction(); duke@435: duke@435: // The _at version returns a pointer because the address is used for GC. duke@435: intptr_t* interpreter_frame_expression_stack_at(jint offset) const; duke@435: duke@435: // top of expression stack duke@435: intptr_t* interpreter_frame_tos_at(jint offset) const; duke@435: intptr_t* interpreter_frame_tos_address() const; duke@435: duke@435: duke@435: jint interpreter_frame_expression_stack_size() const; duke@435: duke@435: intptr_t* interpreter_frame_sender_sp() const; duke@435: duke@435: #ifndef CC_INTERP duke@435: // template based interpreter deoptimization support duke@435: void set_interpreter_frame_sender_sp(intptr_t* sender_sp); duke@435: void interpreter_frame_set_monitor_end(BasicObjectLock* value); duke@435: #endif // CC_INTERP duke@435: goetz@6521: // Address of the temp oop in the frame. Needed as GC root. goetz@6521: oop* interpreter_frame_temp_oop_addr() const; goetz@6521: duke@435: // BasicObjectLocks: duke@435: // duke@435: // interpreter_frame_monitor_begin is higher in memory than interpreter_frame_monitor_end duke@435: // Interpreter_frame_monitor_begin points to one element beyond the oldest one, duke@435: // interpreter_frame_monitor_end points to the youngest one, or if there are none, duke@435: // it points to one beyond where the first element will be. duke@435: // interpreter_frame_monitor_size reports the allocation size of a monitor in the interpreter stack. duke@435: // this value is >= BasicObjectLock::size(), and may be rounded up duke@435: duke@435: BasicObjectLock* interpreter_frame_monitor_begin() const; duke@435: BasicObjectLock* interpreter_frame_monitor_end() const; duke@435: BasicObjectLock* next_monitor_in_interpreter_frame(BasicObjectLock* current) const; duke@435: BasicObjectLock* previous_monitor_in_interpreter_frame(BasicObjectLock* current) const; duke@435: static int interpreter_frame_monitor_size(); duke@435: duke@435: void interpreter_frame_verify_monitor(BasicObjectLock* value) const; duke@435: duke@435: // Tells whether the current interpreter_frame frame pointer duke@435: // corresponds to the old compiled/deoptimized fp duke@435: // The receiver used to be a top level frame duke@435: bool interpreter_frame_equals_unpacked_fp(intptr_t* fp); duke@435: duke@435: // Return/result value from this interpreter frame duke@435: // If the method return type is T_OBJECT or T_ARRAY populates oop_result duke@435: // For other (non-T_VOID) the appropriate field in the jvalue is populated duke@435: // with the result value. duke@435: // Should only be called when at method exit when the method is not duke@435: // exiting due to an exception. duke@435: BasicType interpreter_frame_result(oop* oop_result, jvalue* value_result); duke@435: duke@435: public: duke@435: // Method & constant pool cache coleenp@4037: Method* interpreter_frame_method() const; coleenp@4037: void interpreter_frame_set_method(Method* method); coleenp@4037: Method** interpreter_frame_method_addr() const; coleenp@4037: ConstantPoolCache** interpreter_frame_cache_addr() const; duke@435: duke@435: public: duke@435: // Entry frames rbackman@5419: JavaCallWrapper* entry_frame_call_wrapper() const { return *entry_frame_call_wrapper_addr(); } rbackman@5419: JavaCallWrapper* entry_frame_call_wrapper_if_safe(JavaThread* thread) const; rbackman@5419: JavaCallWrapper** entry_frame_call_wrapper_addr() const; duke@435: intptr_t* entry_frame_argument_at(int offset) const; duke@435: duke@435: // tells whether there is another chunk of Delta stack above duke@435: bool entry_frame_is_first() const; duke@435: duke@435: // Compiled frames: duke@435: duke@435: public: duke@435: // Given the index of a local, and the number of argument words duke@435: // in this stack frame, tell which word of the stack frame to find duke@435: // the local in. Arguments are stored above the ofp/rpc pair, duke@435: // while other locals are stored below it. duke@435: // Since monitors (BasicLock blocks) are also assigned indexes, duke@435: // but may have different storage requirements, their presence duke@435: // can also affect the calculation of offsets. duke@435: static int local_offset_for_compiler(int local_index, int nof_args, int max_nof_locals, int max_nof_monitors); duke@435: duke@435: // Given the index of a monitor, etc., tell which word of the duke@435: // stack frame contains the start of the BasicLock block. duke@435: // Note that the local index by convention is the __higher__ duke@435: // of the two indexes allocated to the block. duke@435: static int monitor_offset_for_compiler(int local_index, int nof_args, int max_nof_locals, int max_nof_monitors); duke@435: duke@435: // Tell the smallest value that local_offset_for_compiler will attain. duke@435: // This is used to help determine how much stack frame to allocate. duke@435: static int min_local_offset_for_compiler(int nof_args, int max_nof_locals, int max_nof_monitors); duke@435: duke@435: // Tells if this register must be spilled during a call. duke@435: // On Intel, all registers are smashed by calls. duke@435: static bool volatile_across_calls(Register reg); duke@435: duke@435: duke@435: // Safepoints duke@435: duke@435: public: duke@435: oop saved_oop_result(RegisterMap* map) const; duke@435: void set_saved_oop_result(RegisterMap* map, oop obj); duke@435: duke@435: // For debugging duke@435: private: duke@435: const char* print_name() const; duke@435: never@2868: void describe_pd(FrameValues& values, int frame_no); never@2868: duke@435: public: duke@435: void print_value() const { print_value_on(tty,NULL); } duke@435: void print_value_on(outputStream* st, JavaThread *thread) const; duke@435: void print_on(outputStream* st) const; duke@435: void interpreter_frame_print_on(outputStream* st) const; duke@435: void print_on_error(outputStream* st, char* buf, int buflen, bool verbose = false) const; iklam@5667: static void print_C_frame(outputStream* st, char* buf, int buflen, address pc); duke@435: never@2868: // Add annotated descriptions of memory locations belonging to this frame to values never@2868: void describe(FrameValues& values, int frame_no); never@2868: duke@435: // Conversion from an VMReg to physical stack location duke@435: oop* oopmapreg_to_location(VMReg reg, const RegisterMap* regmap) const; duke@435: duke@435: // Oops-do's roland@5222: void oops_compiled_arguments_do(Symbol* signature, bool has_receiver, bool has_appendix, const RegisterMap* reg_map, OopClosure* f); stefank@6973: void oops_interpreted_do(OopClosure* f, CLDClosure* cld_f, const RegisterMap* map, bool query_oop_map_cache = true); duke@435: duke@435: private: coleenp@2497: void oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f); duke@435: duke@435: // Iteration of oops stefank@6973: void oops_do_internal(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache); duke@435: void oops_entry_do(OopClosure* f, const RegisterMap* map); jrose@1424: void oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* map); coleenp@4037: int adjust_offset(Method* method, int index); // helper for above fn duke@435: public: duke@435: // Memory management stefank@6973: void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map) { oops_do_internal(f, cld_f, cf, map, true); } jrose@1424: void nmethods_do(CodeBlobClosure* cf); duke@435: coleenp@4037: // RedefineClasses support for finding live interpreted methods on the stack coleenp@4037: void metadata_do(void f(Metadata*)); coleenp@4037: duke@435: void gc_prologue(); duke@435: void gc_epilogue(); duke@435: void pd_gc_epilog(); duke@435: duke@435: # ifdef ENABLE_ZAP_DEAD_LOCALS duke@435: private: duke@435: class CheckValueClosure: public OopClosure { coleenp@548: public: coleenp@548: void do_oop(oop* p); coleenp@548: void do_oop(narrowOop* p) { ShouldNotReachHere(); } duke@435: }; duke@435: static CheckValueClosure _check_value; duke@435: duke@435: class CheckOopClosure: public OopClosure { coleenp@548: public: coleenp@548: void do_oop(oop* p); coleenp@548: void do_oop(narrowOop* p) { ShouldNotReachHere(); } duke@435: }; duke@435: static CheckOopClosure _check_oop; duke@435: duke@435: static void check_derived_oop(oop* base, oop* derived); duke@435: duke@435: class ZapDeadClosure: public OopClosure { coleenp@548: public: coleenp@548: void do_oop(oop* p); coleenp@548: void do_oop(narrowOop* p) { ShouldNotReachHere(); } duke@435: }; duke@435: static ZapDeadClosure _zap_dead; duke@435: duke@435: public: duke@435: // Zapping duke@435: void zap_dead_locals (JavaThread* thread, const RegisterMap* map); duke@435: void zap_dead_interpreted_locals(JavaThread* thread, const RegisterMap* map); duke@435: void zap_dead_compiled_locals (JavaThread* thread, const RegisterMap* map); duke@435: void zap_dead_entry_locals (JavaThread* thread, const RegisterMap* map); duke@435: void zap_dead_deoptimized_locals(JavaThread* thread, const RegisterMap* map); duke@435: # endif duke@435: // Verification duke@435: void verify(const RegisterMap* map); duke@435: static bool verify_return_pc(address x); duke@435: static bool is_bci(intptr_t bcx); duke@435: // Usage: duke@435: // assert(frame::verify_return_pc(return_address), "must be a return pc"); duke@435: duke@435: int pd_oop_map_offset_adjustment() const; duke@435: stefank@2314: #ifdef TARGET_ARCH_x86 stefank@2314: # include "frame_x86.hpp" stefank@2314: #endif stefank@2314: #ifdef TARGET_ARCH_sparc stefank@2314: # include "frame_sparc.hpp" stefank@2314: #endif stefank@2314: #ifdef TARGET_ARCH_zero stefank@2314: # include "frame_zero.hpp" stefank@2314: #endif bobv@2508: #ifdef TARGET_ARCH_arm bobv@2508: # include "frame_arm.hpp" bobv@2508: #endif bobv@2508: #ifdef TARGET_ARCH_ppc bobv@2508: # include "frame_ppc.hpp" bobv@2508: #endif stefank@2314: duke@435: }; duke@435: bdelsart@3451: #ifndef PRODUCT never@2868: // A simple class to describe a location on the stack never@2868: class FrameValue VALUE_OBJ_CLASS_SPEC { never@2868: public: never@2868: intptr_t* location; never@2868: char* description; never@2868: int owner; never@2868: int priority; never@2868: }; never@2868: never@2868: never@2868: // A collection of described stack values that can print a symbolic never@2868: // description of the stack memory. Interpreter frame values can be never@2868: // in the caller frames so all the values are collected first and then never@2868: // sorted before being printed. never@2868: class FrameValues { never@2868: private: never@2868: GrowableArray _values; never@2868: never@2868: static int compare(FrameValue* a, FrameValue* b) { never@2868: if (a->location == b->location) { never@2868: return a->priority - b->priority; never@2868: } never@2868: return a->location - b->location; never@2868: } never@2868: never@2868: public: never@2868: // Used by frame functions to describe locations. never@2868: void describe(int owner, intptr_t* location, const char* description, int priority = 0); never@2868: bdelsart@3451: #ifdef ASSERT never@2897: void validate(); bdelsart@3451: #endif twisti@3238: void print(JavaThread* thread); never@2868: }; never@2868: never@2868: #endif duke@435: duke@435: // duke@435: // StackFrameStream iterates through the frames of a thread starting from duke@435: // top most frame. It automatically takes care of updating the location of duke@435: // all (callee-saved) registers. Notice: If a thread is stopped at duke@435: // a safepoint, all registers are saved, not only the callee-saved ones. duke@435: // duke@435: // Use: duke@435: // duke@435: // for(StackFrameStream fst(thread); !fst.is_done(); fst.next()) { duke@435: // ... duke@435: // } duke@435: // duke@435: class StackFrameStream : public StackObj { duke@435: private: duke@435: frame _fr; duke@435: RegisterMap _reg_map; duke@435: bool _is_done; duke@435: public: duke@435: StackFrameStream(JavaThread *thread, bool update = true); duke@435: duke@435: // Iteration duke@435: bool is_done() { return (_is_done) ? true : (_is_done = _fr.is_first_frame(), false); } duke@435: void next() { if (!_is_done) _fr = _fr.sender(&_reg_map); } duke@435: duke@435: // Query duke@435: frame *current() { return &_fr; } duke@435: RegisterMap* register_map() { return &_reg_map; } duke@435: }; stefank@2314: stefank@2314: #endif // SHARE_VM_RUNTIME_FRAME_HPP