@@ -1543,16 +1543,12 @@ void JvmtiExport::post_method_entry(JavaThread *thread, Method* method, frame cu
15431543 }
15441544}
15451545
1546- void JvmtiExport::post_method_exit (JavaThread * thread, Method* method, frame current_frame) {
1546+ void JvmtiExport::post_method_exit (JavaThread* thread, Method* method, frame current_frame) {
15471547 HandleMark hm (thread);
15481548 methodHandle mh (thread, method);
15491549
1550- EVT_TRIG_TRACE (JVMTI_EVENT_METHOD_EXIT, (" [%s] Trg Method Exit triggered %s.%s" ,
1551- JvmtiTrace::safe_get_thread_name (thread),
1552- (mh () == NULL ) ? " NULL" : mh ()->klass_name ()->as_C_string (),
1553- (mh () == NULL ) ? " NULL" : mh ()->name ()->as_C_string () ));
1554-
15551550 JvmtiThreadState *state = thread->jvmti_thread_state ();
1551+
15561552 if (state == NULL || !state->is_interp_only_mode ()) {
15571553 // for any thread that actually wants method exit, interp_only_mode is set
15581554 return ;
@@ -1561,13 +1557,11 @@ void JvmtiExport::post_method_exit(JavaThread *thread, Method* method, frame cur
15611557 // return a flag when a method terminates by throwing an exception
15621558 // i.e. if an exception is thrown and it's not caught by the current method
15631559 bool exception_exit = state->is_exception_detected () && !state->is_exception_caught ();
1564-
1560+ Handle result;
1561+ jvalue value;
1562+ value.j = 0L ;
15651563
15661564 if (state->is_enabled (JVMTI_EVENT_METHOD_EXIT)) {
1567- Handle result;
1568- jvalue value;
1569- value.j = 0L ;
1570-
15711565 // if the method hasn't been popped because of an exception then we populate
15721566 // the return_value parameter for the callback. At this point we only have
15731567 // the address of a "raw result" and we just call into the interpreter to
@@ -1577,9 +1571,36 @@ void JvmtiExport::post_method_exit(JavaThread *thread, Method* method, frame cur
15771571 BasicType type = current_frame.interpreter_frame_result (&oop_result, &value);
15781572 if (type == T_OBJECT || type == T_ARRAY) {
15791573 result = Handle (thread, oop_result);
1574+ value.l = JNIHandles::make_local (thread, result ());
15801575 }
15811576 }
1577+ }
15821578
1579+ // Deferred transition to VM, so we can stash away the return oop before GC
1580+ // Note that this transition is not needed when throwing an exception, because
1581+ // there is no oop to retain.
1582+ JRT_BLOCK
1583+ post_method_exit_inner (thread, mh, state, exception_exit, current_frame, value);
1584+ JRT_BLOCK_END
1585+
1586+ if (result.not_null () && !mh->is_native ()) {
1587+ // We have to restore the oop on the stack for interpreter frames
1588+ *(oop*)current_frame.interpreter_frame_tos_address () = result ();
1589+ }
1590+ }
1591+
1592+ void JvmtiExport::post_method_exit_inner (JavaThread* thread,
1593+ methodHandle& mh,
1594+ JvmtiThreadState *state,
1595+ bool exception_exit,
1596+ frame current_frame,
1597+ jvalue& value) {
1598+ EVT_TRIG_TRACE (JVMTI_EVENT_METHOD_EXIT, (" [%s] Trg Method Exit triggered %s.%s" ,
1599+ JvmtiTrace::safe_get_thread_name (thread),
1600+ (mh () == NULL ) ? " NULL" : mh ()->klass_name ()->as_C_string (),
1601+ (mh () == NULL ) ? " NULL" : mh ()->name ()->as_C_string () ));
1602+
1603+ if (state->is_enabled (JVMTI_EVENT_METHOD_EXIT)) {
15831604 JvmtiEnvThreadStateIterator it (state);
15841605 for (JvmtiEnvThreadState* ets = it.first (); ets != NULL ; ets = it.next (ets)) {
15851606 if (ets->is_enabled (JVMTI_EVENT_METHOD_EXIT)) {
@@ -1590,9 +1611,6 @@ void JvmtiExport::post_method_exit(JavaThread *thread, Method* method, frame cur
15901611
15911612 JvmtiEnv *env = ets->get_env ();
15921613 JvmtiMethodEventMark jem (thread, mh);
1593- if (result.not_null ()) {
1594- value.l = JNIHandles::make_local (thread, result ());
1595- }
15961614 JvmtiJavaThreadEventTransition jet (thread);
15971615 jvmtiEventMethodExit callback = env->callbacks ()->MethodExit ;
15981616 if (callback != NULL ) {
@@ -1781,7 +1799,9 @@ void JvmtiExport::notice_unwind_due_to_exception(JavaThread *thread, Method* met
17811799 if (state->is_interp_only_mode ()) {
17821800 // method exit and frame pop events are posted only in interp mode.
17831801 // When these events are enabled code should be in running in interp mode.
1784- JvmtiExport::post_method_exit (thread, method, thread->last_frame ());
1802+ jvalue no_value;
1803+ no_value.j = 0L ;
1804+ JvmtiExport::post_method_exit_inner (thread, mh, state, true , thread->last_frame (), no_value);
17851805 // The cached cur_stack_depth might have changed from the
17861806 // operations of frame pop or method exit. We are not 100% sure
17871807 // the cached cur_stack_depth is still valid depth so invalidate
0 commit comments