Skip to content

Commit 8cd4e7d

Browse files
committed
8365192: post_meth_exit should be in vm state when calling get_jvmti_thread_state
Reviewed-by: mdoerr, dholmes
1 parent f964039 commit 8cd4e7d

File tree

1 file changed

+35
-31
lines changed

1 file changed

+35
-31
lines changed

src/hotspot/share/prims/jvmtiExport.cpp

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ JvmtiExport::get_jvmti_interface(JavaVM *jvm, void **penv, jint version) {
418418
JvmtiThreadState*
419419
JvmtiExport::get_jvmti_thread_state(JavaThread *thread, bool allow_suspend) {
420420
assert(thread == JavaThread::current(), "must be current thread");
421+
assert(thread->thread_state() == _thread_in_vm, "thread should be in vm");
421422
if (thread->is_vthread_mounted() && thread->jvmti_thread_state() == nullptr) {
422423
JvmtiEventController::thread_started(thread);
423424
if (allow_suspend && thread->is_suspended()) {
@@ -1826,47 +1827,50 @@ void JvmtiExport::post_method_entry(JavaThread *thread, Method* method, frame cu
18261827
}
18271828

18281829
void JvmtiExport::post_method_exit(JavaThread* thread, Method* method, frame current_frame) {
1830+
// At this point we only have the address of a "raw result" and
1831+
// we just call into the interpreter to convert this into a jvalue.
1832+
// This method always makes transition to vm and back where GC can happen.
1833+
// So it is needed to preserve result and then restore it
1834+
// even if events are not actually posted.
1835+
// Saving oop_result into value.j is deferred until jvmti state is ready.
18291836
HandleMark hm(thread);
18301837
methodHandle mh(thread, method);
1831-
1832-
JvmtiThreadState *state = get_jvmti_thread_state(thread);
1833-
1834-
if (state == nullptr || !state->is_interp_only_mode()) {
1835-
// for any thread that actually wants method exit, interp_only_mode is set
1836-
return;
1837-
}
1838-
18391838
Handle result;
1839+
oop oop_result;
18401840
jvalue value;
18411841
value.j = 0L;
1842-
1843-
if (state->is_enabled(JVMTI_EVENT_METHOD_EXIT)) {
1844-
// At this point we only have the address of a "raw result" and
1845-
// we just call into the interpreter to convert this into a jvalue.
1846-
oop oop_result;
1847-
BasicType type = current_frame.interpreter_frame_result(&oop_result, &value);
1848-
assert(type == T_VOID || current_frame.interpreter_frame_expression_stack_size() > 0,
1849-
"Stack shouldn't be empty");
1850-
if (is_reference_type(type)) {
1851-
result = Handle(thread, oop_result);
1852-
value.l = JNIHandles::make_local(thread, result());
1853-
}
1842+
BasicType type = current_frame.interpreter_frame_result(&oop_result, &value);
1843+
assert(mh->is_native() || type == T_VOID || current_frame.interpreter_frame_expression_stack_size() > 0,
1844+
"Stack shouldn't be empty");
1845+
if (is_reference_type(type)) {
1846+
result = Handle(thread, oop_result);
18541847
}
1855-
1856-
// Do not allow NotifyFramePop to add new FramePop event request at
1857-
// depth 0 as it is already late in the method exiting dance.
1858-
state->set_top_frame_is_exiting();
1859-
1860-
// Deferred transition to VM, so we can stash away the return oop before GC.
1848+
JvmtiThreadState* state; // should be initialized in vm state only
18611849
JavaThread* current = thread; // for JRT_BLOCK
1850+
bool interp_only; // might be changed in JRT_BLOCK_END
18621851
JRT_BLOCK
1863-
post_method_exit_inner(thread, mh, state, false /* not exception exit */, current_frame, value);
1864-
JRT_BLOCK_END
1852+
state = get_jvmti_thread_state(thread);
1853+
interp_only = state != nullptr && state->is_interp_only_mode();
1854+
if (interp_only) {
1855+
if (state->is_enabled(JVMTI_EVENT_METHOD_EXIT)) {
1856+
// Deferred saving Object result into value.
1857+
if (is_reference_type(type)) {
1858+
value.l = JNIHandles::make_local(thread, result());
1859+
}
1860+
}
18651861

1866-
// The JRT_BLOCK_END can safepoint in ThreadInVMfromJava desctructor. Now it is safe to allow
1867-
// adding FramePop event requests as no safepoint can happen before removing activation.
1868-
state->clr_top_frame_is_exiting();
1862+
// Do not allow NotifyFramePop to add new FramePop event request at
1863+
// depth 0 as it is already late in the method exiting dance.
1864+
state->set_top_frame_is_exiting();
18691865

1866+
post_method_exit_inner(thread, mh, state, false /* not exception exit */, current_frame, value);
1867+
}
1868+
JRT_BLOCK_END
1869+
if (interp_only) {
1870+
// The JRT_BLOCK_END can safepoint in ThreadInVMfromJava destructor. Now it is safe to allow
1871+
// adding FramePop event requests as no safepoint can happen before removing activation.
1872+
state->clr_top_frame_is_exiting();
1873+
}
18701874
if (result.not_null() && !mh->is_native()) {
18711875
// We have to restore the oop on the stack for interpreter frames
18721876
*(oop*)current_frame.interpreter_frame_tos_address() = result();

0 commit comments

Comments
 (0)