@@ -1560,16 +1560,12 @@ void JvmtiExport::post_method_entry(JavaThread *thread, Method* method, frame cu
1560
1560
}
1561
1561
}
1562
1562
1563
- void JvmtiExport::post_method_exit (JavaThread * thread, Method* method, frame current_frame) {
1563
+ void JvmtiExport::post_method_exit (JavaThread* thread, Method* method, frame current_frame) {
1564
1564
HandleMark hm (thread);
1565
1565
methodHandle mh (thread, method);
1566
1566
1567
- EVT_TRIG_TRACE (JVMTI_EVENT_METHOD_EXIT, (" [%s] Trg Method Exit triggered %s.%s" ,
1568
- JvmtiTrace::safe_get_thread_name (thread),
1569
- (mh () == NULL ) ? " NULL" : mh ()->klass_name ()->as_C_string (),
1570
- (mh () == NULL ) ? " NULL" : mh ()->name ()->as_C_string () ));
1571
-
1572
1567
JvmtiThreadState *state = thread->jvmti_thread_state ();
1568
+
1573
1569
if (state == NULL || !state->is_interp_only_mode ()) {
1574
1570
// for any thread that actually wants method exit, interp_only_mode is set
1575
1571
return ;
@@ -1578,13 +1574,11 @@ void JvmtiExport::post_method_exit(JavaThread *thread, Method* method, frame cur
1578
1574
// return a flag when a method terminates by throwing an exception
1579
1575
// i.e. if an exception is thrown and it's not caught by the current method
1580
1576
bool exception_exit = state->is_exception_detected () && !state->is_exception_caught ();
1581
-
1577
+ Handle result;
1578
+ jvalue value;
1579
+ value.j = 0L ;
1582
1580
1583
1581
if (state->is_enabled (JVMTI_EVENT_METHOD_EXIT)) {
1584
- Handle result;
1585
- jvalue value;
1586
- value.j = 0L ;
1587
-
1588
1582
// if the method hasn't been popped because of an exception then we populate
1589
1583
// the return_value parameter for the callback. At this point we only have
1590
1584
// the address of a "raw result" and we just call into the interpreter to
@@ -1594,9 +1588,36 @@ void JvmtiExport::post_method_exit(JavaThread *thread, Method* method, frame cur
1594
1588
BasicType type = current_frame.interpreter_frame_result (&oop_result, &value);
1595
1589
if (is_reference_type (type)) {
1596
1590
result = Handle (thread, oop_result);
1591
+ value.l = JNIHandles::make_local (thread, result ());
1597
1592
}
1598
1593
}
1594
+ }
1599
1595
1596
+ // Deferred transition to VM, so we can stash away the return oop before GC
1597
+ // Note that this transition is not needed when throwing an exception, because
1598
+ // there is no oop to retain.
1599
+ JRT_BLOCK
1600
+ post_method_exit_inner (thread, mh, state, exception_exit, current_frame, value);
1601
+ JRT_BLOCK_END
1602
+
1603
+ if (result.not_null () && !mh->is_native ()) {
1604
+ // We have to restore the oop on the stack for interpreter frames
1605
+ *(oop*)current_frame.interpreter_frame_tos_address () = result ();
1606
+ }
1607
+ }
1608
+
1609
+ void JvmtiExport::post_method_exit_inner (JavaThread* thread,
1610
+ methodHandle& mh,
1611
+ JvmtiThreadState *state,
1612
+ bool exception_exit,
1613
+ frame current_frame,
1614
+ jvalue& value) {
1615
+ EVT_TRIG_TRACE (JVMTI_EVENT_METHOD_EXIT, (" [%s] Trg Method Exit triggered %s.%s" ,
1616
+ JvmtiTrace::safe_get_thread_name (thread),
1617
+ (mh () == NULL ) ? " NULL" : mh ()->klass_name ()->as_C_string (),
1618
+ (mh () == NULL ) ? " NULL" : mh ()->name ()->as_C_string () ));
1619
+
1620
+ if (state->is_enabled (JVMTI_EVENT_METHOD_EXIT)) {
1600
1621
JvmtiEnvThreadStateIterator it (state);
1601
1622
for (JvmtiEnvThreadState* ets = it.first (); ets != NULL ; ets = it.next (ets)) {
1602
1623
if (ets->is_enabled (JVMTI_EVENT_METHOD_EXIT)) {
@@ -1607,9 +1628,6 @@ void JvmtiExport::post_method_exit(JavaThread *thread, Method* method, frame cur
1607
1628
1608
1629
JvmtiEnv *env = ets->get_env ();
1609
1630
JvmtiMethodEventMark jem (thread, mh);
1610
- if (result.not_null ()) {
1611
- value.l = JNIHandles::make_local (thread, result ());
1612
- }
1613
1631
JvmtiJavaThreadEventTransition jet (thread);
1614
1632
jvmtiEventMethodExit callback = env->callbacks ()->MethodExit ;
1615
1633
if (callback != NULL ) {
@@ -1801,7 +1819,9 @@ void JvmtiExport::notice_unwind_due_to_exception(JavaThread *thread, Method* met
1801
1819
if (state->is_interp_only_mode ()) {
1802
1820
// method exit and frame pop events are posted only in interp mode.
1803
1821
// When these events are enabled code should be in running in interp mode.
1804
- JvmtiExport::post_method_exit (thread, method, thread->last_frame ());
1822
+ jvalue no_value;
1823
+ no_value.j = 0L ;
1824
+ JvmtiExport::post_method_exit_inner (thread, mh, state, true , thread->last_frame (), no_value);
1805
1825
// The cached cur_stack_depth might have changed from the
1806
1826
// operations of frame pop or method exit. We are not 100% sure
1807
1827
// the cached cur_stack_depth is still valid depth so invalidate
0 commit comments