*** 143,17 *** sender_sp = _unextended_sp + _cb->frame_size(); // Is sender_sp safe? if (!thread->is_in_full_stack_checked((address)sender_sp)) { return false; } - sender_unextended_sp = sender_sp; // On Intel the return_address is always the word on the stack sender_pc = (address) *(sender_sp-1); // Note: frame::sender_sp_offset is only valid for compiled frame ! saved_fp = (intptr_t*) *(sender_sp - frame::sender_sp_offset); ! } if (Continuation::is_return_barrier_entry(sender_pc)) { // sender_pc might be invalid so check that the frame // actually belongs to a Continuation. if (!Continuation::is_frame_in_continuation(thread, *this)) { return false; --- 143,20 --- sender_sp = _unextended_sp + _cb->frame_size(); // Is sender_sp safe? if (!thread->is_in_full_stack_checked((address)sender_sp)) { return false; } // On Intel the return_address is always the word on the stack sender_pc = (address) *(sender_sp-1); // Note: frame::sender_sp_offset is only valid for compiled frame ! intptr_t** saved_fp_addr = (intptr_t**) (sender_sp - frame::sender_sp_offset); ! saved_fp = *saved_fp_addr; + // Repair the sender sp if this is a method with scalarized inline type args + sender_sp = repair_sender_sp(sender_sp, saved_fp_addr); + sender_unextended_sp = sender_sp; + } if (Continuation::is_return_barrier_entry(sender_pc)) { // sender_pc might be invalid so check that the frame // actually belongs to a Continuation. if (!Continuation::is_frame_in_continuation(thread, *this)) { return false;
*** 608,17 *** intptr_t* fp_loc; if (is_interpreted_frame()) { ret_pc_loc = fp() + return_addr_offset; fp_loc = fp(); } else { ! ret_pc_loc = real_fp() - return_addr_offset; ! fp_loc = real_fp() - sender_sp_offset; } address ret_pc = *(address*)ret_pc_loc; values.describe(frame_no, ret_pc_loc, Continuation::is_return_barrier_entry(ret_pc) ? "return address (return barrier)" : "return address"); values.describe(-1, fp_loc, "saved fp", 0); // "unowned" as value belongs to sender } } #endif // !PRODUCT --- 611,28 --- intptr_t* fp_loc; if (is_interpreted_frame()) { ret_pc_loc = fp() + return_addr_offset; fp_loc = fp(); } else { ! if (cb()->is_nmethod() && cb()->as_nmethod_or_null()->needs_stack_repair()) { ! values.describe(frame_no, real_fp() - sender_sp_offset - 1, err_msg("fsize for #%d", frame_no), 1); + } + frame::CompiledFramePointers cfp = compiled_frame_details(); + ret_pc_loc = (intptr_t*)cfp.sender_pc_addr; + fp_loc = (intptr_t*)cfp.saved_fp_addr; } address ret_pc = *(address*)ret_pc_loc; values.describe(frame_no, ret_pc_loc, Continuation::is_return_barrier_entry(ret_pc) ? "return address (return barrier)" : "return address"); values.describe(-1, fp_loc, "saved fp", 0); // "unowned" as value belongs to sender + + intptr_t* ret_pc_loc2 = real_fp() - return_addr_offset; + if (ret_pc_loc2 != ret_pc_loc) { + intptr_t* fp_loc2 = real_fp() - sender_sp_offset; + values.describe(frame_no, ret_pc_loc2, "return address copy #2"); + values.describe(-1, fp_loc2, "saved fp copy #2", 0); + } } } #endif // !PRODUCT
*** 633,10 *** --- 647,68 --- init((intptr_t*)sp, (intptr_t*)fp, (address)pc); } #endif + // Check for a method with scalarized inline type arguments that needs + // a stack repair and return the repaired sender stack pointer. + intptr_t* frame::repair_sender_sp(intptr_t* sender_sp, intptr_t** saved_fp_addr) const { + nmethod* nm = _cb->as_nmethod_or_null(); + if (nm != nullptr && nm->needs_stack_repair()) { + // The stack increment resides just below the saved rbp on the stack + // and does not account for the return address and rbp (see MacroAssembler::remove_frame). + intptr_t* real_frame_size_addr = (intptr_t*) (saved_fp_addr - 1); + int real_frame_size = (*real_frame_size_addr / wordSize) + metadata_words_at_bottom; + assert(real_frame_size >= _cb->frame_size() && real_frame_size <= 1000000, "invalid frame size"); + sender_sp = unextended_sp() + real_frame_size; + } + return sender_sp; + } + + + // See comment in MacroAssembler::remove_frame + frame::CompiledFramePointers frame::compiled_frame_details() const { + // 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(), ""); + + // Repair the sender sp if the frame has been extended + sender_sp = repair_sender_sp(sender_sp, (intptr_t**)(sender_sp - frame::sender_sp_offset)); + + CompiledFramePointers cfp; + cfp.sender_sp = sender_sp; + cfp.saved_fp_addr = (intptr_t**)(sender_sp - frame::sender_sp_offset); + // On Intel the return_address is always the word on the stack + cfp.sender_pc_addr = (address*)(sender_sp - frame::return_addr_offset); + + return cfp; + } + + intptr_t* frame::repair_sender_sp(nmethod* nm, intptr_t* sp, intptr_t** saved_fp_addr) { + assert(nm != nullptr && nm->needs_stack_repair(), ""); + // The stack increment resides just below the saved rbp on the stack + // and does not account for the return address and rbp (see MacroAssembler::remove_frame). + intptr_t* real_frame_size_addr = (intptr_t*) (saved_fp_addr - 1); + int real_frame_size = (*real_frame_size_addr / wordSize) + metadata_words_at_bottom; + assert(real_frame_size >= nm->frame_size() && real_frame_size <= 1000000, "invalid frame size"); + return sp + real_frame_size; + } + + bool frame::was_augmented_on_entry(int& real_size) const { + assert(is_compiled_frame(), ""); + if (_cb->as_nmethod_or_null()->needs_stack_repair()) { + // The stack increment resides just below the saved rbp on the stack + // and does not account for the return address and rbp (see MacroAssembler::remove_frame). + intptr_t* real_frame_size_addr = unextended_sp() + _cb->frame_size() - sender_sp_offset - 1; + real_size = (*real_frame_size_addr / wordSize) + metadata_words_at_bottom; + return real_size != _cb->frame_size(); + } + real_size = _cb->frame_size(); + return false; + } + void JavaFrameAnchor::make_walkable() { // last frame set? if (last_Java_sp() == nullptr) return; // already walkable? if (walkable()) return;