From 6e820bb025b5cd16e391a7839ae215dcba401c3a Mon Sep 17 00:00:00 2001
From: Dean Long <dlong@openjdk.org>
Date: Tue, 16 Aug 2016 09:19:13 -0700
Subject: [PATCH] 8161598: Kitchensink fails:
 assert(nm->insts_contains(original_pc)) failed: original PC must be in
 nmethod/CompiledMethod

Skip unwalkable frames in

Reviewed-by: fparain, coleenp, aph
---
 hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp    |  4 +--
 hotspot/src/cpu/x86/vm/frame_x86.cpp          | 31 ++++++++++++++++---
 hotspot/src/cpu/x86/vm/frame_x86.inline.hpp   |  1 +
 .../src/cpu/x86/vm/javaFrameAnchor_x86.hpp    |  7 ++---
 hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp | 17 +++++-----
 hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp |  4 +--
 hotspot/src/cpu/x86/vm/runtime_x86_32.cpp     |  2 +-
 .../src/cpu/x86/vm/sharedRuntime_x86_32.cpp   | 16 +++++-----
 .../src/cpu/x86/vm/sharedRuntime_x86_64.cpp   | 20 ++++++------
 .../src/cpu/x86/vm/stubGenerator_x86_32.cpp   |  2 +-
 .../src/cpu/x86/vm/stubGenerator_x86_64.cpp   |  2 +-
 .../vm/templateInterpreterGenerator_x86.cpp   |  4 +--
 .../src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp  |  2 +-
 .../src/os_cpu/bsd_x86/vm/thread_bsd_x86.hpp  |  8 ++---
 .../os_cpu/linux_x86/vm/thread_linux_x86.cpp  |  2 +-
 .../os_cpu/linux_x86/vm/thread_linux_x86.hpp  |  8 ++---
 .../solaris_x86/vm/thread_solaris_x86.cpp     |  5 ++-
 .../solaris_x86/vm/thread_solaris_x86.hpp     |  8 ++---
 .../windows_x86/vm/thread_windows_x86.cpp     |  2 +-
 .../windows_x86/vm/thread_windows_x86.hpp     |  8 ++---
 20 files changed, 77 insertions(+), 76 deletions(-)

diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp
index 0b607df2606..5fe455600d1 100644
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp
@@ -98,7 +98,7 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre
   }
   pop(rax);
 #endif
-  reset_last_Java_frame(thread, true, align_stack);
+  reset_last_Java_frame(thread, true);
 
   // discard thread and arguments
   NOT_LP64(addptr(rsp, num_rt_args()*BytesPerWord));
@@ -872,7 +872,7 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) {
   }
   __ pop(rax);
 #endif
-  __ reset_last_Java_frame(thread, true, false);
+  __ reset_last_Java_frame(thread, true);
 #ifndef _LP64
   __ pop(rcx); // discard thread arg
   __ pop(rcx); // discard dummy
diff --git a/hotspot/src/cpu/x86/vm/frame_x86.cpp b/hotspot/src/cpu/x86/vm/frame_x86.cpp
index 1db4b424cf5..0a636f44ec0 100644
--- a/hotspot/src/cpu/x86/vm/frame_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp
@@ -337,13 +337,16 @@ frame frame::sender_for_entry_frame(RegisterMap* map) const {
   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;
 }
 
@@ -666,3 +669,21 @@ frame::frame(void* sp, void* fp, void* pc) {
   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/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp
index 0c968ce80cf..d7d8e47ea89 100644
--- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp
+++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp
@@ -101,6 +101,7 @@ inline frame::frame(intptr_t* sp, intptr_t* fp) {
   // call a specialized frame constructor instead of this one.
   // Then we could use the assert below. However this assert is of somewhat dubious
   // value.
+  // UPDATE: this constructor is only used by trace_method_handle_stub() now.
   // assert(_pc != NULL, "no pc?");
 
   _cb = CodeCache::find_blob(_pc);
diff --git a/hotspot/src/cpu/x86/vm/javaFrameAnchor_x86.hpp b/hotspot/src/cpu/x86/vm/javaFrameAnchor_x86.hpp
index 77298e53770..40eedf019ae 100644
--- a/hotspot/src/cpu/x86/vm/javaFrameAnchor_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/javaFrameAnchor_x86.hpp
@@ -62,10 +62,9 @@ public:
     _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; }
 
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
index 9b52535459a..9957425c95c 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
@@ -752,8 +752,7 @@ void MacroAssembler::pushptr(AddressLiteral src) {
   }
 }
 
