8265934: Cleanup _suspend_flags and _special_runtime_exit_condition
Reviewed-by: rehn, dcubed, dholmes
This commit is contained in:
parent
f3c6cda476
commit
853ffdb25c
@ -2952,7 +2952,7 @@ JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable))
|
||||
THROW_OOP(java_throwable);
|
||||
} else {
|
||||
// Use a VM_Operation to throw the exception.
|
||||
Thread::send_async_exception(java_thread, java_throwable);
|
||||
JavaThread::send_async_exception(java_thread, java_throwable);
|
||||
}
|
||||
} else {
|
||||
// Either:
|
||||
|
@ -971,7 +971,7 @@ void ThreadSafepointState::handle_polling_page_exception() {
|
||||
|
||||
// If we have a pending async exception deoptimize the frame
|
||||
// as otherwise we may never deliver it.
|
||||
if (self->has_async_condition()) {
|
||||
if (self->has_async_exception_condition()) {
|
||||
ThreadInVMfromJava __tiv(self, false /* check asyncs */);
|
||||
Deoptimization::deoptimize_frame(self, caller_fr.id());
|
||||
}
|
||||
|
@ -265,8 +265,6 @@ Thread::Thread() {
|
||||
set_allocated_bytes(0);
|
||||
_current_pending_raw_monitor = NULL;
|
||||
|
||||
_suspend_flags = 0;
|
||||
|
||||
// thread-specific hashCode stream generator state - Marsaglia shift-xor form
|
||||
_hashStateX = os::random();
|
||||
_hashStateY = 842502087;
|
||||
@ -541,27 +539,6 @@ void Thread::start(Thread* thread) {
|
||||
os::start_thread(thread);
|
||||
}
|
||||
|
||||
class InstallAsyncExceptionClosure : public HandshakeClosure {
|
||||
Handle _throwable; // The Throwable thrown at the target Thread
|
||||
public:
|
||||
InstallAsyncExceptionClosure(Handle throwable) : HandshakeClosure("InstallAsyncException"), _throwable(throwable) {}
|
||||
|
||||
void do_thread(Thread* thr) {
|
||||
JavaThread* target = thr->as_Java_thread();
|
||||
// Note that this now allows multiple ThreadDeath exceptions to be
|
||||
// thrown at a thread.
|
||||
// The target thread has run and has not exited yet.
|
||||
target->send_thread_stop(_throwable());
|
||||
}
|
||||
};
|
||||
|
||||
void Thread::send_async_exception(oop java_thread, oop java_throwable) {
|
||||
Handle throwable(Thread::current(), java_throwable);
|
||||
JavaThread* target = java_lang_Thread::thread(java_thread);
|
||||
InstallAsyncExceptionClosure vm_stop(throwable);
|
||||
Handshake::execute(&vm_stop, target);
|
||||
}
|
||||
|
||||
// GC Support
|
||||
bool Thread::claim_par_threads_do(uintx claim_token) {
|
||||
uintx token = _threads_do_token;
|
||||
@ -1045,7 +1022,9 @@ JavaThread::JavaThread() :
|
||||
_Stalled(0),
|
||||
|
||||
_monitor_chunks(nullptr),
|
||||
_special_runtime_exit_condition(_no_async_condition),
|
||||
|
||||
_suspend_flags(0),
|
||||
_async_exception_condition(_no_async_condition),
|
||||
_pending_async_exception(nullptr),
|
||||
|
||||
_thread_state(_thread_new),
|
||||
@ -1606,13 +1585,14 @@ void JavaThread::remove_monitor_chunk(MonitorChunk* chunk) {
|
||||
}
|
||||
}
|
||||
|
||||
// JVM support.
|
||||
|
||||
// Asynchronous exceptions support
|
||||
//
|
||||
// Note: this function shouldn't block if it's called in
|
||||
// _thread_in_native_trans state (such as from
|
||||
// check_special_condition_for_native_trans()).
|
||||
void JavaThread::check_and_handle_async_exceptions(bool check_unsafe_error) {
|
||||
if (has_last_Java_frame() && has_async_condition()) {
|
||||
void JavaThread::check_and_handle_async_exceptions() {
|
||||
if (has_last_Java_frame() && has_async_exception_condition()) {
|
||||
// If we are at a polling page safepoint (not a poll return)
|
||||
// then we must defer async exception because live registers
|
||||
// will be clobbered by the exception path. Poll return is
|
||||
@ -1636,7 +1616,7 @@ void JavaThread::check_and_handle_async_exceptions(bool check_unsafe_error) {
|
||||
}
|
||||
}
|
||||
|
||||
JavaThread::AsyncRequests condition = clear_special_runtime_exit_condition();
|
||||
AsyncExceptionCondition condition = clear_async_exception_condition();
|
||||
if (condition == _no_async_condition) {
|
||||
// Conditions have changed since has_special_runtime_exit_condition()
|
||||
// was called:
|
||||
@ -1668,15 +1648,14 @@ void JavaThread::check_and_handle_async_exceptions(bool check_unsafe_error) {
|
||||
ls.print_cr(" of type: %s", _pending_async_exception->klass()->external_name());
|
||||
}
|
||||
_pending_async_exception = NULL;
|
||||
clear_has_async_exception();
|
||||
// Clear condition from _suspend_flags since we have finished processing it.
|
||||
clear_suspend_flag(_has_async_exception);
|
||||
}
|
||||
}
|
||||
|
||||
if (check_unsafe_error &&
|
||||
condition == _async_unsafe_access_error && !has_pending_exception()) {
|
||||
if (condition == _async_unsafe_access_error && !has_pending_exception()) {
|
||||
// We may be at method entry which requires we save the do-not-unlock flag.
|
||||
UnlockFlagSaver fs(this);
|
||||
condition = _no_async_condition; // done
|
||||
switch (thread_state()) {
|
||||
case _thread_in_vm: {
|
||||
JavaThread* THREAD = this;
|
||||
@ -1700,9 +1679,7 @@ void JavaThread::check_and_handle_async_exceptions(bool check_unsafe_error) {
|
||||
}
|
||||
}
|
||||
|
||||
assert(condition == _no_async_condition || has_pending_exception() ||
|
||||
(!check_unsafe_error && condition == _async_unsafe_access_error),
|
||||
"must have handled the async condition, if no exception");
|
||||
assert(has_pending_exception(), "must have handled the async condition if no exception");
|
||||
}
|
||||
|
||||
void JavaThread::handle_special_runtime_exit_condition(bool check_asyncs) {
|
||||
@ -1721,6 +1698,27 @@ void JavaThread::handle_special_runtime_exit_condition(bool check_asyncs) {
|
||||
JFR_ONLY(SUSPEND_THREAD_CONDITIONAL(this);)
|
||||
}
|
||||
|
||||
class InstallAsyncExceptionClosure : public HandshakeClosure {
|
||||
Handle _throwable; // The Throwable thrown at the target Thread
|
||||
public:
|
||||
InstallAsyncExceptionClosure(Handle throwable) : HandshakeClosure("InstallAsyncException"), _throwable(throwable) {}
|
||||
|
||||
void do_thread(Thread* thr) {
|
||||
JavaThread* target = thr->as_Java_thread();
|
||||
// Note that this now allows multiple ThreadDeath exceptions to be
|
||||
// thrown at a thread.
|
||||
// The target thread has run and has not exited yet.
|
||||
target->send_thread_stop(_throwable());
|
||||
}
|
||||
};
|
||||
|
||||
void JavaThread::send_async_exception(oop java_thread, oop java_throwable) {
|
||||
Handle throwable(Thread::current(), java_throwable);
|
||||
JavaThread* target = java_lang_Thread::thread(java_thread);
|
||||
InstallAsyncExceptionClosure vm_stop(throwable);
|
||||
Handshake::execute(&vm_stop, target);
|
||||
}
|
||||
|
||||
void JavaThread::send_thread_stop(oop java_throwable) {
|
||||
ResourceMark rm;
|
||||
assert(is_handshake_safe_for(Thread::current()),
|
||||
@ -1875,10 +1873,10 @@ void JavaThread::check_special_condition_for_native_trans(JavaThread *thread) {
|
||||
// barrier, which will trap unsafe stack frames.
|
||||
StackWatermarkSet::before_unwind(thread);
|
||||
|
||||
if (thread->has_async_exception()) {
|
||||
if (thread->has_async_exception_condition(false /* check unsafe access error */)) {
|
||||
// We are in _thread_in_native_trans state, don't handle unsafe
|
||||
// access error since that may block.
|
||||
thread->check_and_handle_async_exceptions(false);
|
||||
thread->check_and_handle_async_exceptions();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,20 +215,6 @@ class Thread: public ThreadShadow {
|
||||
protected:
|
||||
static void* allocate(size_t size, bool throw_excpt, MEMFLAGS flags = mtThread);
|
||||
|
||||
enum SuspendFlags {
|
||||
// NOTE: avoid using the sign-bit as cc generates different test code
|
||||
// when the sign-bit is used, and sometimes incorrectly - see CR 6398077
|
||||
|
||||
_has_async_exception = 0x00000001U, // there is a pending async exception
|
||||
|
||||
_trace_flag = 0x00000004U, // call tracing backend
|
||||
_obj_deopt = 0x00000008U // suspend for object reallocation and relocking for JVMTI agent
|
||||
};
|
||||
|
||||
// various suspension related flags - atomically updated
|
||||
// overloaded for async exception checking in check_special_condition_for_native_trans.
|
||||
volatile uint32_t _suspend_flags;
|
||||
|
||||
private:
|
||||
DEBUG_ONLY(bool _suspendible_thread;)
|
||||
|
||||
@ -396,20 +382,6 @@ class Thread: public ThreadShadow {
|
||||
os::set_native_thread_name(name);
|
||||
}
|
||||
|
||||
bool has_async_exception() const { return (_suspend_flags & _has_async_exception) != 0; }
|
||||
|
||||
inline void set_suspend_flag(SuspendFlags f);
|
||||
inline void clear_suspend_flag(SuspendFlags f);
|
||||
|
||||
inline void set_has_async_exception();
|
||||
inline void clear_has_async_exception();
|
||||
|
||||
inline void set_trace_flag();
|
||||
inline void clear_trace_flag();
|
||||
|
||||
inline void set_obj_deopt_flag();
|
||||
inline void clear_obj_deopt_flag();
|
||||
|
||||
// Support for Unhandled Oop detection
|
||||
// Add the field for both, fastdebug and debug, builds to keep
|
||||
// Thread's fields layout the same.
|
||||
@ -440,9 +412,6 @@ class Thread: public ThreadShadow {
|
||||
void set_skip_gcalot(bool v) { _skip_gcalot = v; }
|
||||
#endif
|
||||
|
||||
// Installs a pending exception to be inserted later
|
||||
static void send_async_exception(oop thread_oop, oop java_throwable);
|
||||
|
||||
// Resource area
|
||||
ResourceArea* resource_area() const { return _resource_area; }
|
||||
void set_resource_area(ResourceArea* area) { _resource_area = area; }
|
||||
@ -478,10 +447,6 @@ class Thread: public ThreadShadow {
|
||||
|
||||
JFR_ONLY(DEFINE_THREAD_LOCAL_ACCESSOR_JFR;)
|
||||
|
||||
bool is_trace_suspend() { return (_suspend_flags & _trace_flag) != 0; }
|
||||
|
||||
bool is_obj_deopt_suspend() { return (_suspend_flags & _obj_deopt) != 0; }
|
||||
|
||||
// For tracking the Jvmti raw monitor the thread is pending on.
|
||||
JvmtiRawMonitor* current_pending_raw_monitor() {
|
||||
return _current_pending_raw_monitor;
|
||||
@ -807,14 +772,62 @@ class JavaThread: public Thread {
|
||||
// allocated during deoptimization
|
||||
// and by JNI_MonitorEnter/Exit
|
||||
|
||||
// Async. requests support
|
||||
enum AsyncRequests {
|
||||
enum SuspendFlags {
|
||||
// NOTE: avoid using the sign-bit as cc generates different test code
|
||||
// when the sign-bit is used, and sometimes incorrectly - see CR 6398077
|
||||
_has_async_exception = 0x00000001U, // there is a pending async exception
|
||||
_trace_flag = 0x00000004U, // call tracing backend
|
||||
_obj_deopt = 0x00000008U // suspend for object reallocation and relocking for JVMTI agent
|
||||
};
|
||||
|
||||
// various suspension related flags - atomically updated
|
||||
// overloaded with async exceptions so that we do a single check when transitioning from native->Java
|
||||
volatile uint32_t _suspend_flags;
|
||||
|
||||
inline void set_suspend_flag(SuspendFlags f);
|
||||
inline void clear_suspend_flag(SuspendFlags f);
|
||||
|
||||
public:
|
||||
inline void set_trace_flag();
|
||||
inline void clear_trace_flag();
|
||||
inline void set_obj_deopt_flag();
|
||||
inline void clear_obj_deopt_flag();
|
||||
bool is_trace_suspend() { return (_suspend_flags & _trace_flag) != 0; }
|
||||
bool is_obj_deopt_suspend() { return (_suspend_flags & _obj_deopt) != 0; }
|
||||
|
||||
// Asynchronous exceptions support
|
||||
private:
|
||||
enum AsyncExceptionCondition {
|
||||
_no_async_condition = 0,
|
||||
_async_exception,
|
||||
_async_unsafe_access_error
|
||||
};
|
||||
AsyncRequests _special_runtime_exit_condition; // Enum indicating pending async. request
|
||||
oop _pending_async_exception;
|
||||
AsyncExceptionCondition _async_exception_condition;
|
||||
oop _pending_async_exception;
|
||||
|
||||
void set_async_exception_condition(AsyncExceptionCondition aec) { _async_exception_condition = aec; }
|
||||
AsyncExceptionCondition clear_async_exception_condition() {
|
||||
AsyncExceptionCondition x = _async_exception_condition;
|
||||
_async_exception_condition = _no_async_condition;
|
||||
return x;
|
||||
}
|
||||
|
||||
public:
|
||||
bool has_async_exception_condition(bool check_unsafe_access_error = true) {
|
||||
return check_unsafe_access_error ? _async_exception_condition != _no_async_condition
|
||||
: _async_exception_condition == _async_exception;
|
||||
}
|
||||
inline void set_pending_async_exception(oop e);
|
||||
void set_pending_unsafe_access_error() {
|
||||
// Don't overwrite an asynchronous exception sent by another thread
|
||||
if (_async_exception_condition == _no_async_condition) {
|
||||
set_async_exception_condition(_async_unsafe_access_error);
|
||||
}
|
||||
}
|
||||
void check_and_handle_async_exceptions();
|
||||
// Installs a pending exception to be inserted later
|
||||
static void send_async_exception(oop thread_oop, oop java_throwable);
|
||||
void send_thread_stop(oop throwable);
|
||||
|
||||
// Safepoint support
|
||||
public: // Expose _thread_state for SafeFetchInt()
|
||||
@ -1127,33 +1140,16 @@ class JavaThread: public Thread {
|
||||
// current thread, i.e. reverts optimizations based on escape analysis.
|
||||
void wait_for_object_deoptimization();
|
||||
|
||||
// Thread.stop support
|
||||
void send_thread_stop(oop throwable);
|
||||
AsyncRequests clear_special_runtime_exit_condition() {
|
||||
AsyncRequests x = _special_runtime_exit_condition;
|
||||
_special_runtime_exit_condition = _no_async_condition;
|
||||
return x;
|
||||
}
|
||||
|
||||
// Are any async conditions present?
|
||||
bool has_async_condition() { return (_special_runtime_exit_condition != _no_async_condition); }
|
||||
|
||||
void check_and_handle_async_exceptions(bool check_unsafe_error = true);
|
||||
|
||||
// these next two are also used for self-suspension and async exception support
|
||||
void handle_special_runtime_exit_condition(bool check_asyncs = true);
|
||||
|
||||
// Return true if JavaThread has an asynchronous condition or
|
||||
// if external suspension is requested.
|
||||
bool has_special_runtime_exit_condition() {
|
||||
return (_special_runtime_exit_condition != _no_async_condition) ||
|
||||
return (_async_exception_condition != _no_async_condition) ||
|
||||
(_suspend_flags & (_obj_deopt JFR_ONLY(| _trace_flag))) != 0;
|
||||
}
|
||||
|
||||
void set_pending_unsafe_access_error() { _special_runtime_exit_condition = _async_unsafe_access_error; }
|
||||
|
||||
inline void set_pending_async_exception(oop e);
|
||||
|
||||
// Fast-locking support
|
||||
bool is_lock_owned(address adr) const;
|
||||
|
||||
|
@ -36,40 +36,6 @@
|
||||
#include "runtime/os.hpp"
|
||||
#endif
|
||||
|
||||
inline void Thread::set_suspend_flag(SuspendFlags f) {
|
||||
uint32_t flags;
|
||||
do {
|
||||
flags = _suspend_flags;
|
||||
}
|
||||
while (Atomic::cmpxchg(&_suspend_flags, flags, (flags | f)) != flags);
|
||||
}
|
||||
inline void Thread::clear_suspend_flag(SuspendFlags f) {
|
||||
uint32_t flags;
|
||||
do {
|
||||
flags = _suspend_flags;
|
||||
}
|
||||
while (Atomic::cmpxchg(&_suspend_flags, flags, (flags & ~f)) != flags);
|
||||
}
|
||||
|
||||
inline void Thread::set_has_async_exception() {
|
||||
set_suspend_flag(_has_async_exception);
|
||||
}
|
||||
inline void Thread::clear_has_async_exception() {
|
||||
clear_suspend_flag(_has_async_exception);
|
||||
}
|
||||
inline void Thread::set_trace_flag() {
|
||||
set_suspend_flag(_trace_flag);
|
||||
}
|
||||
inline void Thread::clear_trace_flag() {
|
||||
clear_suspend_flag(_trace_flag);
|
||||
}
|
||||
inline void Thread::set_obj_deopt_flag() {
|
||||
set_suspend_flag(_obj_deopt);
|
||||
}
|
||||
inline void Thread::clear_obj_deopt_flag() {
|
||||
clear_suspend_flag(_obj_deopt);
|
||||
}
|
||||
|
||||
inline jlong Thread::cooked_allocated_bytes() {
|
||||
jlong allocated_bytes = Atomic::load_acquire(&_allocated_bytes);
|
||||
if (UseTLAB) {
|
||||
@ -119,10 +85,41 @@ inline WXMode Thread::enable_wx(WXMode new_state) {
|
||||
}
|
||||
#endif // __APPLE__ && AARCH64
|
||||
|
||||
inline void JavaThread::set_suspend_flag(SuspendFlags f) {
|
||||
uint32_t flags;
|
||||
do {
|
||||
flags = _suspend_flags;
|
||||
}
|
||||
while (Atomic::cmpxchg(&_suspend_flags, flags, (flags | f)) != flags);
|
||||
}
|
||||
inline void JavaThread::clear_suspend_flag(SuspendFlags f) {
|
||||
uint32_t flags;
|
||||
do {
|
||||
flags = _suspend_flags;
|
||||
}
|
||||
while (Atomic::cmpxchg(&_suspend_flags, flags, (flags & ~f)) != flags);
|
||||
}
|
||||
|
||||
inline void JavaThread::set_trace_flag() {
|
||||
set_suspend_flag(_trace_flag);
|
||||
}
|
||||
inline void JavaThread::clear_trace_flag() {
|
||||
clear_suspend_flag(_trace_flag);
|
||||
}
|
||||
inline void JavaThread::set_obj_deopt_flag() {
|
||||
set_suspend_flag(_obj_deopt);
|
||||
}
|
||||
inline void JavaThread::clear_obj_deopt_flag() {
|
||||
clear_suspend_flag(_obj_deopt);
|
||||
}
|
||||
|
||||
inline void JavaThread::set_pending_async_exception(oop e) {
|
||||
_pending_async_exception = e;
|
||||
_special_runtime_exit_condition = _async_exception;
|
||||
set_has_async_exception();
|
||||
set_async_exception_condition(_async_exception);
|
||||
// Set _suspend_flags too so we save a comparison in the transition from native to Java
|
||||
// in the native wrappers. It will be cleared in check_and_handle_async_exceptions()
|
||||
// when we actually install the exception.
|
||||
set_suspend_flag(_has_async_exception);
|
||||
}
|
||||
|
||||
inline JavaThreadState JavaThread::thread_state() const {
|
||||
|
@ -730,7 +730,6 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
||||
nonstatic_field(ThreadShadow, _pending_exception, oop) \
|
||||
nonstatic_field(ThreadShadow, _exception_file, const char*) \
|
||||
nonstatic_field(ThreadShadow, _exception_line, int) \
|
||||
volatile_nonstatic_field(Thread, _suspend_flags, uint32_t) \
|
||||
nonstatic_field(Thread, _active_handles, JNIHandleBlock*) \
|
||||
nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \
|
||||
nonstatic_field(Thread, _allocated_bytes, jlong) \
|
||||
@ -743,11 +742,12 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
||||
nonstatic_field(JavaThread, _current_pending_monitor, ObjectMonitor*) \
|
||||
nonstatic_field(JavaThread, _current_pending_monitor_is_from_java, bool) \
|
||||
nonstatic_field(JavaThread, _current_waiting_monitor, ObjectMonitor*) \
|
||||
volatile_nonstatic_field(JavaThread, _suspend_flags, uint32_t) \
|
||||
nonstatic_field(JavaThread, _async_exception_condition, JavaThread::AsyncExceptionCondition) \
|
||||
nonstatic_field(JavaThread, _pending_async_exception, oop) \
|
||||
volatile_nonstatic_field(JavaThread, _exception_oop, oop) \
|
||||
volatile_nonstatic_field(JavaThread, _exception_pc, address) \
|
||||
volatile_nonstatic_field(JavaThread, _is_method_handle_return, int) \
|
||||
nonstatic_field(JavaThread, _special_runtime_exit_condition, JavaThread::AsyncRequests) \
|
||||
nonstatic_field(JavaThread, _saved_exception_pc, address) \
|
||||
volatile_nonstatic_field(JavaThread, _thread_state, JavaThreadState) \
|
||||
nonstatic_field(JavaThread, _osthread, OSThread*) \
|
||||
@ -1983,7 +1983,7 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
||||
declare_toplevel_type(JavaThread*) \
|
||||
declare_toplevel_type(JavaThread *const *const) \
|
||||
declare_toplevel_type(java_lang_Class) \
|
||||
declare_integer_type(JavaThread::AsyncRequests) \
|
||||
declare_integer_type(JavaThread::AsyncExceptionCondition) \
|
||||
declare_integer_type(JavaThread::TerminatedTypes) \
|
||||
declare_toplevel_type(jbyte*) \
|
||||
declare_toplevel_type(jbyte**) \
|
||||
@ -2143,7 +2143,7 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
||||
/* Thread::SuspendFlags enum */ \
|
||||
/*****************************/ \
|
||||
\
|
||||
declare_constant(Thread::_has_async_exception) \
|
||||
declare_constant(JavaThread::_has_async_exception) \
|
||||
\
|
||||
/*******************/ \
|
||||
/* JavaThreadState */ \
|
||||
|
@ -55,8 +55,8 @@ public class Thread extends VMObject {
|
||||
Type typeThread = db.lookupType("Thread");
|
||||
Type typeJavaThread = db.lookupType("JavaThread");
|
||||
|
||||
suspendFlagsField = typeThread.getCIntegerField("_suspend_flags");
|
||||
HAS_ASYNC_EXCEPTION = db.lookupIntConstant("Thread::_has_async_exception").intValue();
|
||||
suspendFlagsField = typeJavaThread.getCIntegerField("_suspend_flags");
|
||||
HAS_ASYNC_EXCEPTION = db.lookupIntConstant("JavaThread::_has_async_exception").intValue();
|
||||
|
||||
tlabFieldOffset = typeThread.getField("_tlab").getOffset();
|
||||
activeHandlesField = typeThread.getAddressField("_active_handles");
|
||||
|
Loading…
Reference in New Issue
Block a user