/* Sun-$Revision: 23.15 $ */ /* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University. See the LICENSE file for license information. */ # pragma interface // vframes are "virtual" frames (as opposed to physical stack frames) # if defined(FAST_COMPILER) || defined(SIC_COMPILER) class compiled_vframe; class nvframe; class dummy_vframe; typedef void (*vfValueDoFn)(compiled_vframe* vf1, NameDesc* n1, compiled_vframe* vf2, NameDesc* n2); # endif class abstract_vframe: public ResourceObj { unknown: frame* fr; unknown: # if defined(FAST_COMPILER) || defined(SIC_COMPILER) compiled_vframe* as_compiled() { if (this == NULL) return NULL; assert_compiled(); return (compiled_vframe*)this; } # endif interpreted_vframe* as_interpreted() { if (this == NULL) return NULL; assert_interpreted(); return (interpreted_vframe*)this; } # if defined(FAST_COMPILER) || defined(SIC_COMPILER) nvframe* as_n() { if (this == NULL) return NULL; assert_n(); return (nvframe*)this; } # endif // defined(FAST_COMPILER) || defined(SIC_COMPILER) abstract_vframe* as_abstract() { return (abstract_vframe*) this; } void assert_compiled() { assert(is_compiled(), "must be compiled vframe"); } void assert_interpreted() { assert(is_interpreted(), "must be interpreted vframe"); } void assert_n() { assert(is_n(), "must be nvframe"); } virtual bool is_n() { return false; }; virtual bool is_compiled() = 0; bool is_interpreted() {return !is_compiled();} protected: virtual abstract_vframe* get_sender(bool skipCFrames); public: virtual bool EQ(abstract_vframe *f) { return this == f || fr == f->fr; } public: virtual smiOop descOffset() = 0; virtual int32 real_bci() = 0; int32 bci(); bool is_prologue(); public: abstract_vframe* sendee(abstract_vframe* lastSelfVf = NULL);// vframe below the receiver; SLOW! virtual abstract_vframe* parent(); abstract_vframe* sender() { return get_sender(true); } abstract_vframe* immediateSender() { return get_sender(false); } virtual abstract_vframe* home(); virtual abstract_vframe* top(); // top vframe in same frame virtual bool is_top() = 0; virtual oop selector() = 0; virtual oop delegatee() = 0; virtual oop method() = 0; virtual oop methodHolder_or_map() = 0; virtual bool isDummy() { return false; } virtual int32 scopeID() = 0; virtual bool is_primCall() = 0; // currently executing a primitive call? virtual bool is_uncommonTrap() = 0; bool is_first_self_vframe() { return is_top() && fr->is_first_self_frame(); } virtual bool isCallerOf(ScopeDesc* callee) = 0; virtual oop get_slot(slotDesc* s) = 0; virtual void set_slot(slotDesc* s, oop x) = 0; virtual void get_expr_stack(oop*& stack, smi& len, bool badOopForUnknown = false) = 0; virtual oop self() = 0; virtual oop receiver() = 0; virtual oop block() = 0; virtual oop methodHolder_object() = 0; virtual void createBlocks(abstract_vframe* calleeOrNull, OopOopTable*& blockValues) = 0; virtual void enumerate_references(enumeration *e); void enumerate_families(enumeration *e); virtual bool print_frame(fint curFrame = 0); void print_slot(slotDesc* s, oop meth); void print() { print_frame(); } protected: virtual void print_code(fint curFrame) = 0; virtual void print_contents(); }; class interpreted_vframe: public abstract_vframe { public: interpreter* interp() { return fr->get_interpreter(); } bool is_compiled() { return false; } interpreted_vframe(frame* f); interpreted_vframe() {fr = NULL;} public: smiOop descOffset() { return smiOop_zero; } int32 real_bci(); abstract_vframe* parent(); bool is_top() { return true; } oop selector(); oop delegatee(); oop method(); oop methodHolder_or_map(); int32 scopeID() { return BLOCK_PROTO_DESC->value(); } bool is_primCall(); // currently executing a primitive call? bool is_uncommonTrap() { return false; } bool isCallerOf(ScopeDesc* callee) { Unused(callee); return false; } oop get_slot(slotDesc* s); void set_slot(slotDesc* s, oop x); void get_expr_stack(oop*& stack, smi& len, bool badOopForUnknown = false); oop self(); oop receiver(); oop block(); oop methodHolder_object(); void createBlocks(abstract_vframe* calleeOrNull, OopOopTable*& blockValues); void enumerate_references(enumeration *e); protected: void print_code(fint curFrame) {Unused(curFrame);} }; # if defined(FAST_COMPILER) || defined(SIC_COMPILER) class compiled_vframe: public abstract_vframe { unknown: nmethod* code; ScopeDesc* desc; RegisterLocator* rl; protected: int32 _bci; private: void set_rl(RegisterLocator* _rl); public: bool is_compiled() { return true; } RegisterLocator* reg_loc() { return rl; } void fix_frame(frame* f); unknown: void codeFromFrame() { code = fr->code(); } void descFromCode() { PcDesc* d = code->containingPcDesc(fr->return_addr()); desc = d->containingDesc(code); _bci = d->byteCode; } int32 bciFromDesc(ScopeDesc* dc); void descFromOffset(smiOop offset) { desc = code->scopes->at(offset); _bci = bciFromDesc(desc); } void rlFromFrame(); // constructors compiled_vframe() { fr = NULL, code = NULL, desc = NULL, rl = NULL, _bci = 0; } compiled_vframe(frame* f, nmethod* c, ScopeDesc* d, fint b, RegisterLocator* _r) { fr = f; code = c; desc = d; _bci = b; set_rl( _r); } compiled_vframe(frame* f, nmethod* c, ScopeDesc* d, fint b) { fr = f; code = c; desc = d; _bci = b; rlFromFrame(); } compiled_vframe(frame* f, RegisterLocator* _rl) { fr = f; codeFromFrame(); descFromCode(); set_rl(_rl); } compiled_vframe(frame* f) { fr = f; codeFromFrame(); descFromCode(); rlFromFrame(); } compiled_vframe(frame* f, smiOop offset, RegisterLocator* r) { fr = f; codeFromFrame(); descFromOffset(offset); set_rl(r); } compiled_vframe(frame* f, smiOop offset) { fr = f; codeFromFrame(); descFromOffset(offset); rlFromFrame(); } compiled_vframe(frame* f, nmethod* c, smiOop offset) { fr = f; code = c; descFromOffset(offset); rlFromFrame(); } bool EQ(abstract_vframe *f) { return this == f || fr == f->fr && desc->is_equal(f->as_compiled()->desc); } protected: abstract_vframe* get_sender(bool skipCFrames); public: int32 real_bci() { return _bci; } smiOop descOffset() { return as_smiOop(code->scopes->offsetTo(desc)); } abstract_vframe* parent(); oop selector() { return desc->key.selector; } oop delegatee() { return desc->key.delegatee; } oop method() { return desc->method(); } oop methodHolder_or_map() { return desc->methodHolder_or_map(); } int32 scopeID(); bool is_primCall(); // currently executing a primitive call? bool is_uncommonTrap(); // currently executing an uncommon trap? bool is_top(); bool isCallerOf(ScopeDesc* callee); // only for compiled_vframe's NameDesc* get_name_desc(slotDesc* s, bool canFail = false); NameDesc* get_self_name(); NameDesc* get_cachedSelf_name(); NameDesc* get_receiver_name(); NameDesc* get_block_name(); NameDesc* get_cachedBlock_name(); int32 register_offset(Location r); virtual oop* register_contents_addr(Location r); virtual oop* register_contents_secondary_addr(Location r); # if defined(SIC_COMPILER) protected: oop* special_register_contents_addr(Location r); public: # endif oop register_contents(Location r) { return *register_contents_addr(r); } public: oop get_contents(NameDesc* n, bool cloneMemoizedBlocks = true, bool cloneEliminatedBlocks = false); protected: void get_search_locations_for_liveness_check(NameDesc* n, frame*& fr_to_search, RegisterLocator*& rl_to_search); public: void set_contents(NameDesc* n, oop p); oop get_slot(slotDesc* s); // this one is just for compiled frames oop get_slot2(slotDesc* s, bool clone1, bool clone2); void set_slot(slotDesc* s, oop x); void get_expr_stack(oop*& stack, smi& len, bool badOopForUnknown = false); // only for compiled void get_exprStackInfo(compiled_vframe* calleeOrNull, compiled_vframe**& vfs, NameDesc**& nds, smi& len, bool includeArgs = true); protected: // helpers for get_exprStackInfo void get_exprStackInfo_outgoing_args( methodMap* mm, compiled_vframe* calleeOrNull, compiled_vframe** vfs, NameDesc** nds, fint i, smi len, IntListElem* e2 ); void get_outgoing_arg_info_from_dummy_callee( bool isReceiverExplicit, compiled_vframe* calleeOrNull, compiled_vframe** vfs, NameDesc** nds, fint& i, smi len, oop sel ); NameDesc* make_up_fake_name_desc_for_outgoing_receiver(); void get_outgoing_arg_info_no_sendee( compiled_vframe** vfs, NameDesc** nds, fint& i, smi len, IntListElem* e2 ); void get_outgoing_arg_info_from_sendee( bool isReceiverExplicit, compiled_vframe* calleeOrNull, compiled_vframe** vfs, NameDesc** nds, fint& i ); public: oop self() { return get_contents(get_self_name()); } oop receiver() { return get_contents(get_receiver_name()); } oop block() { return get_contents(get_block_name()); } oop methodHolder_object() { if (desc->isDeadBlockScope()) return self(); // methodHolder_or_map() would fail -- dmu 6/99 oop mh = methodHolder_or_map(); if (mh->is_map()) { // method holder is the same as self return self(); } else { return mh; } } // conversion functions // XXXXX not done yet for interp // (internal) oop copyValueFrom( compiled_vframe* toVF, NameDesc* fromNd, frame* oldBlockHome, OopOopTable* blockValues); void copyValueTo( NameDesc* n, oop x ); void copyValue(NameDesc* n, compiled_vframe* vf2, NameDesc* n2, frame* f, OopOopTable* blockValues); void valuesDo( compiled_vframe* vf, compiled_vframe* calleeOrNull, vfValueDoFn fn, bool wasInInterruptCheck); void createBlock(NameDesc* n, OopOopTable*& blockValues); // (external) void copyValuesFrom (compiled_vframe* vf, compiled_vframe* callee, frame* blockHome, OopOopTable*& blockValues, bool wasInInterruptCheck); void copyOutgoingArgs(compiled_vframe* vf, frame* oldBlockHome, OopOopTable*& blockValues, bool lastOnly); protected: Location location_of_saved_outgoing_arg(fint argNo); void copy_outgoing_arg( fint argNo, // -1 for rcvr NameDesc* nd2, // for src caller's expr stack elem compiled_vframe* vf, // src caller's vframe dummy_vframe* dummy, // old callee NameDesc* nd, // dst nameDesc frame* oldBlkHome, OopOopTable* blkValues); public: void createBlocks(abstract_vframe* calleeOrNull, OopOopTable*& blockValues); void enumerate_references(enumeration *e); bool print_frame(fint curFrame = 0); protected: void print_code(fint curFrame); }; // used to represent the callee of the actual last vframe (to get at out- // going args)...somewhat hacky - only get_contents is guaranteed to work struct dummy_vframe : compiled_vframe { friend dummy_vframe* new_dummy_vframe(frame* sender); dummy_vframe(frame* f, nmethod* c, ScopeDesc* d, fint b) : compiled_vframe(f, c, d, b) {} oop* register_contents_addr(Location r); bool isDummy() { return true; } void print(); }; # endif // defined(FAST_COMPILER) || defined(SIC_COMPILER) extern abstract_vframe* new_vframe(frame* f, RegisterLocator* _rl = NULL); extern abstract_vframe* new_vframe(frame* f, smiOop offset, RegisterLocator* _rl = NULL);