-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
   movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), NULL_WORD);
   // must clear fp, so that compiled frames are not confused; it is
@@ -762,9 +761,8 @@ void MacroAssembler::reset_last_Java_frame(bool clear_fp,
     movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), NULL_WORD);
   }
 
-  if (clear_pc) {
-    movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), NULL_WORD);
-  }
+  // Always clear the pc because it could have been set by make_walkable()
+  movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), NULL_WORD);
 }
 
 void MacroAssembler::set_last_Java_frame(Register last_java_sp,
@@ -2531,7 +2529,7 @@ void MacroAssembler::call_VM_base(Register oop_result,
   }
   // reset last Java frame
   // Only interpreter should have to clear fp
-  reset_last_Java_frame(java_thread, true, false);
+  reset_last_Java_frame(java_thread, true);
 
    // C++ interp handles this in the interpreter
   check_and_handle_popframe(java_thread);
@@ -3642,8 +3640,7 @@ void MacroAssembler::push_IU_state() {
   pusha();
 }
 
-void MacroAssembler::reset_last_Java_frame(Register java_thread, bool clear_fp, bool clear_pc) {
-  // determine java_thread register
+void MacroAssembler::reset_last_Java_frame(Register java_thread, bool clear_fp) { // determine java_thread register
   if (!java_thread->is_valid()) {
     java_thread = rdi;
     get_thread(java_thread);
@@ -3654,8 +3651,8 @@ void MacroAssembler::reset_last_Java_frame(Register java_thread, bool clear_fp,
     movptr(Address(java_thread, JavaThread::last_Java_fp_offset()), NULL_WORD);
   }
 
-  if (clear_pc)
-    movptr(Address(java_thread, JavaThread::last_Java_pc_offset()), NULL_WORD);
+  // Always clear the pc because it could have been set by make_walkable()
+  movptr(Address(java_thread, JavaThread::last_Java_pc_offset()), NULL_WORD);
 
 }
 
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
index 2098c05891e..cd3c67c4ab2 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
@@ -288,10 +288,10 @@ class MacroAssembler: public Assembler {
                            Register last_java_fp,
                            address last_java_pc);
 
-  void reset_last_Java_frame(Register thread, bool clear_fp, bool clear_pc);
+  void reset_last_Java_frame(Register thread, bool clear_fp);
 
   // thread in the default location (r15_thread on 64bit)
-  void reset_last_Java_frame(bool clear_fp, bool clear_pc);
+  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/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp b/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp
index 5ff630145a7..a40edbd1297 100644
--- a/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp
+++ b/hotspot/src/cpu/x86/vm/runtime_x86_32.cpp
@@ -117,7 +117,7 @@ void OptoRuntime::generate_exception_blob() {
   // No registers to map, rbp is known implicitly
   oop_maps->add_gc_map( __ pc() - start,  new OopMap( framesize, 0 ));
   __ get_thread(rcx);
-  __ reset_last_Java_frame(rcx, false, false);
+  __ reset_last_Java_frame(rcx, false);
 
   // Restore callee-saved registers
   __ movptr(rbp, Address(rsp, rbp_off * wordSize));
diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp
index a24397f4c8f..96961a8b9b0 100644
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp
@@ -1330,7 +1330,7 @@ static void check_needs_gc_for_critical_native(MacroAssembler* masm,
   __ increment(rsp, wordSize);
 
   __ get_thread(thread);
-  __ reset_last_Java_frame(thread, false, true);
+  __ reset_last_Java_frame(thread, false);
 
   save_or_restore_arguments(masm, stack_slots, total_in_args,
                             arg_save_area, NULL, in_regs, in_sig_bt);
@@ -2224,7 +2224,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
 
   // We can finally stop using that last_Java_frame we setup ages ago
 
-  __ reset_last_Java_frame(thread, false, true);
+  __ reset_last_Java_frame(thread, false);
 
   // Unpack oop result
   if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
@@ -2553,7 +2553,7 @@ void SharedRuntime::generate_deopt_blob() {
   __ pop(rcx);
 
   __ get_thread(rcx);
-  __ reset_last_Java_frame(rcx, false, false);
+  __ reset_last_Java_frame(rcx, false);
 
   // Load UnrollBlock into EDI
   __ mov(rdi, rax);
@@ -2702,7 +2702,7 @@ void SharedRuntime::generate_deopt_blob() {
   __ push(rax);
 
   __ get_thread(rcx);
-  __ reset_last_Java_frame(rcx, false, false);
+  __ reset_last_Java_frame(rcx, false);
 
   // Collect return values
   __ movptr(rax,Address(rsp, (RegisterSaver::raxOffset() + additional_words + 1)*wordSize));
@@ -2806,7 +2806,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
 
   __ get_thread(rcx);
 
-  __ reset_last_Java_frame(rcx, false, false);
+  __ reset_last_Java_frame(rcx, false);
 
   // Load UnrollBlock into EDI
   __ movptr(rdi, rax);
@@ -2912,7 +2912,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
   oop_maps->add_gc_map( __ pc()-start, new OopMap( framesize, 0 ) );
 
   __ get_thread(rdi);
-  __ reset_last_Java_frame(rdi, true, false);
+  __ reset_last_Java_frame(rdi, true);
 
   // Pop self-frame.
   __ leave();     // Epilog!
@@ -3007,7 +3007,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
 
   // Clear last_Java_sp again
   __ get_thread(java_thread);
-  __ reset_last_Java_frame(java_thread, false, false);
+  __ reset_last_Java_frame(java_thread, false);
 
   __ cmpptr(Address(java_thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD);
   __ jcc(Assembler::equal, noException);
@@ -3082,7 +3082,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha
   __ addptr(rsp, wordSize);
 
   // clear last_Java_sp
-  __ reset_last_Java_frame(thread, true, false);
+  __ reset_last_Java_frame(thread, true);
   // check for pending exceptions
   Label pending;
   __ cmpptr(Address(thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD);
diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
index 81ed472f462..76b7bb46e34 100644
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
@@ -1461,7 +1461,7 @@ static void check_needs_gc_for_critical_native(MacroAssembler* masm,
   __ mov(rsp, r12); // restore sp
   __ reinit_heapbase();
 
-  __ reset_last_Java_frame(false, true);
+  __ reset_last_Java_frame(false);
 
   save_or_restore_arguments(masm, stack_slots, total_in_args,
                             arg_save_area, NULL, in_regs, in_sig_bt);
@@ -2577,7 +2577,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
     restore_native_result(masm, ret_type, stack_slots);
   }
 
-  __ reset_last_Java_frame(false, true);
+  __ reset_last_Java_frame(false);
 
   // Unpack oop result
   if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
@@ -2849,7 +2849,7 @@ void SharedRuntime::generate_deopt_blob() {
     __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
     oop_maps->add_gc_map( __ pc()-start, map->deep_copy());
 
-    __ reset_last_Java_frame(false, false);
+    __ reset_last_Java_frame(false);
 
     __ jmp(after_fetch_unroll_info_call);
   } // EnableJVMCI
@@ -2939,7 +2939,7 @@ void SharedRuntime::generate_deopt_blob() {
   // find any register it might need.
   oop_maps->add_gc_map(__ pc() - start, map);
 
-  __ reset_last_Java_frame(false, false);
+  __ reset_last_Java_frame(false);
 
 #if INCLUDE_JVMCI
   if (EnableJVMCI) {
@@ -3087,7 +3087,7 @@ void SharedRuntime::generate_deopt_blob() {
                        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
   __ movdbl(xmm0, Address(rsp, RegisterSaver::xmm0_offset_in_bytes()));
@@ -3164,7 +3164,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
 
   oop_maps->add_gc_map(__ pc() - start, map);
 
-  __ reset_last_Java_frame(false, false);
+  __ reset_last_Java_frame(false);
 
   // Load UnrollBlock* into rdi
   __ mov(rdi, rax);
@@ -3281,7 +3281,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
   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
@@ -3364,7 +3364,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
 
   Label noException;
 
-  __ reset_last_Java_frame(false, false);
+  __ reset_last_Java_frame(false);
 
   __ cmpptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD);
   __ jcc(Assembler::equal, noException);
@@ -3434,7 +3434,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha
   // rax contains the address we are going to jump to assuming no exception got installed
 
   // clear last_Java_sp
-  __ reset_last_Java_frame(false, false);
+  __ reset_last_Java_frame(false);
   // check for pending exceptions
   Label pending;
   __ cmpptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD);
@@ -3809,7 +3809,7 @@ void OptoRuntime::generate_exception_blob() {
 
   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/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp
index 60485a6a1d8..c52be1e17cb 100644
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp
@@ -3766,7 +3766,7 @@ class StubGenerator: public StubCodeGenerator {
     // however can use the register value directly if it is callee saved.
     __ get_thread(java_thread);
 
-    __ reset_last_Java_frame(java_thread, true, false);
+    __ reset_last_Java_frame(java_thread, true);
 
     __ leave(); // required for proper stackwalking of RuntimeStub frame
 
diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
index 02e46bd02aa..668b3e1e128 100644
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
@@ -5018,7 +5018,7 @@ class StubGenerator: public StubCodeGenerator {
 
     oop_maps->add_gc_map(the_pc - start, map);
 
-    __ reset_last_Java_frame(true, true);
+    __ reset_last_Java_frame(true);
 
     __ leave(); // required for proper stackwalking of RuntimeStub frame
 
diff --git a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp
index 225850e8f40..845959fe4e4 100644
--- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp
@@ -1167,7 +1167,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
   __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_Java);
 
   // reset_last_Java_frame
-  __ reset_last_Java_frame(thread, true, true);
+  __ reset_last_Java_frame(thread, true);
 
   // reset handle block
   __ movptr(t, Address(thread, JavaThread::active_handles_offset()));
@@ -1659,7 +1659,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
   __ set_last_Java_frame(noreg, rbp, __ pc());
   __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::popframe_move_outgoing_args), r15_thread, c_rarg1, c_rarg2);
 #endif
-  __ reset_last_Java_frame(thread, true, true);
+  __ reset_last_Java_frame(thread, true);
 
   // Restore the last_sp and null it out
   __ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
diff --git a/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp
index df36e6edbe1..9747e0aab65 100644
--- a/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp
+++ b/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.cpp
@@ -45,7 +45,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava)
 
   // 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/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.hpp b/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.hpp
index 1d7921c7114..b1717c5c22a 100644
--- a/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.hpp
+++ b/hotspot/src/os_cpu/bsd_x86/vm/thread_bsd_x86.hpp
@@ -32,12 +32,8 @@
 
   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());
-    }
+    vmassert(_anchor.last_Java_pc() != NULL, "not walkable");
+    return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc());
   }
 
  public:
diff --git a/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp
index 3075dd19dd3..59991b7765f 100644
--- a/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp
+++ b/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.cpp
@@ -46,7 +46,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava)
 
   // 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/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.hpp b/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.hpp
index 75fb7df5787..ab8bd4c3cb9 100644
--- a/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.hpp
+++ b/hotspot/src/os_cpu/linux_x86/vm/thread_linux_x86.hpp
@@ -32,12 +32,8 @@
 
   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());
-    }
+    vmassert(_anchor.last_Java_pc() != NULL, "not walkable");
+    return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc());
   }
 
  public:
