diff --git a/vm/vmcore/include/jvmti_internal.h b/vm/vmcore/include/jvmti_internal.h index 465d02c..e68bfea 100644 --- a/vm/vmcore/include/jvmti_internal.h +++ b/vm/vmcore/include/jvmti_internal.h @@ -316,12 +316,33 @@ class DebugUtilsTI { return NULL; } - BreakPoint *get_other_breakpoint_same_location(jmethodID m, jlocation l) + BreakPoint *get_other_breakpoint_same_location(BreakPoint *this_bp) { // assert(brkpntlst_lock._lock_or_null()); for (BreakPoint *bp = brkpntlst; NULL != bp; bp = bp->next) - if (bp->method == m && bp->location == l) + if (bp != this_bp && + bp->method == this_bp->method && bp->location == this_bp->location) + return bp; + + return NULL; + } + + BreakPoint *get_other_breakpoint_same_native_location(BreakPoint *this_bp) + { + // assert(brkpntlst_lock._lock_or_null()); + + for (BreakPoint *bp = brkpntlst; NULL != bp; bp = bp->next) + if (bp != this_bp && bp->native_location == this_bp->native_location) + return bp; + + return NULL; + } + + BreakPoint *get_breakpoint_from_location(jmethodID method, jlocation location) + { + for (BreakPoint *bp = brkpntlst; NULL != bp; bp = bp->next) + if (bp->method == method && bp->location == location) return bp; return NULL; @@ -503,8 +524,8 @@ jint load_agentlib(Agent *agent, const c jint load_agentpath(Agent *agent, const char *str, JavaVM_Internal *vm); // Breakpoints internal functions -jvmtiError jvmti_get_next_bytecodes_up_stack_from_native(VM_thread *thread, - jvmti_StepLocation **next_step, unsigned *count); +jvmtiError jvmti_get_next_bytecodes_stack_from_native(VM_thread *thread, + jvmti_StepLocation **next_step, unsigned *count, bool step_up); jvmtiError jvmti_set_breakpoint_for_jit(DebugUtilsTI *ti, BreakPoint *bp); void jvmti_remove_breakpoint_for_jit(DebugUtilsTI *ti, BreakPoint *bp); jvmtiError jvmti_set_single_step_breakpoints(DebugUtilsTI *ti, diff --git a/vm/vmcore/src/exception/exceptions_jit.cpp b/vm/vmcore/src/exception/exceptions_jit.cpp index 534cd5f..803b7dd 100644 --- a/vm/vmcore/src/exception/exceptions_jit.cpp +++ b/vm/vmcore/src/exception/exceptions_jit.cpp @@ -299,12 +299,14 @@ #endif // VM_STATS } } + BEGIN_RAISE_AREA; // Reload exception object pointer because it could have // moved while calling JVMTI callback *exn_obj = jvmti_jit_exception_event_callback_call(*exn_obj, interrupted_method_jit, interrupted_method, interrupted_method_location, jit, method, handler->get_handler_ip()); + END_RAISE_AREA; TRACE2("exn", ("setting return pointer to %d", exn_obj)); diff --git a/vm/vmcore/src/jvmti/jvmti_break.cpp b/vm/vmcore/src/jvmti/jvmti_break.cpp index adfc19a..9c1d504 100644 --- a/vm/vmcore/src/jvmti/jvmti_break.cpp +++ b/vm/vmcore/src/jvmti/jvmti_break.cpp @@ -34,6 +34,7 @@ #include "suspend_checker.h" #include "jit_intf_cpp.h" #include "encoder.h" #include "m2n.h" +#include "exceptions.h" #define INSTRUMENTATION_BYTE_HLT 0xf4 // HLT instruction @@ -51,7 +52,10 @@ #include "open/hythread_ext.h" VMEXPORT void* jvmti_process_interpreter_breakpoint_event(jmethodID method, jlocation location) { - TRACE2("jvmti.break", "BREAKPOINT occured, location = " << location); + TRACE2("jvmti.break", "BREAKPOINT occured: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) << method_get_descriptor((Method*)method) + << " :" << location); ObjectHandle hThread = oh_allocate_local_handle(); hThread->object = (Java_java_lang_Thread *)jthread_get_java_thread(hythread_self())->object; tmn_suspend_enable(); @@ -76,15 +80,21 @@ jvmti_process_interpreter_breakpoint_eve if (NULL != func) { JNIEnv *jni_env = (JNIEnv *)jni_native_intf; - TRACE2("jvmti.break", "Calling interpreter global breakpoint callback method = " << - ((Method*)method)->get_name() << " location = " << location); + TRACE2("jvmti.break", "Calling interpreter global breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location); ti->brkpntlst_lock._unlock(); func((jvmtiEnv*)env, jni_env, (jthread)hThread, method, location); ti->brkpntlst_lock._lock(); - TRACE2("jvmti.break", "Finished interpreter global breakpoint callback method = " << - ((Method*)method)->get_name() << " location = " << location); + TRACE2("jvmti.break", "Finished interpreter global breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location); } bp = next_bp; continue; // Don't send local events @@ -101,15 +111,21 @@ jvmti_process_interpreter_breakpoint_eve if (NULL != func) { JNIEnv *jni_env = (JNIEnv *)jni_native_intf; - TRACE2("jvmti.break", "Calling interpreter local breakpoint callback method = " << - ((Method*)method)->get_name() << " location = " << location); + TRACE2("jvmti.break", "Calling interpreter local breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location); ti->brkpntlst_lock._unlock(); func((jvmtiEnv*)env, jni_env, (jthread)hThread, method, location); ti->brkpntlst_lock._lock(); - TRACE2("jvmti.break", "Finished interpreter local breakpoint callback method = " << - ((Method*)method)->get_name() << " location = " << location); + TRACE2("jvmti.break", "Finished interpreter local breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location); } } @@ -133,6 +149,32 @@ ConditionCode get_condition_code(Instruc return (ConditionCode)jump_type; } +static BreakPoint * +jvmti_check_and_get_single_step_breakpoint( DebugUtilsTI *ti, + VM_thread *vm_thread, + NativeCodePtr native_location) +{ + BreakPoint *ss_breakpoint = NULL; + + if (ti->is_single_step_enabled()) + { + if (NULL != vm_thread->ss_state) + { + for(unsigned iii = 0; iii < vm_thread->ss_state->predicted_bp_count; iii++) + { + if (vm_thread->ss_state->predicted_breakpoints[iii]->native_location == + native_location) + { + assert(!ss_breakpoint); + ss_breakpoint = + vm_thread->ss_state->predicted_breakpoints[iii]; + } + } + } + } + return ss_breakpoint; +} // jvmti_check_and_get_single_step_breakpoint + bool jvmti_send_jit_breakpoint_event(Registers *regs) { #if PLATFORM_POSIX && INSTRUMENTATION_BYTE == INSTRUMENTATION_BYTE_INT3 @@ -142,7 +184,7 @@ #else NativeCodePtr native_location = (NativeCodePtr)regs->get_ip(); #endif - TRACE2("jvmti.break", "BREAKPOINT occured, location = " << native_location); + TRACE2("jvmti.break", "BREAKPOINT occured: " << native_location); DebugUtilsTI *ti = VM_Global_State::loader_env->TI; if (!ti->isEnabled() || ti->getPhase() != JVMTI_PHASE_LIVE) @@ -160,6 +202,7 @@ #endif assert(!interpreter_enabled()); M2nFrame *m2nf = m2n_push_suspended_frame(regs); + BEGIN_RAISE_AREA; hythread_t h_thread = hythread_self(); jthread j_thread = jthread_get_java_thread(h_thread); @@ -174,76 +217,80 @@ #endif InstructionDisassembler idisasm(*bp->disasm); JNIEnv *jni_env = (JNIEnv *)jni_native_intf; - BreakPoint *ss_breakpoint = NULL; + VM_thread *vm_thread = p_TLS_vmthread; + BreakPoint *ss_breakpoint = jvmti_check_and_get_single_step_breakpoint( ti, + vm_thread, native_location ); // Check if there are Single Step type breakpoints in TLS - if (ti->is_single_step_enabled()) + if (ss_breakpoint) { - VM_thread *vm_thread = p_TLS_vmthread; - if (NULL != vm_thread->ss_state) + TIEnv *ti_env = ti->getEnvironments(); + TIEnv *next_env; + jlocation location = ss_breakpoint->location; + jmethodID method = ss_breakpoint->method; + + while (NULL != ti_env) { - for(unsigned iii = 0; NULL != vm_thread->ss_state && - iii < vm_thread->ss_state->predicted_bp_count; iii++) + next_env = ti_env->next; + jvmtiEventSingleStep func = + (jvmtiEventSingleStep)ti_env->get_event_callback(JVMTI_EVENT_SINGLE_STEP); + if (NULL != func) { - if (vm_thread->ss_state->predicted_breakpoints[iii]->native_location == - native_location) + if (ti_env->global_events[JVMTI_EVENT_SINGLE_STEP - JVMTI_MIN_EVENT_TYPE_VAL]) { - ss_breakpoint = - vm_thread->ss_state->predicted_breakpoints[iii]; - - TIEnv *ti_env = ti->getEnvironments(); - TIEnv *next_env; - jlocation location = ss_breakpoint->location; - jmethodID method = ss_breakpoint->method; + TRACE2("jvmti.break.ss", + "Calling JIT global SingleStep breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location << " :" << native_location); + // fire global event + ti->brkpntlst_lock._unlock(); + func((jvmtiEnv*)ti_env, jni_env, (jthread)hThread, method, location); + ti->brkpntlst_lock._lock(); + TRACE2("jvmti.break.ss", + "Finished JIT global SingleStep breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location << " :" << native_location); + ti_env = next_env; + continue; + } - while (NULL != ti_env) + TIEventThread* next_ti_et; + // fire local events + for(TIEventThread* ti_et = ti_env->event_threads[JVMTI_EVENT_SINGLE_STEP - JVMTI_MIN_EVENT_TYPE_VAL]; + ti_et != NULL; ti_et = next_ti_et) + { + next_ti_et = ti_et->next; + if (ti_et->thread == hythread_self()) { - next_env = ti_env->next; - jvmtiEventSingleStep func = - (jvmtiEventSingleStep)ti_env->get_event_callback(JVMTI_EVENT_SINGLE_STEP); - if (NULL != func) - { - if (ti_env->global_events[JVMTI_EVENT_SINGLE_STEP - JVMTI_MIN_EVENT_TYPE_VAL]) - { - TRACE2("jvmti.break.ss", - "Calling JIT global SingleStep breakpoint callback method = " << - ((Method*)method)->get_name() << " location = " << location); - // fire global event - ti->brkpntlst_lock._unlock(); - func((jvmtiEnv*)ti_env, jni_env, (jthread)hThread, method, location); - ti->brkpntlst_lock._lock(); - TRACE2("jvmti.break.ss", - "Finished JIT global SingleStep breakpoint callback method = " << - ((Method*)method)->get_name() << " location = " << location); - ti_env = next_env; - continue; - } - - // fire local events - for(TIEventThread* ti_et = ti_env->event_threads[JVMTI_EVENT_SINGLE_STEP - JVMTI_MIN_EVENT_TYPE_VAL]; - ti_et != NULL; ti_et = ti_et->next) - if (ti_et->thread == hythread_self()) - { - TRACE2("jvmti.break.ss", - "Calling JIT local SingleStep breakpoint callback method = " << - ((Method*)method)->get_name() << " location = " << location); - ti->brkpntlst_lock._unlock(); - func((jvmtiEnv*)ti_env, jni_env, - (jthread)hThread, method, location); - ti->brkpntlst_lock._lock(); - TRACE2("jvmti.break.ss", - "Finished JIT local SingleStep breakpoint callback method = " << - ((Method*)method)->get_name() << " location = " << location); - } - } - ti_env = next_env; + TRACE2("jvmti.break.ss", + "Calling JIT local SingleStep breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location << " :" << native_location); + ti->brkpntlst_lock._unlock(); + func((jvmtiEnv*)ti_env, jni_env, + (jthread)hThread, method, location); + ti->brkpntlst_lock._lock(); + TRACE2("jvmti.break.ss", + "Finished JIT local SingleStep breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location << " :" << native_location); } } } - // Reinitialize breakpoint after SingleStep because this - // breakpoint could have been deleted inside of callback - // if agent terminated single step - bp = ti->find_first_bpt(native_location); + ti_env = next_env; } + + // Reinitialize breakpoint after SingleStep because this + // breakpoint could have been deleted inside of callback + // if agent terminated single step + bp = ti->find_first_bpt(native_location); } @@ -256,7 +303,8 @@ #endif jmethodID method = bp->method; BreakPoint *next_bp = ti->find_next_bpt(bp, native_location); - if (bp == ss_breakpoint) + // check if this is a single step breakpoint + if (!bp->env) { // Don't send breakpoint event for breakpoint which was // actually SingleStep breakpoint @@ -269,15 +317,21 @@ #endif jvmtiEventBreakpoint func = (jvmtiEventBreakpoint)env->get_event_callback(JVMTI_EVENT_BREAKPOINT); if (NULL != func) { - TRACE2("jvmti.break", "Calling JIT global breakpoint callback method = " << - ((Method*)method)->get_name() << " location = " << location); + TRACE2("jvmti.break", "Calling JIT global breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location << " :" << native_location); ti->brkpntlst_lock._unlock(); func((jvmtiEnv*)env, jni_env, (jthread)hThread, method, location); ti->brkpntlst_lock._lock(); - TRACE2("jvmti.break", "Finished JIT global breakpoint callback method = " << - ((Method*)method)->get_name() << " location = " << location); + TRACE2("jvmti.break", "Finished JIT global breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location << " :" << native_location); } bp = next_bp; continue; // Don't send local events @@ -294,15 +348,21 @@ #endif if (NULL != func) { JNIEnv *jni_env = (JNIEnv *)jni_native_intf; - TRACE2("jvmti.break", "Calling JIT local breakpoint callback method = " << - ((Method*)method)->get_name() << " location = " << location); + TRACE2("jvmti.break", "Calling JIT local breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location << " :" << native_location); ti->brkpntlst_lock._unlock(); func((jvmtiEnv*)env, jni_env, (jthread)hThread, method, location); ti->brkpntlst_lock._lock(); - TRACE2("jvmti.break", "Finished JIT local breakpoint callback method = " << - ((Method*)method)->get_name() << " location = " << location); + TRACE2("jvmti.break", "Finished JIT local breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location << " :" << native_location); } } @@ -320,7 +380,6 @@ #endif // special handling. InstructionDisassembler::Type type = idisasm.get_type(); - VM_thread *vm_thread = p_TLS_vmthread; jbyte *instruction_buffer = vm_thread->jvmti_jit_breakpoints_handling_buffer; jbyte *interrupted_instruction = (jbyte *)native_location; jint instruction_length = idisasm.get_length_with_prefix(); @@ -398,23 +457,21 @@ #else #endif // Set breakpoints on bytecodes after the current one - if (ti->is_single_step_enabled()) + ss_breakpoint = jvmti_check_and_get_single_step_breakpoint( ti, + vm_thread, native_location ); + if (ss_breakpoint) { - VM_thread *vm_thread = p_TLS_vmthread; - if (NULL != vm_thread->ss_state) - { - jvmti_StepLocation *locations; - unsigned locations_count; + jvmti_StepLocation *locations; + unsigned locations_count; - jvmti_SingleStepLocation(vm_thread, (Method *)ss_breakpoint->method, - (unsigned)ss_breakpoint->location, &locations, &locations_count); + jvmti_SingleStepLocation(vm_thread, (Method *)ss_breakpoint->method, + (unsigned)ss_breakpoint->location, &locations, &locations_count); - jvmti_remove_single_step_breakpoints(ti, vm_thread); + jvmti_remove_single_step_breakpoints(ti, vm_thread); - jvmtiError UNREF errorCode = jvmti_set_single_step_breakpoints( - ti, vm_thread, locations, locations_count); - assert(JVMTI_ERROR_NONE == errorCode); - } + jvmtiError UNREF errorCode = jvmti_set_single_step_breakpoints( + ti, vm_thread, locations, locations_count); + assert(JVMTI_ERROR_NONE == errorCode); } ti->brkpntlst_lock._unlock(); @@ -422,40 +479,55 @@ #endif tmn_suspend_disable(); oh_discard_local_handle(hThread); + END_RAISE_AREA; m2n_set_last_frame(m2n_get_previous_frame(m2nf)); STD_FREE(m2nf); return true; } -jvmtiError jvmti_set_jit_mode_breakpoint(BreakPoint *bp) +jvmtiError jvmti_set_jit_mode_breakpoint(DebugUtilsTI *ti, BreakPoint *bp) { // Function is always executed under global TI breakpoints lock - // Find native location in the method code NativeCodePtr np = NULL; Method *m = (Method *)bp->method; + assert( m->get_state() == Method::ST_Compiled ); + OpenExeJpdaError res = EXE_ERROR_NONE; for (CodeChunkInfo* cci = m->get_first_JIT_specific_info(); cci; cci = cci->_next) { JIT *jit = cci->get_jit(); - OpenExeJpdaError res = jit->get_native_location_for_bc(m, - (uint16)bp->location, &np); + res = jit->get_native_location_for_bc(m, (uint16)bp->location, &np); if (res == EXE_ERROR_NONE) break; } + assert(res == EXE_ERROR_NONE); if (NULL == np) return JVMTI_ERROR_INTERNAL; - TRACE2("jvmti.break", "SetBreakpoint instrumenting native location " << np); + TRACE2("jvmti.break", "Set breakpoint: " + << class_get_name(method_get_class((Method *)bp->method)) << "." + << method_get_name((Method *)bp->method) + << method_get_descriptor((Method *)bp->method) + << " :" << bp->location << " :" << np); bp->native_location = np; - bp->disasm = new InstructionDisassembler(np); - jbyte *target_instruction = (jbyte *)np; - bp->id = (void *)(POINTER_SIZE_INT)*target_instruction; - *target_instruction = (jbyte)INSTRUMENTATION_BYTE; + BreakPoint *other_bp = ti->get_other_breakpoint_same_native_location(bp); + if (other_bp) // No other breakpoints were set in this place + { + assert(NULL == bp->disasm); + bp->id = other_bp->id; + bp->disasm = new InstructionDisassembler(*other_bp->disasm); + } else { + bp->disasm = new InstructionDisassembler(np); + + jbyte *target_instruction = (jbyte *)np; + bp->id = (void *)(POINTER_SIZE_INT)*target_instruction; + *target_instruction = (jbyte)INSTRUMENTATION_BYTE; + } return JVMTI_ERROR_NONE; } @@ -487,7 +559,7 @@ void jvmti_set_pending_breakpoints(Metho if (bp->location == locations[iii]) continue; - jvmti_set_jit_mode_breakpoint(bp); + jvmti_set_jit_mode_breakpoint(ti, bp); locations[location_count++] = bp->location; method->remove_pending_breakpoint(); @@ -503,8 +575,7 @@ jvmtiError jvmti_set_breakpoint_for_jit( { // Function is always executed under global TI breakpoints lock - BreakPoint *other_bp = ti->get_other_breakpoint_same_location(bp->method, - bp->location); + BreakPoint *other_bp = ti->get_other_breakpoint_same_location(bp); if (NULL == other_bp) // No other breakpoints were set in this place { @@ -512,25 +583,27 @@ jvmtiError jvmti_set_breakpoint_for_jit( if (m->get_state() == Method::ST_Compiled) { - jvmtiError errorCode = jvmti_set_jit_mode_breakpoint(bp); + jvmtiError errorCode = jvmti_set_jit_mode_breakpoint(ti, bp); if (JVMTI_ERROR_NONE != errorCode) return JVMTI_ERROR_INTERNAL; } else { - TRACE2("jvmti.break", "Skipping setting breakpoing in method " << - m->get_class()->name->bytes << "." << - m->get_name()->bytes << " " << m->get_descriptor()->bytes << - " because it is not compiled yet"); + TRACE2("jvmti.break", "Skipping setting breakpoint: " + << class_get_name(method_get_class((Method *)bp->method)) << "." + << method_get_name((Method *)bp->method) + << method_get_descriptor((Method *)bp->method) + << " :" << bp->location << ", because it is not compiled yet"); m->insert_pending_breakpoint(); } } else { bp->id = other_bp->id; - if (NULL != bp->disasm) - bp->disasm = new InstructionDisassembler(*bp->disasm); + bp->native_location = other_bp->native_location; + assert(NULL == bp->disasm); + bp->disasm = new InstructionDisassembler(*other_bp->disasm); } ti->add_breakpoint(bp); @@ -550,7 +623,12 @@ jvmtiSetBreakpoint(jvmtiEnv* env, jmethodID method, jlocation location) { - TRACE2("jvmti.break", "SetBreakpoint called, method = " << method << " , location = " << location); + TRACE2("jvmti.break", "SetBreakpoint called: " + << class_get_name(method_get_class((Method *)method)) << "." + << method_get_name((Method *)method) + << method_get_descriptor((Method *)method) + << " :" << location); + SuspendEnabledChecker sec; jvmtiError errorCode; @@ -566,8 +644,11 @@ jvmtiSetBreakpoint(jvmtiEnv* env, return JVMTI_ERROR_INVALID_METHODID; Method *m = (Method*) method; - TRACE2("jvmti.break", "SetBreakpoint method = " << m->get_class()->name->bytes << "." << - m->get_name()->bytes << " " << m->get_descriptor()->bytes); + TRACE2("jvmti.break", "SetBreakpoint: " + << class_get_name(method_get_class((Method *)method)) << "." + << method_get_name((Method *)method) + << method_get_descriptor((Method *)method) + << " :" << location); #if defined (__INTEL_COMPILER) #pragma warning( push ) @@ -604,14 +685,14 @@ #endif if (JVMTI_ERROR_NONE != errorCode) return errorCode; + memset( bp, 0, sizeof(BreakPoint)); bp->method = method; bp->location = location; bp->env = p_env; - bp->disasm = NULL; if (interpreter_enabled()) { - BreakPoint *other_bp = ti->get_other_breakpoint_same_location(method, location); + BreakPoint *other_bp = ti->get_other_breakpoint_same_location(bp); if (NULL == other_bp) // No other breakpoints were set in this place bp->id = interpreter.interpreter_ti_set_breakpoint(method, location); @@ -634,19 +715,28 @@ void jvmti_remove_breakpoint_for_jit(Deb { // Function is always executed under global TI breakpoints lock - if (NULL == ti->get_other_breakpoint_same_location(bp->method, bp->location)) + if (NULL == ti->get_other_breakpoint_same_location(bp)) { Method *m = (Method *)bp->method; if (m->get_state() == Method::ST_Compiled) { - jbyte *target_instruction = (jbyte *)bp->native_location; - *target_instruction = (POINTER_SIZE_INT)bp->id; + if (NULL == ti->get_other_breakpoint_same_native_location(bp)) + { + jbyte *target_instruction = (jbyte *)bp->native_location; + *target_instruction = (POINTER_SIZE_INT)bp->id; + } } else m->remove_pending_breakpoint(); } + TRACE2("jvmti.break", "Remove breakpoint: " + << class_get_name(method_get_class((Method *)bp->method)) << "." + << method_get_name((Method *)bp->method) + << method_get_descriptor((Method *)bp->method) + << " :" << bp->location << " :" << bp->native_location); + ti->remove_breakpoint(bp); } @@ -663,7 +753,11 @@ jvmtiClearBreakpoint(jvmtiEnv* env, jmethodID method, jlocation location) { - TRACE2("jvmti.break", "ClearBreakpoint called, method = " << method << " , location = " << location); + TRACE2("jvmti.break", "ClearBreakpoint called: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location); SuspendEnabledChecker sec; jvmtiError errorCode; @@ -678,8 +772,11 @@ jvmtiClearBreakpoint(jvmtiEnv* env, return JVMTI_ERROR_INVALID_METHODID; Method *m = (Method*) method; - TRACE2("jvmti.break", "ClearBreakpoint method = " << m->get_class()->name->bytes << "." << - m->get_name()->bytes << " " << m->get_descriptor()->bytes); + TRACE2("jvmti.break", "ClearBreakpoint: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location); #if defined (__INTEL_COMPILER) #pragma warning( push ) @@ -715,7 +812,7 @@ #endif if (interpreter_enabled()) { - if (NULL == ti->get_other_breakpoint_same_location(method, location)) + if (NULL == ti->get_other_breakpoint_same_location(bp)) // No other breakpoints were set in this place interpreter.interpreter_ti_clear_breakpoint(method, location, bp->id); diff --git a/vm/vmcore/src/jvmti/jvmti_dasm.cpp b/vm/vmcore/src/jvmti/jvmti_dasm.cpp index 67b8075..ad1c514 100644 --- a/vm/vmcore/src/jvmti/jvmti_dasm.cpp +++ b/vm/vmcore/src/jvmti/jvmti_dasm.cpp @@ -27,6 +27,7 @@ #include "dec_base.h" void InstructionDisassembler::disasm(const NativeCodePtr addr, InstructionDisassembler * pidi) { + assert(addr); assert(pidi != NULL); Inst inst; pidi->len = DecoderBase::decode(addr, &inst); diff --git a/vm/vmcore/src/jvmti/jvmti_step.cpp b/vm/vmcore/src/jvmti/jvmti_step.cpp index 7fbafdf..c56a53c 100644 --- a/vm/vmcore/src/jvmti/jvmti_step.cpp +++ b/vm/vmcore/src/jvmti/jvmti_step.cpp @@ -248,8 +248,8 @@ jvmti_SingleStepLocation( VM_thread* thr case OPCODE_RETURN: /* 0xb1 */ assert( !is_wide ); { - error = jvmti_get_next_bytecodes_up_stack_from_native( - thread, next_step, count ); + error = jvmti_get_next_bytecodes_stack_from_native( + thread, next_step, count, true ); assert( error == JVMTI_ERROR_NONE ); } break; @@ -354,6 +354,16 @@ jvmti_SingleStepLocation( VM_thread* thr break; } while( true ); + for( unsigned index = 0; index < *count; index++ ) { + TRACE2( "jvmti.step", "Step: " << class_get_name(method_get_class(method)) + << "." << method_get_name(method) << method_get_descriptor(method) + << " :" << bytecode_index << "\n -> " + << class_get_name(method_get_class((*next_step)[index].method)) + << "." << method_get_name((*next_step)[index].method) + << method_get_descriptor((*next_step)[index].method) + << " :" << (*next_step)[index].location ) + } + return; } // jvmti_SingleStepLocation @@ -362,7 +372,7 @@ jvmtiError jvmti_set_single_step_breakpo { // Function is always executed under global TI breakpoints lock BreakPoint **thread_breakpoints; - jvmtiError errorCode = _allocate(sizeof(BreakPoint), + jvmtiError errorCode = _allocate(sizeof(BreakPoint*) * locations_number, (unsigned char **)&thread_breakpoints); if (JVMTI_ERROR_NONE != errorCode) return errorCode; @@ -374,10 +384,15 @@ jvmtiError jvmti_set_single_step_breakpo if (JVMTI_ERROR_NONE != errorCode) return errorCode; + memset( bp, 0, sizeof(BreakPoint)); bp->method = (jmethodID)locations[iii].method; bp->location = locations[iii].location; - bp->env = NULL; - bp->disasm = NULL; + + TRACE2("jvmti.break.ss", "Set single step breakpoint: " + << class_get_name(method_get_class((Method *)bp->method)) << "." + << method_get_name((Method *)bp->method) + << method_get_descriptor((Method *)bp->method) + << " :" << bp->location); errorCode = jvmti_set_breakpoint_for_jit(ti, bp); if (JVMTI_ERROR_NONE != errorCode) @@ -408,9 +423,10 @@ void jvmti_remove_single_step_breakpoint ss_state->predicted_bp_count = 0; } -jvmtiError jvmti_get_next_bytecodes_up_stack_from_native(VM_thread *thread, +jvmtiError jvmti_get_next_bytecodes_stack_from_native(VM_thread *thread, jvmti_StepLocation **next_step, - unsigned *count) + unsigned *count, + bool step_up) { ASSERT_NO_INTERPRETER; @@ -429,8 +445,10 @@ jvmtiError jvmti_get_next_bytecodes_up_s } assert(!si_is_native(si)); - // get previous stack frame - si_goto_previous(si); + if( step_up ) { + // get previous stack frame + si_goto_previous(si); + } if (!si_is_native(si)) { // stack frame is java frame, get frame method and location uint16 bc = 0; @@ -441,11 +459,12 @@ jvmtiError jvmti_get_next_bytecodes_up_s OpenExeJpdaError UNREF result = jit->get_bc_location_for_native(func, ip, &bc); assert(result == EXE_ERROR_NONE); + TRACE2( "jvmti.break.ss", "SingleStep method IP: " << ip ); // set step location structure *count = 1; jvmtiError error = _allocate( sizeof(jvmti_StepLocation), (unsigned char**)next_step ); - if( error == JVMTI_ERROR_NONE ) { + if( error != JVMTI_ERROR_NONE ) { si_free(si); return error; } @@ -457,7 +476,7 @@ jvmtiError jvmti_get_next_bytecodes_up_s } si_free(si); return JVMTI_ERROR_NONE; -} // jvmti_get_next_bytecodes_up_stack_from_native +} // jvmti_get_next_bytecodes_stack_from_native jvmtiError DebugUtilsTI::jvmti_single_step_start(void) { @@ -477,6 +496,10 @@ jvmtiError DebugUtilsTI::jvmti_single_st while ((ht = hythread_iterator_next(&threads_iterator)) != NULL) { VM_thread *vm_thread = get_vm_thread(ht); + if( !vm_thread ) { + assert(!hythread_is_alive(ht)); + continue; + } // Init single step state for the thread jvmtiError errorCode = _allocate(sizeof(JVMTISingleStepState), @@ -494,8 +517,8 @@ jvmtiError DebugUtilsTI::jvmti_single_st jvmti_StepLocation *locations; unsigned locations_number; - errorCode = jvmti_get_next_bytecodes_up_stack_from_native( - vm_thread, &locations, &locations_number); + errorCode = jvmti_get_next_bytecodes_stack_from_native( + vm_thread, &locations, &locations_number, false); if (JVMTI_ERROR_NONE != errorCode) { @@ -540,6 +563,10 @@ jvmtiError DebugUtilsTI::jvmti_single_st while ((ht = hythread_iterator_next(&threads_iterator)) != NULL) { VM_thread *vm_thread = get_vm_thread(ht); + if( !vm_thread ) { + assert(!hythread_is_alive(ht)); + continue; + } jvmti_remove_single_step_breakpoints(this, vm_thread); _deallocate((unsigned char *)vm_thread->ss_state); vm_thread->ss_state = NULL;