@@ -418,6 +418,7 @@ JvmtiExport::get_jvmti_interface(JavaVM *jvm, void **penv, jint version) {
418418JvmtiThreadState*
419419JvmtiExport::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
18281829void 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