diff --git a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp
index 48af49f7497..4f413baaca3 100644
--- a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp
+++ b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp
@@ -45,9 +45,8 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr,
   assert(this->is_Java_thread(), "must be JavaThread");
   JavaThread* jt = (JavaThread *)this;
 
-  // last_Java_frame is always walkable and safe use it if we have it
-
-  if (jt->has_last_Java_frame()) {
+  // There is small window where last_Java_frame is not walkable or safe
+  if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) {
     *fr_addr = jt->pd_last_frame();
     return true;
   }
diff --git a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.hpp b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.hpp
index 7589a81a83b..934f80a04fe 100644
--- a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.hpp
+++ b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.hpp
@@ -30,12 +30,8 @@
 
   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());
-    }
+    vmassert(_anchor.last_Java_pc() != NULL, "not walkable");
+    return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc());
   }
 
  public:
diff --git a/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp
index ba5be5736cf..c093c146842 100644
--- a/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp
+++ b/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.cpp
@@ -48,7 +48,7 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava)
 
   // If we have a last_Java_frame, then we should use it even if
   // isInJava == true.  It should be more reliable than CONTEXT 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/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.hpp b/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.hpp
index 65aac35109a..8d6e5f820f8 100644
--- a/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.hpp
+++ b/hotspot/src/os_cpu/windows_x86/vm/thread_windows_x86.hpp
@@ -32,12 +32,8 @@
 
   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());
-    }
+    vmassert(_anchor.last_Java_pc() != NULL, "not walkable");
+    return frame(_anchor.last_Java_sp(), _anchor.last_Java_fp(), _anchor.last_Java_pc());
   }
 
  public: