< prev index next >

src/hotspot/cpu/x86/frame_x86.inline.hpp

Print this page

        

*** 24,87 **** #ifndef CPU_X86_FRAME_X86_INLINE_HPP #define CPU_X86_FRAME_X86_INLINE_HPP #include "code/codeCache.hpp" #include "code/vmreg.inline.hpp" // Inline functions for Intel frames: // Constructors: inline frame::frame() { _pc = NULL; _sp = NULL; _unextended_sp = NULL; _fp = NULL; _cb = NULL; _deopt_state = unknown; } inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) { _sp = sp; _unextended_sp = sp; _fp = fp; _pc = pc; assert(pc != NULL, "no pc?"); ! _cb = CodeCache::find_blob(pc); adjust_unextended_sp(); address original_pc = CompiledMethod::get_deopt_original_pc(this); if (original_pc != NULL) { _pc = original_pc; _deopt_state = is_deoptimized; } else { _deopt_state = not_deoptimized; } } inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) { init(sp, fp, pc); } inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) { _sp = sp; _unextended_sp = unextended_sp; _fp = fp; _pc = pc; assert(pc != NULL, "no pc?"); ! _cb = CodeCache::find_blob(pc); adjust_unextended_sp(); address original_pc = CompiledMethod::get_deopt_original_pc(this); if (original_pc != NULL) { _pc = original_pc; assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc), "original PC must be in the main code section of the the compiled method (or must be immediately following it)"); _deopt_state = is_deoptimized; } else { ! if (_cb->is_deoptimization_stub()) { _deopt_state = is_deoptimized; } else { _deopt_state = not_deoptimized; } } --- 24,157 ---- #ifndef CPU_X86_FRAME_X86_INLINE_HPP #define CPU_X86_FRAME_X86_INLINE_HPP #include "code/codeCache.hpp" + #include "code/codeCache.inline.hpp" #include "code/vmreg.inline.hpp" + #include "compiler/oopMap.inline.hpp" + #include "runtime/sharedRuntime.hpp" // Inline functions for Intel frames: + class ContinuationCodeBlobLookup { + public: + enum { has_oopmap_lookup = true }; + + static CodeBlob* find_blob(address pc) { + CodeBlob* cb = CodeCache::find_blob_fast(pc); + /*Prefetch::read(cb, PrefetchScanIntervalInBytes); + Prefetch::read((void*)cb->is_compiled_addr(), PrefetchScanIntervalInBytes); + Prefetch::read((void*) ((CompiledMethod*) cb)->deopt_handler_begin_addr(), PrefetchScanIntervalInBytes);*/ + return cb; + } + + static CodeBlob* find_blob_and_oopmap(address pc, int& slot) { + return CodeCache::find_blob_and_oopmap(pc, slot); + } + }; + // Constructors: inline frame::frame() { _pc = NULL; _sp = NULL; _unextended_sp = NULL; _fp = NULL; _cb = NULL; _deopt_state = unknown; + _oop_map = NULL; } inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) { _sp = sp; _unextended_sp = sp; _fp = fp; _pc = pc; assert(pc != NULL, "no pc?"); ! _cb = CodeCache::find_blob_fast(pc); adjust_unextended_sp(); address original_pc = CompiledMethod::get_deopt_original_pc(this); if (original_pc != NULL) { _pc = original_pc; _deopt_state = is_deoptimized; } else { _deopt_state = not_deoptimized; } + + _oop_map = NULL; } inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) { init(sp, fp, pc); } + inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb) { + _sp = sp; + _unextended_sp = unextended_sp; + _fp = fp; + _pc = pc; + assert(pc != NULL, "no pc?"); + _cb = cb; + _oop_map = NULL; + setup(pc); + } + + inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb, const ImmutableOopMap* oop_map) { + _sp = sp; + _unextended_sp = unextended_sp; + _fp = fp; + _pc = pc; + assert(pc != NULL, "no pc?"); + _cb = cb; + _oop_map = oop_map; + setup(pc); + } + + inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb, const ImmutableOopMap* oop_map, bool dummy) { + _sp = sp; + _unextended_sp = unextended_sp; + _fp = fp; + _pc = pc; + assert(pc != NULL, "no pc?"); + _cb = cb; + _oop_map = oop_map; + _deopt_state = not_deoptimized; + #ifdef ASSERT + // The following assertion has been disabled because it would sometime trap for Continuation.run, which is not *in* a continuation + // and therefore does not clear the _cont_fastpath flag, but this is benign even in fast mode (see Freeze::setup_jump) + // if (cb != NULL) { + // setup(pc); + // assert(_pc == pc && _deopt_state == not_deoptimized, ""); + // } + #endif + } + inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) { _sp = sp; _unextended_sp = unextended_sp; _fp = fp; _pc = pc; assert(pc != NULL, "no pc?"); ! _cb = CodeCache::find_blob(pc); // TODO R find_blob_fast ! _oop_map = NULL; ! setup(pc); ! } ! ! inline void frame::setup(address pc) { adjust_unextended_sp(); + assert(_cb != NULL, "pc: " INTPTR_FORMAT, p2i(pc)); address original_pc = CompiledMethod::get_deopt_original_pc(this); if (original_pc != NULL) { _pc = original_pc; assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc), "original PC must be in the main code section of the the compiled method (or must be immediately following it)"); _deopt_state = is_deoptimized; } else { ! if (_cb == SharedRuntime::deopt_blob()) { _deopt_state = is_deoptimized; } else { _deopt_state = not_deoptimized; } }
*** 113,122 **** --- 183,205 ---- _pc = original_pc; _deopt_state = is_deoptimized; } else { _deopt_state = not_deoptimized; } + _oop_map = NULL; + } + + inline frame::frame(int sp, int ref_sp, intptr_t fp, address pc, CodeBlob* cb, bool deopt) { + _cont_sp._sp = sp; + _cont_sp._ref_sp = ref_sp; + _unextended_sp = NULL; + _fp = (intptr_t*)fp; + _pc = pc; + assert(pc != NULL, "no pc?"); + _cb = cb; + _deopt_state = deopt ? is_deoptimized : not_deoptimized; + _oop_map = NULL; } // Accessors inline bool frame::equal(frame other) const {
*** 141,150 **** --- 224,275 ---- inline intptr_t* frame::link() const { return (intptr_t*) *(intptr_t **)addr_at(link_offset); } inline intptr_t* frame::unextended_sp() const { return _unextended_sp; } + inline intptr_t* frame::real_fp() const { + if (_cb != NULL) { + // use the frame size if valid + int size = _cb->frame_size(); + if (size > 0) { + return unextended_sp() + size; + } + } + // else rely on fp() + assert(! is_compiled_frame(), "unknown compiled frame size"); + return fp(); + } + + // helper to update a map with callee-saved RBP + + template <typename RegisterMapT> + void frame::update_map_with_saved_link(RegisterMapT* map, intptr_t** link_addr) { + // The interpreter and compiler(s) always save EBP/RBP in a known + // location on entry. We must record where that location is + // so this if EBP/RBP was live on callout from c2 we can find + // the saved copy no matter what it called. + + // Since the interpreter always saves EBP/RBP if we record where it is then + // we don't have to always save EBP/RBP on entry and exit to c2 compiled + // code, on entry will be enough. + map->set_location(rbp->as_VMReg(), (address) link_addr); + #ifdef AMD64 + // this is weird "H" ought to be at a higher address however the + // oopMaps seems to have the "H" regs at the same address and the + // vanilla register. + // XXXX make this go away + if (true) { + map->set_location(rbp->as_VMReg()->next(), (address) link_addr); + } + #endif // AMD64 + } + + template <typename RegisterMapT> + intptr_t** frame::saved_link_address(const RegisterMapT* map) { + return (intptr_t**)map->location(rbp->as_VMReg()); + } + // Return address: inline address* frame::sender_pc_addr() const { return (address*) addr_at( return_addr_offset); } inline address frame::sender_pc() const { return *sender_pc_addr(); }
*** 238,243 **** --- 363,473 ---- guarantee(result_adr != NULL, "bad register save location"); *result_adr = obj; } + inline bool frame::is_interpreted_frame() const { + return Interpreter::contains(pc()); + } + + template <typename LOOKUP> + frame frame::frame_sender(RegisterMap* map) const { + // Default is we done have to follow them. The sender_for_xxx will + // update it accordingly + map->set_include_argument_oops(false); + + if (is_entry_frame()) return sender_for_entry_frame(map); + if (is_interpreted_frame()) return sender_for_interpreter_frame(map); + + assert(_cb == CodeCache::find_blob(pc()), "Must be the same"); + + if (_cb != NULL) { + return is_compiled_frame() ? sender_for_compiled_frame<LOOKUP, false>(map) : sender_for_compiled_frame<LOOKUP, true>(map); + } + // Must be native-compiled frame, i.e. the marshaling code for native + // methods that exists in the core system. + return frame(sender_sp(), link(), sender_pc()); + } + + //------------------------------------------------------------------------------ + // frame::sender_for_compiled_frame + template <typename LOOKUP, bool stub> + frame frame::sender_for_compiled_frame(RegisterMap* map) const { + assert(map != NULL, "map must be set"); + + if (map->in_cont()) { // already in an h-stack + return Continuation::sender_for_compiled_frame(*this, map); + } + + // frame owned by optimizing compiler + assert(_cb->frame_size() >= 0, "must have non-zero frame size"); + intptr_t* sender_sp = unextended_sp() + _cb->frame_size(); + + assert (sender_sp == real_fp(), "sender_sp: " INTPTR_FORMAT " real_fp: " INTPTR_FORMAT, p2i(sender_sp), p2i(real_fp())); + + // On Intel the return_address is always the word on the stack + address sender_pc = (address) *(sender_sp-1); + + // This is the saved value of EBP which may or may not really be an FP. + // It is only an FP if the sender is an interpreter frame (or C1?). + intptr_t** saved_fp_addr = (intptr_t**) (sender_sp - frame::sender_sp_offset); + + if (map->update_map()) { + // Tell GC to use argument oopmaps for some runtime stubs that need it. + // For C1, the runtime stub might not have oop maps, so set this flag + // outside of update_register_map. + if (stub) { // compiled frames do not use callee-saved registers + map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread())); + if (oop_map() != NULL) { + _oop_map->update_register_map(this, map); + } + } else { + assert (!_cb->caller_must_gc_arguments(map->thread()), ""); + assert (!map->include_argument_oops(), ""); + assert (oop_map() == NULL || OopMapStream(oop_map(), OopMapValue::callee_saved_value).is_done(), "callee-saved value in compiled frame"); + } + + // Since the prolog does the save and restore of EBP there is no oopmap + // for it so we must fill in its location as if there was an oopmap entry + // since if our caller was compiled code there could be live jvm state in it. + update_map_with_saved_link(map, saved_fp_addr); + } + + assert(sender_sp != sp(), "must have changed"); + + if (Continuation::is_return_barrier_entry(sender_pc)) { + if (map->walk_cont()) { // about to walk into an h-stack + return Continuation::top_frame(*this, map); + } else { + Continuation::fix_continuation_bottom_sender(map, *this, &sender_pc, &sender_sp); + } + } + + intptr_t* unextended_sp = sender_sp; + CodeBlob* sender_cb = LOOKUP::find_blob(sender_pc); + if (sender_cb != NULL) { + return frame(sender_sp, unextended_sp, *saved_fp_addr, sender_pc, sender_cb); // Continuation::fix_continuation_bottom_sender(*this, map, frame(sender_sp, unextended_sp, *saved_fp_addr, sender_pc, sender_cb)); + } + // tty->print_cr(">>>> NO CB:"); print_on(tty); + return frame(sender_sp, unextended_sp, *saved_fp_addr, sender_pc); // Continuation::fix_continuation_bottom_sender(*this, map, frame(sender_sp, unextended_sp, *saved_fp_addr, sender_pc)); + } + + inline const ImmutableOopMap* frame::get_oop_map() const { + if (_cb == NULL) return NULL; + if (_cb->oop_maps() != NULL) { + NativePostCallNop* nop = nativePostCallNop_at(_pc); + if (nop != NULL && + #ifdef CONT_DOUBLE_NOP + !nop->is_mode2() && + #endif + nop->displacement() != 0 + ) { + int slot = ((nop->displacement() >> 24) & 0xff); + return _cb->oop_map_for_slot(slot, _pc); + } + const ImmutableOopMap* oop_map = OopMapSet::find_map(this); + return oop_map; + } + return NULL; + } + #endif // CPU_X86_FRAME_X86_INLINE_HPP
< prev index next >