# HG changeset patch # User sla # Date 1399485823 -7200 # Wed May 07 20:03:43 2014 +0200 # Node ID f69ffdd2ea7b35669d423f2ee176978eface7677 # Parent 003c36658224b4225a16420517098f3db9bf1999 imported patch 8041934-method_exit diff --git a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -2657,6 +2657,28 @@ __ bind(done); } + { + // Normally we do not post method_entry and method_exit events from + // compiled code, only from the interpreter. If method_entry/exit + // events are switched on at runtime, we will deoptimize everything + // (see VM_EnterInterpOnlyMode) on the stack and call method_entry/exit + // from the interpreter. But when we do that, we will not deoptimize + // this native wrapper frame. Thus we have an extra check here to see + // if we are now in interp_only_mode and in that case we do the jvmti + // callback. + Label skip_jvmti_method_exit; + __ ld(G2_thread, JavaThread::interp_only_mode_offset(), G3_scratch); + __ cmp_and_br_short(G3_scratch, 0, Assembler::zero, Assembler::pt, skip_jvmti_method_exit); + + save_native_result(masm, ret_type, stack_slots); + __ set_metadata_constant(method(), O1); + __ call_VM_leaf(L7_thread_cache, + CAST_FROM_FN_PTR(address, SharedRuntime::jvmti_method_exit), + G2_thread, O1); + restore_native_result(masm, ret_type, stack_slots); + __ bind(skip_jvmti_method_exit); + } + // Tell dtrace about this method exit { SkipIfEqual skip_if( diff --git a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -2239,6 +2239,28 @@ } { + // Normally we do not post method_entry and method_exit events from + // compiled code, only from the interpreter. If method_entry/exit + // events are switched on at runtime, we will deoptimize everything + // (see VM_EnterInterpOnlyMode) on the stack and call method_entry/exit + // from the interpreter. But when we do that, we will not deoptimize + // this native wrapper frame. Thus we have an extra check here to see + // if we are now in interp_only_mode and in that case we do the jvmti + // callback. + Label skip_jvmti_method_exit; + __ cmpb(Address(thread, JavaThread::interp_only_mode_offset()), 0); + __ jccb(Assembler::zero, skip_jvmti_method_exit); + + save_native_result(masm, ret_type, stack_slots); + __ mov_metadata(rax, method()); + __ call_VM_leaf( + CAST_FROM_FN_PTR(address, SharedRuntime::jvmti_method_exit), + thread, rax); + restore_native_result(masm, ret_type, stack_slots); + __ bind(skip_jvmti_method_exit); + } + + { SkipIfEqual skip_if(masm, &DTraceMethodProbes, 0); // Tell dtrace about this method exit save_native_result(masm, ret_type, stack_slots); diff --git a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -2484,6 +2484,29 @@ __ bind(done); } + + { + // Normally we do not post method_entry and method_exit events from + // compiled code, only from the interpreter. If method_entry/exit + // events are switched on at runtime, we will deoptimize everything + // (see VM_EnterInterpOnlyMode) on the stack and call method_entry/exit + // from the interpreter. But when we do that, we will not deoptimize + // this native wrapper frame. Thus we have an extra check here to see + // if we are now in interp_only_mode and in that case we do the jvmti + // callback. + Label skip_jvmti_method_exit; + __ cmpb(Address(r15_thread, JavaThread::interp_only_mode_offset()), 0); + __ jccb(Assembler::zero, skip_jvmti_method_exit); + + save_native_result(masm, ret_type, stack_slots); + __ mov_metadata(c_rarg1, method()); + __ call_VM_leaf( + CAST_FROM_FN_PTR(address, SharedRuntime::jvmti_method_exit), + r15_thread, c_rarg1); + restore_native_result(masm, ret_type, stack_slots); + __ bind(skip_jvmti_method_exit); + } + { SkipIfEqual skip(masm, &DTraceMethodProbes, false); save_native_result(masm, ret_type, stack_slots); diff --git a/src/share/vm/runtime/sharedRuntime.cpp b/src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp +++ b/src/share/vm/runtime/sharedRuntime.cpp @@ -991,6 +991,12 @@ return 0; JRT_END +JRT_LEAF(int, SharedRuntime::jvmti_method_exit( + JavaThread* thread, Method* method)) + JvmtiExport::post_method_exit(thread, method, thread->last_frame()); + return 0; +JRT_END + // Finds receiver, CallInfo (i.e. receiver method), and calling bytecode) // for a call current in progress, i.e., arguments has been pushed on stack diff --git a/src/share/vm/runtime/sharedRuntime.hpp b/src/share/vm/runtime/sharedRuntime.hpp --- a/src/share/vm/runtime/sharedRuntime.hpp +++ b/src/share/vm/runtime/sharedRuntime.hpp @@ -263,6 +263,9 @@ static int dtrace_method_entry(JavaThread* thread, Method* m); static int dtrace_method_exit(JavaThread* thread, Method* m); + // jvmti notification + static int jvmti_method_exit(JavaThread* thread, Method* m); + // Utility method for retrieving the Java thread id, returns 0 if the // thread is not a well formed Java thread. static jlong get_java_tid(Thread* thread);