Skip to content
Permalink
Browse files
8265934: Cleanup _suspend_flags and _special_runtime_exit_condition
Reviewed-by: rehn, dcubed, dholmes
  • Loading branch information
pchilano committed May 13, 2021
1 parent f3c6cda commit 853ffdb25c76637555fa732f5e05024243747a70
@@ -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;

1 comment on commit 853ffdb

@openjdk-notifier

This comment has been minimized.

Copy link

@openjdk-notifier openjdk-notifier bot commented on 853ffdb May 13, 2021

Please sign in to comment.