From be1ea26d3fb0f4c4745674637c7daec249945605 Mon Sep 17 00:00:00 2001 From: never Date: Thu, 12 Aug 2010 23:34:34 -0700 Subject: [PATCH] 6975006: assert(check.is_deoptimized_frame()) failed: missed deopt Reviewed-by: kvn, twisti --- src/share/vm/runtime/frame.cpp | 18 ++++++++++-------- src/share/vm/runtime/frame.hpp | 2 +- src/share/vm/runtime/safepoint.cpp | 3 +++ src/share/vm/runtime/safepoint.hpp | 2 ++ src/share/vm/runtime/thread.cpp | 3 +-- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/share/vm/runtime/frame.cpp b/src/share/vm/runtime/frame.cpp index 89de3ca1a..69d287984 100644 --- a/src/share/vm/runtime/frame.cpp +++ b/src/share/vm/runtime/frame.cpp @@ -215,17 +215,15 @@ bool frame::can_be_deoptimized() const { return !nm->is_at_poll_return(pc()); } -void frame::deoptimize(JavaThread* thread, bool thread_is_known_safe) { -// Schedule deoptimization of an nmethod activation with this frame. - - // Store the original pc before an patch (or request to self-deopt) - // in the published location of the frame. - +void frame::deoptimize(JavaThread* thread) { + // Schedule deoptimization of an nmethod activation with this frame. assert(_cb != NULL && _cb->is_nmethod(), "must be"); nmethod* nm = (nmethod*)_cb; // This is a fix for register window patching race - if (NeedsDeoptSuspend && !thread_is_known_safe) { + if (NeedsDeoptSuspend && Thread::current() != thread) { + assert(SafepointSynchronize::is_at_safepoint(), + "patching other threads for deopt may only occur at a safepoint"); // It is possible especially with DeoptimizeALot/DeoptimizeRandom that // we could see the frame again and ask for it to be deoptimized since @@ -248,7 +246,11 @@ void frame::deoptimize(JavaThread* thread, bool thread_is_known_safe) { // whether to spin or block. It isn't worth it. Just treat it like // native and be done with it. // - JavaThreadState state = thread->thread_state(); + // Examine the state of the thread at the start of safepoint since + // threads that were in native at the start of the safepoint could + // come to a halt during the safepoint, changing the current value + // of the safepoint_state. + JavaThreadState state = thread->safepoint_state()->orig_thread_state(); if (state == _thread_in_native || state == _thread_in_native_trans) { // Since we are at a safepoint the target thread will stop itself // before it can return to java as long as we remain at the safepoint. diff --git a/src/share/vm/runtime/frame.hpp b/src/share/vm/runtime/frame.hpp index 4f2df2ad9..a2ac51f36 100644 --- a/src/share/vm/runtime/frame.hpp +++ b/src/share/vm/runtime/frame.hpp @@ -174,7 +174,7 @@ class frame VALUE_OBJ_CLASS_SPEC { address sender_pc() const; // Support for deoptimization - void deoptimize(JavaThread* thread, bool thread_is_known_safe = false); + void deoptimize(JavaThread* thread); // The frame's original SP, before any extension by an interpreted callee; // used for packing debug info into vframeArray objects and vframeArray lookup. diff --git a/src/share/vm/runtime/safepoint.cpp b/src/share/vm/runtime/safepoint.cpp index 65d130de1..2b51d3037 100644 --- a/src/share/vm/runtime/safepoint.cpp +++ b/src/share/vm/runtime/safepoint.cpp @@ -782,6 +782,9 @@ void ThreadSafepointState::examine_state_of_thread() { JavaThreadState state = _thread->thread_state(); + // Save the state at the start of safepoint processing. + _orig_thread_state = state; + // Check for a thread that is suspended. Note that thread resume tries // to grab the Threads_lock which we own here, so a thread cannot be // resumed during safepoint synchronization. diff --git a/src/share/vm/runtime/safepoint.hpp b/src/share/vm/runtime/safepoint.hpp index 46d7f3c3b..740cbd61c 100644 --- a/src/share/vm/runtime/safepoint.hpp +++ b/src/share/vm/runtime/safepoint.hpp @@ -185,6 +185,7 @@ class ThreadSafepointState: public CHeapObj { JavaThread * _thread; volatile suspend_type _type; + JavaThreadState _orig_thread_state; public: @@ -199,6 +200,7 @@ class ThreadSafepointState: public CHeapObj { JavaThread* thread() const { return _thread; } suspend_type type() const { return _type; } bool is_running() const { return (_type==_running); } + JavaThreadState orig_thread_state() const { return _orig_thread_state; } // Support for safepoint timeout (debugging) bool has_called_back() const { return _has_called_back; } diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp index e2ac4f86b..d9fdbbd75 100644 --- a/src/share/vm/runtime/thread.cpp +++ b/src/share/vm/runtime/thread.cpp @@ -2110,8 +2110,7 @@ void JavaThread::check_safepoint_and_suspend_for_native_trans(JavaThread *thread } if (f.id() == thread->must_deopt_id()) { thread->clear_must_deopt_id(); - // Since we know we're safe to deopt the current state is a safe state - f.deoptimize(thread, true); + f.deoptimize(thread); } else { fatal("missed deoptimization!"); } -- GitLab