diff --git a/vm/vmcore/src/jit/ini.cpp b/vm/vmcore/src/jit/ini.cpp index 2bdf2b1..93c6863 100644 --- a/vm/vmcore/src/jit/ini.cpp +++ b/vm/vmcore/src/jit/ini.cpp @@ -57,11 +57,24 @@ vm_execute_java_method_array(jmethodID m VM_Global_State::loader_env->em_interface->ExecuteMethod(method, result, args); //DEBUG_POP_LOCK(JAVA_CODE_PSEUDO_LOCK); - // gregory - When method executes *return bytecode in Java it will - // set a breakpoint on the bytecode after invoke* or another - // bytecode which caused managed to VM transition. This is a - // general case of *return handling. So it seems here we don't - // have to do anything, *return handling will set a breakpoint up - // the stack in java automatically. -} + // Return from native code. It is necessary to set up a breakpoint + // in the method which called us + if (ti->isEnabled() && ti->is_single_step_enabled() && + ti->getPhase() == JVMTI_PHASE_LIVE) + { + VM_thread *vm_thread = p_TLS_vmthread; + if (NULL != vm_thread->ss_state) + { + LMAutoUnlock lock(ti->vm_brpt->get_lock()); + + jvmti_StepLocation *method_return; + unsigned locations_number; + + jvmtiError errorCode = jvmti_get_next_bytecodes_from_native( + vm_thread, &method_return, &locations_number, false); + assert (JVMTI_ERROR_NONE == errorCode); + jvmti_set_single_step_breakpoints(ti , vm_thread, method_return, locations_number); + } + } +} diff --git a/vm/vmcore/src/jvmti/jvmti_step.cpp b/vm/vmcore/src/jvmti/jvmti_step.cpp index 8c8eade..4956b5a 100644 --- a/vm/vmcore/src/jvmti/jvmti_step.cpp +++ b/vm/vmcore/src/jvmti/jvmti_step.cpp @@ -714,7 +714,14 @@ jvmtiError jvmti_get_next_bytecodes_from return JVMTI_ERROR_NONE; } - assert(!si_is_native(si)); + if (si_is_native(si)) + { + // We are called from native code, nothing to be done + // here. The bytecode which called us will be instrumented + // when we return back to java in vm_execute_java_method_array + return JVMTI_ERROR_NONE; + } + if( invoked_frame ) { // get previous stack frame si_goto_previous(si);