--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Mon Aug 15 14:08:01 2016 -0700
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Tue Aug 16 17:31:57 2016 +0100
@@ -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);
--- a/hotspot/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp Mon Aug 15 14:08:01 2016 -0700
+++ b/hotspot/src/cpu/aarch64/vm/c1_Runtime1_aarch64.cpp Tue Aug 16 17:31:57 2016 +0100
@@ -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
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp Mon Aug 15 14:08:01 2016 -0700
+++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp Tue Aug 16 17:31:57 2016 +0100
@@ -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];
+}
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp Mon Aug 15 14:08:01 2016 -0700
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp Tue Aug 16 17:31:57 2016 +0100
@@ -201,7 +201,7 @@
// #endif
MacroAssembler::null_check(reg, offset);
// #ifdef ASSERT
-// reset_last_Java_frame(true, false);
+// reset_last_Java_frame(true);
// #endif
}
--- a/hotspot/src/cpu/aarch64/vm/javaFrameAnchor_aarch64.hpp Mon Aug 15 14:08:01 2016 -0700
+++ b/hotspot/src/cpu/aarch64/vm/javaFrameAnchor_aarch64.hpp Tue Aug 16 17:31:57 2016 +0100
@@ -64,10 +64,9 @@
_last_Java_sp = src->_last_Java_sp;
}
- // 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; }
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Mon Aug 15 14:08:01 2016 -0700
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Tue Aug 16 17:31:57 2016 +0100
@@ -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);
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Mon Aug 15 14:08:01 2016 -0700
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Tue Aug 16 17:31:57 2016 +0100
@@ -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
--- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Mon Aug 15 14:08:01 2016 -0700
+++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp Tue Aug 16 17:31:57 2016 +0100
@@ -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
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Mon Aug 15 14:08:01 2016 -0700
+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Tue Aug 16 17:31:57 2016 +0100
@@ -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();
--- a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp Mon Aug 15 14:08:01 2016 -0700
+++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp Tue Aug 16 17:31:57 2016 +0100
@@ -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()));
--- a/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp Mon Aug 15 14:08:01 2016 -0700
+++ b/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp Tue Aug 16 17:31:57 2016 +0100
@@ -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;
}
--- a/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp Mon Aug 15 14:08:01 2016 -0700
+++ b/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp Tue Aug 16 17:31:57 2016 +0100
@@ -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: