# HG changeset patch # User aph # Date 1471362576 -3600 # Tue Aug 16 16:49:36 2016 +0100 # Node ID 5d40d9646c3a9a6b3c556d2463b75a3f274841d4 # Parent 7f23e809f6cf8920ef965f95d10a1b9ba711cbf9 8164113: AArch64: follow-up the fix for 8161598 Reviewed-by: duke diff --git a/src/cpu/aarch64/vm/aarch64.ad b/src/cpu/aarch64/vm/aarch64.ad --- a/src/cpu/aarch64/vm/aarch64.ad +++ b/src/cpu/aarch64/vm/aarch64.ad @@ -4680,7 +4680,7 @@ Label retaddr; __ adr(rscratch2, retaddr); __ lea(rscratch1, RuntimeAddress(entry)); - // Leave a breadcrumb for JavaThread::pd_last_frame(). + // Leave a breadcrumb for JavaFrameAnchor::capture_last_Java_pc() __ stp(zr, rscratch2, Address(__ pre(sp, -2 * wordSize))); __ blrt(rscratch1, gpcnt, fpcnt, rtype); __ bind(retaddr); diff --git a/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp b/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp --- a/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp +++ b/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp @@ -78,7 +78,7 @@ } pop(r0, sp); #endif - reset_last_Java_frame(true, true); + reset_last_Java_frame(true); maybe_isb(); // check for pending exceptions @@ -547,7 +547,7 @@ __ bind(L); } #endif - __ reset_last_Java_frame(true, false); + __ reset_last_Java_frame(true); __ maybe_isb(); // check for pending exceptions diff --git a/src/cpu/aarch64/vm/frame_aarch64.cpp b/src/cpu/aarch64/vm/frame_aarch64.cpp --- a/src/cpu/aarch64/vm/frame_aarch64.cpp +++ b/src/cpu/aarch64/vm/frame_aarch64.cpp @@ -336,13 +336,16 @@ JavaFrameAnchor* jfa = entry_frame_call_wrapper()->anchor(); assert(!entry_frame_is_first(), "next Java fp must be non zero"); assert(jfa->last_Java_sp() > sp(), "must be above this frame on stack"); + // Since we are walking the stack now this nested anchor is obviously walkable + // even if it wasn't when it was stacked. + if (!jfa->walkable()) { + // Capture _last_Java_pc (if needed) and mark anchor walkable. + jfa->capture_last_Java_pc(); + } map->clear(); assert(map->include_argument_oops(), "should be set by clear"); - if (jfa->last_Java_pc() != NULL ) { - frame fr(jfa->last_Java_sp(), jfa->last_Java_fp(), jfa->last_Java_pc()); - return fr; - } - frame fr(jfa->last_Java_sp(), jfa->last_Java_fp()); + vmassert(jfa->last_Java_pc() != NULL, "not walkable"); + frame fr(jfa->last_Java_sp(), jfa->last_Java_fp(), jfa->last_Java_pc()); return fr; } @@ -769,3 +772,21 @@ init((intptr_t*)sp, (intptr_t*)fp, (address)pc); } #endif + +void JavaFrameAnchor::make_walkable(JavaThread* thread) { + // last frame set? + if (last_Java_sp() == NULL) return; + // already walkable? + if (walkable()) return; + vmassert(Thread::current() == (Thread*)thread, "not current thread"); + vmassert(last_Java_sp() != NULL, "not called from Java code?"); + vmassert(last_Java_pc() == NULL, "already walkable"); + capture_last_Java_pc(); + vmassert(walkable(), "something went wrong"); +} + +void JavaFrameAnchor::capture_last_Java_pc() { + vmassert(_last_Java_sp != NULL, "no last frame set"); + vmassert(_last_Java_pc == NULL, "already walkable"); + _last_Java_pc = (address)_last_Java_sp[-1]; +} diff --git a/src/cpu/aarch64/vm/interp_masm_aarch64.hpp b/src/cpu/aarch64/vm/interp_masm_aarch64.hpp --- a/src/cpu/aarch64/vm/interp_masm_aarch64.hpp +++ b/src/cpu/aarch64/vm/interp_masm_aarch64.hpp @@ -201,7 +201,7 @@ // #endif MacroAssembler::null_check(reg, offset); // #ifdef ASSERT -// reset_last_Java_frame(true, false); +// reset_last_Java_frame(true); // #endif } diff --git a/src/cpu/aarch64/vm/javaFrameAnchor_aarch64.hpp b/src/cpu/aarch64/vm/javaFrameAnchor_aarch64.hpp --- a/src/cpu/aarch64/vm/javaFrameAnchor_aarch64.hpp +++ b/src/cpu/aarch64/vm/javaFrameAnchor_aarch64.hpp @@ -65,9 +65,9 @@ } // Always walkable - bool walkable(void) { return true; } - // Never any thing to do since we are always walkable and can find address of return addresses - void make_walkable(JavaThread* thread) { } + bool walkable(void) { return _last_Java_sp != NULL && _last_Java_pc != NULL; } + void make_walkable(JavaThread* thread); + void capture_last_Java_pc(void); intptr_t* last_Java_sp(void) const { return _last_Java_sp; } diff --git a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp --- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -274,19 +274,18 @@ } -void MacroAssembler::reset_last_Java_frame(bool clear_fp, - bool clear_pc) { +void MacroAssembler::reset_last_Java_frame(bool clear_fp) { // we must set sp to zero to clear frame str(zr, Address(rthread, JavaThread::last_Java_sp_offset())); + // must clear fp, so that compiled frames are not confused; it is // possible that we need it only for debugging if (clear_fp) { str(zr, Address(rthread, JavaThread::last_Java_fp_offset())); } - if (clear_pc) { - str(zr, Address(rthread, JavaThread::last_Java_pc_offset())); - } + // Always clear the pc because it could have been set by make_walkable() + str(zr, Address(rthread, JavaThread::last_Java_pc_offset())); } // Calls to C land @@ -632,7 +631,7 @@ // reset last Java frame // Only interpreter should have to clear fp - reset_last_Java_frame(true, true); + reset_last_Java_frame(true); // C++ interp handles this in the interpreter check_and_handle_popframe(java_thread); @@ -875,7 +874,7 @@ if (type == bytecode_start) { // set_last_Java_frame(esp, rfp, (address)NULL); Assembler:: notify(type); - // reset_last_Java_frame(true, false); + // reset_last_Java_frame(true); } else Assembler:: notify(type); diff --git a/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp --- a/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp +++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp @@ -757,10 +757,10 @@ Register last_java_pc, Register scratch); - void reset_last_Java_frame(Register thread, bool clearfp, bool clear_pc); + void reset_last_Java_frame(Register thread); - // thread in the default location (r15_thread on 64bit) - void reset_last_Java_frame(bool clear_fp, bool clear_pc); + // thread in the default location (rthread) + void reset_last_Java_frame(bool clear_fp); // Stores void store_check(Register obj); // store check for obj - register is destroyed afterwards diff --git a/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp b/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp --- a/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp +++ b/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp @@ -2030,7 +2030,7 @@ __ bind(dtrace_method_exit_done); } - __ reset_last_Java_frame(false, true); + __ reset_last_Java_frame(false); // Unpack oop result if (ret_type == T_OBJECT || ret_type == T_ARRAY) { @@ -2370,7 +2370,7 @@ __ bind(retaddr); oop_maps->add_gc_map( __ pc()-start, map->deep_copy()); - __ reset_last_Java_frame(false, false); + __ reset_last_Java_frame(false); __ b(after_fetch_unroll_info_call); } // EnableJVMCI @@ -2465,7 +2465,7 @@ // find any register it might need. oop_maps->add_gc_map(__ pc() - start, map); - __ reset_last_Java_frame(false, true); + __ reset_last_Java_frame(false); #if INCLUDE_JVMCI if (EnableJVMCI) { @@ -2606,7 +2606,7 @@ new OopMap( frame_size_in_words, 0 )); // Clear fp AND pc - __ reset_last_Java_frame(true, true); + __ reset_last_Java_frame(true); // Collect return values __ ldrd(v0, Address(sp, RegisterSaver::v0_offset_in_bytes())); @@ -2709,7 +2709,7 @@ oop_maps->add_gc_map(__ pc() - start, map); - __ reset_last_Java_frame(false, true); + __ reset_last_Java_frame(false); // move UnrollBlock* into r4 __ mov(r4, r0); @@ -2828,7 +2828,7 @@ oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); // Clear fp AND pc - __ reset_last_Java_frame(true, true); + __ reset_last_Java_frame(true); // Pop self-frame. __ leave(); // Epilog @@ -2906,7 +2906,7 @@ Label noException; - __ reset_last_Java_frame(false, true); + __ reset_last_Java_frame(false); __ maybe_isb(); __ membar(Assembler::LoadLoad | Assembler::LoadStore); @@ -2985,7 +2985,7 @@ // r0 contains the address we are going to jump to assuming no exception got installed // clear last_Java_sp - __ reset_last_Java_frame(false, true); + __ reset_last_Java_frame(false); // check for pending exceptions Label pending; __ ldr(rscratch1, Address(rthread, Thread::pending_exception_offset())); @@ -3116,7 +3116,7 @@ oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); - __ reset_last_Java_frame(false, true); + __ reset_last_Java_frame(false); // Restore callee-saved registers diff --git a/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp --- a/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp +++ b/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp @@ -3801,7 +3801,7 @@ oop_maps->add_gc_map(the_pc - start, map); - __ reset_last_Java_frame(true, true); + __ reset_last_Java_frame(true); __ maybe_isb(); __ leave(); diff --git a/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp b/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp --- a/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp +++ b/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp @@ -1353,7 +1353,7 @@ __ stlrw(rscratch1, rscratch2); // reset_last_Java_frame - __ reset_last_Java_frame(true, true); + __ reset_last_Java_frame(true); // reset handle block __ ldr(t, Address(rthread, JavaThread::active_handles_offset())); diff --git a/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp b/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp --- a/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp +++ b/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp @@ -47,7 +47,7 @@ // If we have a last_Java_frame, then we should use it even if // isInJava == true. It should be more reliable than ucontext info. - if (jt->has_last_Java_frame()) { + if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) { *fr_addr = jt->pd_last_frame(); return true; } diff --git a/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp b/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp --- a/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp +++ b/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp @@ -43,12 +43,7 @@ frame pd_last_frame() { assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); - if (_anchor.last_Java_pc() != NULL) { - return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); - } else { - // This will pick up pc from sp - return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp()); - } + return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc()); } public: