Skip to content

Commit 0d80f6c

Browse files
committed
8274379: Allow process of unsafe access errors in check_special_condition_for_native_trans
Reviewed-by: rehn, dholmes
1 parent b870468 commit 0d80f6c

File tree

7 files changed

+42
-74
lines changed

7 files changed

+42
-74
lines changed

src/hotspot/share/prims/jvm.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2961,7 +2961,7 @@ JVM_ENTRY(void, JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable))
29612961
THROW_OOP(java_throwable);
29622962
} else {
29632963
// Use a VM_Operation to throw the exception.
2964-
JavaThread::send_async_exception(java_thread, java_throwable);
2964+
JavaThread::send_async_exception(receiver, java_throwable);
29652965
}
29662966
} else {
29672967
// Either:

src/hotspot/share/prims/jvmtiEnv.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1072,7 +1072,7 @@ JvmtiEnv::StopThread(JavaThread* java_thread, jobject exception) {
10721072
oop e = JNIHandles::resolve_external_guard(exception);
10731073
NULL_CHECK(e, JVMTI_ERROR_NULL_POINTER);
10741074

1075-
JavaThread::send_async_exception(java_thread->threadObj(), e);
1075+
JavaThread::send_async_exception(java_thread, e);
10761076

10771077
return JVMTI_ERROR_NONE;
10781078

src/hotspot/share/runtime/safepoint.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ class SafepointSynchronize : AllStatic {
131131
switch(state) {
132132
case _thread_in_vm:
133133
case _thread_in_Java: // From compiled code
134-
case _thread_in_native_trans:
135134
case _thread_blocked_trans:
136135
return true;
137136
default:

src/hotspot/share/runtime/thread.cpp

Lines changed: 18 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,8 +1001,10 @@ JavaThread::JavaThread() :
10011001
_monitor_chunks(nullptr),
10021002

10031003
_suspend_flags(0),
1004-
_async_exception_condition(_no_async_condition),
10051004
_pending_async_exception(nullptr),
1005+
#ifdef ASSERT
1006+
_is_unsafe_access_error(false),
1007+
#endif
10061008

10071009
_thread_state(_thread_new),
10081010
_saved_exception_pc(nullptr),
@@ -1572,9 +1574,6 @@ void JavaThread::remove_monitor_chunk(MonitorChunk* chunk) {
15721574

15731575
// Asynchronous exceptions support
15741576
//
1575-
// Note: this function shouldn't block if it's called in
1576-
// _thread_in_native_trans state (such as from
1577-
// check_special_condition_for_native_trans()).
15781577
void JavaThread::check_and_handle_async_exceptions() {
15791578
if (has_last_Java_frame() && has_async_exception_condition()) {
15801579
// If we are at a polling page safepoint (not a poll return)
@@ -1600,21 +1599,12 @@ void JavaThread::check_and_handle_async_exceptions() {
16001599
}
16011600
}
16021601

1603-
AsyncExceptionCondition condition = clear_async_exception_condition();
1604-
if (condition == _no_async_condition) {
1605-
// Conditions have changed since has_special_runtime_exit_condition()
1606-
// was called:
1607-
// - if we were here only because of an external suspend request,
1608-
// then that was taken care of above (or cancelled) so we are done
1609-
// - if we were here because of another async request, then it has
1610-
// been cleared between the has_special_runtime_exit_condition()
1611-
// and now so again we are done
1602+
if (!clear_async_exception_condition()) {
16121603
return;
16131604
}
16141605

1615-
// Check for pending async. exception
16161606
if (_pending_async_exception != NULL) {
1617-
// Only overwrite an already pending exception, if it is not a threadDeath.
1607+
// Only overwrite an already pending exception if it is not a threadDeath.
16181608
if (!has_pending_exception() || !pending_exception()->is_a(vmClasses::ThreadDeath_klass())) {
16191609

16201610
// We cannot call Exceptions::_throw(...) here because we cannot block
@@ -1631,25 +1621,23 @@ void JavaThread::check_and_handle_async_exceptions() {
16311621
}
16321622
ls.print_cr(" of type: %s", _pending_async_exception->klass()->external_name());
16331623
}
1634-
_pending_async_exception = NULL;
1635-
// Clear condition from _suspend_flags since we have finished processing it.
1636-
clear_suspend_flag(_has_async_exception);
16371624
}
1638-
}
1625+
// Always null out the _pending_async_exception oop here since the async condition was
1626+
// already cleared above and thus considered handled.
1627+
_pending_async_exception = NULL;
1628+
} else {
1629+
assert(_is_unsafe_access_error, "must be");
1630+
DEBUG_ONLY(_is_unsafe_access_error = false);
16391631

1640-
if (condition == _async_unsafe_access_error && !has_pending_exception()) {
16411632
// We may be at method entry which requires we save the do-not-unlock flag.
16421633
UnlockFlagSaver fs(this);
16431634
switch (thread_state()) {
16441635
case _thread_in_vm: {
16451636
JavaThread* THREAD = this;
16461637
Exceptions::throw_unsafe_access_internal_error(THREAD, __FILE__, __LINE__, "a fault occurred in an unsafe memory access operation");
1647-
return;
1648-
}
1649-
case _thread_in_native: {
1650-
ThreadInVMfromNative tiv(this);
1651-
JavaThread* THREAD = this;
1652-
Exceptions::throw_unsafe_access_internal_error(THREAD, __FILE__, __LINE__, "a fault occurred in an unsafe memory access operation");
1638+
// We might have blocked in a ThreadBlockInVM wrapper in the call above so make sure we process pending
1639+
// suspend requests and object reallocation operations if any since we might be going to Java after this.
1640+
SafepointMechanism::process_if_requested_with_exit_check(this, true /* check asyncs */);
16531641
return;
16541642
}
16551643
case _thread_in_Java: {
@@ -1662,8 +1650,6 @@ void JavaThread::check_and_handle_async_exceptions() {
16621650
ShouldNotReachHere();
16631651
}
16641652
}
1665-
1666-
assert(has_pending_exception(), "must have handled the async condition if no exception");
16671653
}
16681654

16691655
void JavaThread::handle_special_runtime_exit_condition(bool check_asyncs) {
@@ -1696,9 +1682,8 @@ class InstallAsyncExceptionClosure : public HandshakeClosure {
16961682
}
16971683
};
16981684

1699-
void JavaThread::send_async_exception(oop java_thread, oop java_throwable) {
1685+
void JavaThread::send_async_exception(JavaThread* target, oop java_throwable) {
17001686
Handle throwable(Thread::current(), java_throwable);
1701-
JavaThread* target = java_lang_Thread::thread(java_thread);
17021687
InstallAsyncExceptionClosure vm_stop(throwable);
17031688
Handshake::execute(&vm_stop, target);
17041689
}
@@ -1847,21 +1832,17 @@ void JavaThread::check_special_condition_for_native_trans(JavaThread *thread) {
18471832
assert(thread->thread_state() == _thread_in_native_trans, "wrong state");
18481833
assert(!thread->has_last_Java_frame() || thread->frame_anchor()->walkable(), "Unwalkable stack in native->Java transition");
18491834

1835+
thread->set_thread_state(_thread_in_vm);
1836+
18501837
// Enable WXWrite: called directly from interpreter native wrapper.
18511838
MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, thread));
18521839

1853-
SafepointMechanism::process_if_requested_with_exit_check(thread, false /* check asyncs */);
1840+
SafepointMechanism::process_if_requested_with_exit_check(thread, true /* check asyncs */);
18541841

18551842
// After returning from native, it could be that the stack frames are not
18561843
// yet safe to use. We catch such situations in the subsequent stack watermark
18571844
// barrier, which will trap unsafe stack frames.
18581845
StackWatermarkSet::before_unwind(thread);
1859-
1860-
if (thread->has_async_exception_condition(false /* check unsafe access error */)) {
1861-
// We are in _thread_in_native_trans state, don't handle unsafe
1862-
// access error since that may block.
1863-
thread->check_and_handle_async_exceptions();
1864-
}
18651846
}
18661847

18671848
#ifndef PRODUCT

src/hotspot/share/runtime/thread.hpp

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -802,37 +802,21 @@ class JavaThread: public Thread {
802802

803803
// Asynchronous exceptions support
804804
private:
805-
enum AsyncExceptionCondition {
806-
_no_async_condition = 0,
807-
_async_exception,
808-
_async_unsafe_access_error
809-
};
810-
AsyncExceptionCondition _async_exception_condition;
811-
oop _pending_async_exception;
812-
813-
void set_async_exception_condition(AsyncExceptionCondition aec) { _async_exception_condition = aec; }
814-
AsyncExceptionCondition clear_async_exception_condition() {
815-
AsyncExceptionCondition x = _async_exception_condition;
816-
_async_exception_condition = _no_async_condition;
817-
return x;
818-
}
805+
oop _pending_async_exception;
806+
#ifdef ASSERT
807+
bool _is_unsafe_access_error;
808+
#endif
819809

810+
inline bool clear_async_exception_condition();
820811
public:
821-
bool has_async_exception_condition(bool check_unsafe_access_error = true) {
822-
return check_unsafe_access_error ? _async_exception_condition != _no_async_condition
823-
: _async_exception_condition == _async_exception;
812+
bool has_async_exception_condition() {
813+
return (_suspend_flags & _has_async_exception) != 0;
824814
}
825815
inline void set_pending_async_exception(oop e);
826-
void set_pending_unsafe_access_error() {
827-
// Don't overwrite an asynchronous exception sent by another thread
828-
if (_async_exception_condition == _no_async_condition) {
829-
set_async_exception_condition(_async_unsafe_access_error);
830-
}
831-
}
832-
void check_and_handle_async_exceptions();
833-
// Installs a pending exception to be inserted later
834-
static void send_async_exception(oop thread_oop, oop java_throwable);
816+
inline void set_pending_unsafe_access_error();
817+
static void send_async_exception(JavaThread* jt, oop java_throwable);
835818
void send_thread_stop(oop throwable);
819+
void check_and_handle_async_exceptions();
836820

837821
// Safepoint support
838822
public: // Expose _thread_state for SafeFetchInt()
@@ -1177,8 +1161,7 @@ class JavaThread: public Thread {
11771161
// Return true if JavaThread has an asynchronous condition or
11781162
// if external suspension is requested.
11791163
bool has_special_runtime_exit_condition() {
1180-
return (_async_exception_condition != _no_async_condition) ||
1181-
(_suspend_flags & (_obj_deopt JFR_ONLY(| _trace_flag))) != 0;
1164+
return (_suspend_flags & (_has_async_exception | _obj_deopt JFR_ONLY(| _trace_flag))) != 0;
11821165
}
11831166

11841167
// Fast-locking support

src/hotspot/share/runtime/thread.inline.hpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,22 @@ inline void JavaThread::clear_obj_deopt_flag() {
122122
clear_suspend_flag(_obj_deopt);
123123
}
124124

125+
inline bool JavaThread::clear_async_exception_condition() {
126+
bool ret = has_async_exception_condition();
127+
clear_suspend_flag(_has_async_exception);
128+
return ret;
129+
}
130+
125131
inline void JavaThread::set_pending_async_exception(oop e) {
126132
_pending_async_exception = e;
127-
set_async_exception_condition(_async_exception);
128-
// Set _suspend_flags too so we save a comparison in the transition from native to Java
129-
// in the native wrappers. It will be cleared in check_and_handle_async_exceptions()
130-
// when we actually install the exception.
131133
set_suspend_flag(_has_async_exception);
132134
}
133135

136+
inline void JavaThread::set_pending_unsafe_access_error() {
137+
set_suspend_flag(_has_async_exception);
138+
DEBUG_ONLY(_is_unsafe_access_error = true);
139+
}
140+
134141
inline JavaThreadState JavaThread::thread_state() const {
135142
#if defined(PPC64) || defined (AARCH64)
136143
// Use membars when accessing volatile _thread_state. See

src/hotspot/share/runtime/vmStructs.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,6 @@
717717
nonstatic_field(JavaThread, _current_pending_monitor_is_from_java, bool) \
718718
volatile_nonstatic_field(JavaThread, _current_waiting_monitor, ObjectMonitor*) \
719719
volatile_nonstatic_field(JavaThread, _suspend_flags, uint32_t) \
720-
nonstatic_field(JavaThread, _async_exception_condition, JavaThread::AsyncExceptionCondition) \
721720
nonstatic_field(JavaThread, _pending_async_exception, oop) \
722721
volatile_nonstatic_field(JavaThread, _exception_oop, oop) \
723722
volatile_nonstatic_field(JavaThread, _exception_pc, address) \
@@ -1951,7 +1950,6 @@
19511950
declare_toplevel_type(JavaThread*) \
19521951
declare_toplevel_type(JavaThread *const *const) \
19531952
declare_toplevel_type(java_lang_Class) \
1954-
declare_integer_type(JavaThread::AsyncExceptionCondition) \
19551953
declare_integer_type(JavaThread::TerminatedTypes) \
19561954
declare_toplevel_type(jbyte*) \
19571955
declare_toplevel_type(jbyte**) \

0 commit comments

Comments
 (0)