duke@435: /* duke@435: * Copyright 1997-2007 Sun Microsystems, Inc. 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: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: typedef class BytecodeInterpreter* interpreterState; duke@435: duke@435: class CodeBlob; 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: 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? 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 duke@435: int frame_size() 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: duke@435: oop* adjusted_obj_at_addr(methodOop 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 duke@435: void deoptimize(JavaThread* thread, bool thread_is_known_safe = false); 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: 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: // Tags for TaggedStackInterpreter duke@435: enum Tag { duke@435: TagValue = 0, // Important: must be zero to use G0 on sparc. duke@435: TagReference = 0x555, // Reference type - is an oop that needs gc. duke@435: TagCategory2 = 0x666 // Only used internally by interpreter duke@435: // and not written to the java stack. duke@435: // The values above are chosen so that misuse causes a crash duke@435: // with a recognizable value. duke@435: }; duke@435: duke@435: static Tag tag_for_basic_type(BasicType typ) { duke@435: return (typ == T_OBJECT ? TagReference : TagValue); duke@435: } duke@435: 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: Tag interpreter_frame_local_tag(int index) const; duke@435: void interpreter_frame_set_local_tag(int index, Tag tag) 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 duke@435: // bias if necessary. Takes optional nmethod for this frame as duke@435: // argument to avoid performing repeated lookups in code cache. duke@435: BasicLock* compiled_synchronized_native_monitor (nmethod* nm = NULL); duke@435: oop compiled_synchronized_native_monitor_owner(nmethod* nm = NULL); 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) duke@435: oop interpreter_callee_receiver(symbolHandle signature) { return *interpreter_callee_receiver_addr(signature); } duke@435: duke@435: duke@435: oop *interpreter_callee_receiver_addr(symbolHandle 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: Tag interpreter_frame_expression_stack_tag(jint offset) const; duke@435: void interpreter_frame_set_expression_stack_tag(jint offset, Tag tag) 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: 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 duke@435: methodOop interpreter_frame_method() const; duke@435: void interpreter_frame_set_method(methodOop method); duke@435: methodOop* interpreter_frame_method_addr() const; duke@435: constantPoolCacheOop* interpreter_frame_cache_addr() const; duke@435: duke@435: public: duke@435: // Entry frames duke@435: JavaCallWrapper* entry_frame_call_wrapper() 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: 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; duke@435: 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 duke@435: void oops_compiled_arguments_do(symbolHandle signature, bool is_static, const RegisterMap* reg_map, OopClosure* f); duke@435: void oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool query_oop_map_cache = true); duke@435: duke@435: private: duke@435: void oops_interpreted_locals_do(OopClosure *f, duke@435: int max_locals, duke@435: InterpreterOopMap *mask); duke@435: void oops_interpreted_expressions_do(OopClosure *f, symbolHandle signature, duke@435: bool is_static, int max_stack, int max_locals, duke@435: InterpreterOopMap *mask); duke@435: void oops_interpreted_arguments_do(symbolHandle signature, bool is_static, OopClosure* f); duke@435: duke@435: // Iteration of oops duke@435: void oops_do_internal(OopClosure* f, RegisterMap* map, bool use_interpreter_oop_map_cache); duke@435: void oops_entry_do(OopClosure* f, const RegisterMap* map); duke@435: void oops_code_blob_do(OopClosure* f, const RegisterMap* map); duke@435: int adjust_offset(methodOop method, int index); // helper for above fn duke@435: // Iteration of nmethods duke@435: void nmethods_code_blob_do(); duke@435: public: duke@435: // Memory management duke@435: void oops_do(OopClosure* f, RegisterMap* map) { oops_do_internal(f, map, true); } duke@435: void nmethods_do(); duke@435: 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 { duke@435: public: void do_oop(oop* p); duke@435: }; duke@435: static CheckValueClosure _check_value; duke@435: duke@435: class CheckOopClosure: public OopClosure { duke@435: public: void do_oop(oop* p); 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 { duke@435: public: void do_oop(oop* p); 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: duke@435: # include "incls/_frame_pd.hpp.incl" duke@435: }; duke@435: 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: };