Return-Path: Delivered-To: apmail-incubator-harmony-commits-archive@www.apache.org Received: (qmail 52069 invoked from network); 23 Sep 2006 13:28:24 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 23 Sep 2006 13:28:24 -0000 Received: (qmail 19158 invoked by uid 500); 23 Sep 2006 13:28:24 -0000 Delivered-To: apmail-incubator-harmony-commits-archive@incubator.apache.org Received: (qmail 19134 invoked by uid 500); 23 Sep 2006 13:28:24 -0000 Mailing-List: contact harmony-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: harmony-dev@incubator.apache.org Delivered-To: mailing list harmony-commits@incubator.apache.org Received: (qmail 19123 invoked by uid 99); 23 Sep 2006 13:28:24 -0000 Received: from idunn.apache.osuosl.org (HELO idunn.apache.osuosl.org) (140.211.166.84) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 23 Sep 2006 06:28:24 -0700 Authentication-Results: idunn.apache.osuosl.org smtp.mail=geirm@apache.org; spf=permerror X-ASF-Spam-Status: No, hits=-9.4 required=5.0 tests=ALL_TRUSTED,NO_REAL_NAME Received-SPF: error (idunn.apache.osuosl.org: domain apache.org from 140.211.166.113 cause and error) Received: from [140.211.166.113] ([140.211.166.113:51469] helo=eris.apache.org) by idunn.apache.osuosl.org (ecelerity 2.1.1.8 r(12930)) with ESMTP id E3/7B-27820-47635154 for ; Sat, 23 Sep 2006 06:28:21 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 41DC91A981A; Sat, 23 Sep 2006 06:28:18 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r449232 - in /incubator/harmony/enhanced/drlvm/trunk/vm: include/ interpreter/src/ vmcore/include/ vmcore/src/exception/ vmcore/src/jit/ vmcore/src/jvmti/ vmcore/src/util/linux/ vmcore/src/util/win/ia32/ Date: Sat, 23 Sep 2006 13:28:17 -0000 To: harmony-commits@incubator.apache.org From: geirm@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20060923132818.41DC91A981A@eris.apache.org> X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Author: geirm Date: Sat Sep 23 06:28:16 2006 New Revision: 449232 URL: http://svn.apache.org/viewvc?view=rev&rev=449232 Log: HARMONY-1545 I've reworked the implementation of JVMTI breakpoints and single step. The code which sends breakpoint and single step events currently is ugly and uses unobvious logic. In the new implementation the infrastructure is much more clean and clear :) Main class is VMBreakPoints. It is the container for all breakpoint instrumentation and handler for all breakpoint events. A VMBreakInterface is a class for breakpoints references container. It can be used for any purpose, be it SingleStep or user breakpoints container. In VMBreakInterface breakpoints instrumentations are referenced by VMBreakPointRef. VMBreakPoints has handlers for native (JIT mode) and interpreter mode breakpoints. When such handler is called, the processing goes through all registered VMBreakInterface instances according to their priorities (currently two priorities are supported - SingleStep is first according to JVMTI spec about colocated events) and calls VMBreakInterface handling callback which can send an event of type which this interface supports. Ubuntu 6 - smoke, c-unit Modified: incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_exports.h incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_imports.h incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_exports.cpp incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interpreter_ti.cpp incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_internal.h incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/ini.cpp incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti.cpp incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break.cpp incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_general.cpp incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_method.cpp incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_pop_frame.cpp incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32/nt_exception_filter.cpp Modified: incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_exports.h URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_exports.h?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_exports.h (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_exports.h Sat Sep 23 06:28:16 2006 @@ -67,17 +67,16 @@ * Set breakpoint in place identified by method and location. * No more then one breakpoint will be set at any specific place. Handling * for multiple jvmti environments is done by jvmti framework. - * @return ID, a black box pointer. The pointer will be returned by jvmti as - * a result of breakpoint event callback: jvmti_process_breakpoint_event(...). + * @return bytecode has been replaced by instrumentation */ - void* (*interpreter_ti_set_breakpoint)(jmethodID method, jlocation location); + jbyte (*interpreter_ti_set_breakpoint)(jmethodID method, jlocation location); /** * Clear breakpoint in place identified by method and location. - * Breakpoint ID (returned by interpreter_ti_set_breakpoint(..) also passed - * as a parameter. + * Replaced bytecode (returned by interpreter_ti_set_breakpoint(..) + * is also passed as a parameter. */ - void (*interpreter_ti_clear_breakpoint)(jmethodID method, jlocation location, void *id); + void (*interpreter_ti_clear_breakpoint)(jmethodID method, jlocation location, jbyte saved); /** * Set callback to notify JVMTI about frame pop event. Modified: incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_imports.h URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_imports.h?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_imports.h (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_imports.h Sat Sep 23 06:28:16 2006 @@ -32,7 +32,7 @@ VMEXPORT struct JNIEnv_Internal* get_jni_native_intf(); -VMEXPORT void* jvmti_process_interpreter_breakpoint_event(jmethodID method, jlocation loc); +VMEXPORT jbyte jvmti_process_interpreter_breakpoint_event(jmethodID method, jlocation loc); VMEXPORT void jvmti_process_single_step_event(jmethodID method, jlocation location); VMEXPORT void jvmti_process_frame_pop_event(jvmtiEnv *env, Modified: incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_exports.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_exports.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_exports.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_exports.cpp Sat Sep 23 06:28:16 2006 @@ -84,8 +84,8 @@ extern void interpreter_execute_method(Method *method, jvalue *return_value, jvalue *args); extern void interpreter_ti_set_notification_mode(jvmtiEvent event_type, bool enable); -extern void* interpreter_ti_set_breakpoint(jmethodID method, jlocation location); -extern void interpreter_ti_clear_breakpoint(jmethodID method, jlocation location, void *id); +extern jbyte interpreter_ti_set_breakpoint(jmethodID method, jlocation location); +extern void interpreter_ti_clear_breakpoint(jmethodID method, jlocation location, jbyte saved); extern jvmtiError interpreter_ti_pop_frame(jvmtiEnv*, VM_thread *thread); extern void stack_dump(VM_thread *thread); Modified: incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interpreter_ti.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interpreter_ti.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interpreter_ti.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interpreter_ti.cpp Sat Sep 23 06:28:16 2006 @@ -357,18 +357,18 @@ return (uint8) (POINTER_SIZE_INT) jvmti_process_interpreter_breakpoint_event((jmethodID)m, l); } -void* interpreter_ti_set_breakpoint(jmethodID method, jlocation location) { +jbyte interpreter_ti_set_breakpoint(jmethodID method, jlocation location) { Method *m = (Method*) method; uint8 *bytecodes = (uint8*) m->get_byte_code_addr(); uint8 b = bytecodes[location]; bytecodes[location] = OPCODE_BREAKPOINT; - return (void*) (POINTER_SIZE_INT) b; + return b; } -void interpreter_ti_clear_breakpoint(jmethodID method, jlocation location, void* id) { +void interpreter_ti_clear_breakpoint(jmethodID method, jlocation location, jbyte saved) { Method *m = (Method*) method; uint8 *bytecodes = (uint8*) m->get_byte_code_addr(); - bytecodes[location] = (uint8) (POINTER_SIZE_INT) id; + bytecodes[location] = saved; } int interpreter_ti_notification_mode = 0; Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h Sat Sep 23 06:28:16 2006 @@ -32,6 +32,7 @@ struct Agent; extern Agent *current_loading_agent; +class VmBrkptIntf; /* * Type that describes TI environment created by GetEnv function @@ -45,6 +46,7 @@ jvmtiEventCallbacks event_table; jvmtiExtensionEvent *extension_event_table; jvmtiCapabilities posessed_capabilities; + VmBrkptIntf *brpt_intf; TIEnv* next; bool global_events[JVMTI_MAX_EVENT_TYPE_VAL - JVMTI_MIN_EVENT_TYPE_VAL]; @@ -75,7 +77,6 @@ jint JNICALL create_jvmti_environment(JavaVM *vm, void **env, jint version); jint get_thread_stack_depth(VM_thread *thread, jint* pskip = NULL); -void jvmti_set_pending_breakpoints(Method *method); void jvmti_get_compilation_flags(OpenMethodExecutionParams *flags); // Marks topmost frame of the specified thead to be popped Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_internal.h URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_internal.h?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_internal.h (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_internal.h Sat Sep 23 06:28:16 2006 @@ -75,18 +75,11 @@ }; /* - * Type which will describe one breakpoint + * Type which will be attached to each JVMTI breakpoint */ -struct BreakPoint { - jmethodID method; - jlocation location; - NativeCodePtr native_location; - InstructionDisassembler *disasm; - void *id; - BreakPoint *next; +struct TIBrptData +{ TIEnv *env; - - BreakPoint(TIEnv *_env) : method(NULL), location(0), next(NULL), env(_env) {} }; struct jvmti_StepLocation @@ -98,8 +91,7 @@ struct JVMTISingleStepState { - BreakPoint **predicted_breakpoints; - unsigned predicted_bp_count; + VmBrkptIntf* predicted_breakpoints; }; /* @@ -153,6 +145,8 @@ }; typedef struct Class Class; +class VmBreakpoints; +struct VmBrkptRef; /* * JVMTI state of the VM @@ -160,9 +154,9 @@ class DebugUtilsTI { public: jint agent_counter; - Lock_Manager brkpntlst_lock; Lock_Manager TIenvs_lock; Lock_Manager dcList_lock; + VmBreakpoints* vm_brpt; DebugUtilsTI(); @@ -229,179 +223,6 @@ return p_TIenvs; } - BreakPoint *find_breakpoint(jmethodID m, jlocation l, TIEnv *env) - { - // assert(brkpntlst_lock._lock_or_null()); - - for (BreakPoint *bp = brkpntlst; NULL != bp; bp = bp->next) - if (bp->method == m && bp->location == l && bp->env == env) - return bp; - - return NULL; - } - - bool have_breakpoint(jmethodID m) - { - // assert(brkpntlst_lock._lock_or_null()); - - for (BreakPoint *bp = brkpntlst; NULL != bp; bp = bp->next) - if (bp->method == m) - return true; - - return false; - } - - BreakPoint* find_first_bpt(jmethodID m) - { - // assert(brkpntlst_lock._lock_or_null()); - - for (BreakPoint *bp = brkpntlst; NULL != bp; bp = bp->next) - if (bp->method == m) - return bp; - - return NULL; - } - - BreakPoint* find_next_bpt(BreakPoint* bpt, jmethodID m) - { - // assert(brkpntlst_lock._lock_or_null()); - - for (BreakPoint *bp = bpt->next; NULL != bp; bp = bp->next) - if (bp->method == m) - return bp; - - return NULL; - } - - BreakPoint* find_first_bpt(jmethodID m, jlocation l) - { - // assert(brkpntlst_lock._lock_or_null()); - - for (BreakPoint *bp = brkpntlst; NULL != bp; bp = bp->next) - if (bp->method == m && bp->location == l) - return bp; - - return NULL; - } - - BreakPoint* find_next_bpt(BreakPoint* bpt, jmethodID m, jlocation l) - { - // assert(brkpntlst_lock._lock_or_null()); - - for (BreakPoint *bp = bpt->next; NULL != bp; bp = bp->next) - if (bp->method == m && bp->location == l) - return bp; - - return NULL; - } - - BreakPoint* find_first_bpt(NativeCodePtr np) - { - // assert(brkpntlst_lock._lock_or_null()); - - for (BreakPoint *bp = brkpntlst; NULL != bp; bp = bp->next) - if (bp->native_location == np) - return bp; - - return NULL; - } - - BreakPoint* find_next_bpt(BreakPoint* bpt, NativeCodePtr np) - { - // assert(brkpntlst_lock._lock_or_null()); - - for (BreakPoint *bp = bpt->next; NULL != bp; bp = bp->next) - if (bp->native_location == np) - return bp; - - return NULL; - } - - 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 != 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; - } - - void add_breakpoint(BreakPoint *bp) - { - // assert(brkpntlst_lock._lock_or_null()); - - bp->next = brkpntlst; - brkpntlst = bp; - } - - void remove_breakpoint(BreakPoint *bp) - { - // assert(brkpntlst_lock._lock_or_null()); - assert(brkpntlst); - - if (bp == brkpntlst) - { - brkpntlst = bp->next; - if (NULL != bp->disasm) - delete bp->disasm; - _deallocate((unsigned char *)bp); - return; - } - - for (BreakPoint *p_bp = brkpntlst; NULL != p_bp->next; p_bp = p_bp->next) - if (p_bp->next == bp) - { - p_bp->next = bp->next; - _deallocate((unsigned char *)bp); - return; - } - - ABORT("Can't find the breakpoint"); - } - - void remove_all_breakpoints_env(TIEnv *env) - { - // assert(brkpntlst_lock._lock_or_null()); - - for (BreakPoint **pp_bp = &brkpntlst; NULL != *pp_bp; ) - { - BreakPoint *p_bp = *pp_bp; - - if (p_bp->env == env) - { - *pp_bp = p_bp->next; - _deallocate((unsigned char *)p_bp); - } - else - { - pp_bp = &(p_bp->next); - } - } - } - // Watched fields' support Watch** get_access_watch_list() @@ -500,7 +321,6 @@ protected: friend jint JNICALL create_jvmti_environment(JavaVM *vm, void **env, jint version); - BreakPoint *brkpntlst; Watch *access_watch_list; Watch *modification_watch_list; bool status; @@ -528,9 +348,7 @@ // Breakpoints internal functions 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, +void jvmti_set_single_step_breakpoints(DebugUtilsTI *ti, VM_thread *vm_thread, jvmti_StepLocation *locations, unsigned locations_number); void jvmti_remove_single_step_breakpoints(DebugUtilsTI *ti, VM_thread *vm_thread); @@ -546,5 +364,8 @@ // Single step support void jvmti_SingleStepLocation(VM_thread* thread, Method *method, unsigned location, jvmti_StepLocation **next_step, unsigned *count); + +// Callback function for JVMTI breakpoint processing +bool jvmti_process_breakpoint_event(VmBrkptIntf* intf, VmBrkptRef* bp_ref); #endif /* _JVMTI_INTERNAL_H_ */ Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.cpp Sat Sep 23 06:28:16 2006 @@ -40,6 +40,7 @@ #include "mon_enter_exit.h" #include "stack_iterator.h" #include "vm_stats.h" +#include "jvmti_break_intf.h" #ifdef _IPF_ #elif defined _EM64T_ @@ -222,7 +223,7 @@ VM_thread *vm_thread = p_TLS_vmthread; if (NULL != vm_thread->ss_state) { - LMAutoUnlock lock(&ti->brkpntlst_lock); + LMAutoUnlock lock(ti->vm_brpt->get_lock()); jvmti_remove_single_step_breakpoints(ti, vm_thread); } } @@ -269,7 +270,7 @@ VM_thread *vm_thread = p_TLS_vmthread; if (NULL != vm_thread->ss_state) { - LMAutoUnlock lock(&ti->brkpntlst_lock); + LMAutoUnlock lock(ti->vm_brpt->get_lock()); uint16 bc; NativeCodePtr ip = handler->get_handler_ip(); @@ -279,10 +280,8 @@ jvmti_StepLocation method_start = {(Method *)method, bc, ip}; - jvmtiError UNREF errorCode = - jvmti_set_single_step_breakpoints(ti, vm_thread, + jvmti_set_single_step_breakpoints(ti, vm_thread, &method_start, 1); - assert(JVMTI_ERROR_NONE == errorCode); } } Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/compile.cpp Sat Sep 23 06:28:16 2006 @@ -36,6 +36,7 @@ #include "lil_code_generator.h" #include "stack_iterator.h" #include "interpreter.h" +#include "jvmti_break_intf.h" #include "vm_stats.h" #include "dump.h" Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/ini.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/ini.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/ini.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/ini.cpp Sat Sep 23 06:28:16 2006 @@ -25,6 +25,7 @@ #include "ini.h" #include "environment.h" #include "open/em_vm.h" +#include "jvmti_break_intf.h" void @@ -45,13 +46,11 @@ if (NULL != vm_thread->ss_state) { // Start single stepping a new Java method - LMAutoUnlock lock(&ti->brkpntlst_lock); + LMAutoUnlock lock(ti->vm_brpt->get_lock()); jvmti_remove_single_step_breakpoints(ti, vm_thread); jvmti_StepLocation method_start = {(Method *)method, 0}; - jvmtiError UNREF errorCode = jvmti_set_single_step_breakpoints( - ti, vm_thread, &method_start, 1); - assert(JVMTI_ERROR_NONE == errorCode); + jvmti_set_single_step_breakpoints(ti, vm_thread, &method_start, 1); } } Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti.cpp Sat Sep 23 06:28:16 2006 @@ -33,6 +33,8 @@ #include "environment.h" #include #include "properties.h" +#include "jvmti_break_intf.h" +#include "interpreter_exports.h" #include "port_filepath.h" #include "port_dso.h" @@ -262,6 +264,11 @@ memset(&newenv->global_events, 0, sizeof(newenv->global_events)); memset(&newenv->event_threads, 0, sizeof(newenv->event_threads)); + // Acquire interface for breakpoint handling + newenv->brpt_intf = + vm->vm_env->TI->vm_brpt->query_intf(jvmti_process_breakpoint_event, + interpreter_enabled()); + LMAutoUnlock lock(&vm->vm_env->TI->TIenvs_lock); vm->vm_env->TI->addEnvironment(newenv); *env = newenv; @@ -288,7 +295,6 @@ DebugUtilsTI::DebugUtilsTI() : agent_counter(1), - brkpntlst(NULL), access_watch_list(NULL), modification_watch_list(NULL), status(false), @@ -306,12 +312,15 @@ res = _allocate( MAX_NOTIFY_LIST * sizeof(Class**), (unsigned char**)¬ifyPrepareList ); assert(res == JVMTI_ERROR_NONE); + vm_brpt = new VmBreakpoints(); + assert(vm_brpt); return; } DebugUtilsTI::~DebugUtilsTI() { ReleaseNotifyLists(); + delete vm_brpt; return; } Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break.cpp Sat Sep 23 06:28:16 2006 @@ -28,635 +28,100 @@ #include "Class.h" #include "cxxlog.h" -#include "interpreter_exports.h" -#include "interpreter_imports.h" #include "suspend_checker.h" -#include "jit_intf_cpp.h" -#include "encoder.h" -#include "m2n.h" -#include "exceptions.h" -#include "stack_iterator.h" - - -#define INSTRUMENTATION_BYTE_HLT 0xf4 // HLT instruction -#define INSTRUMENTATION_BYTE_CLI 0xfa // CLI instruction -#define INSTRUMENTATION_BYTE_INT3 0xcc // INT 3 instruction -#define INSTRUMENTATION_BYTE INSTRUMENTATION_BYTE_INT3 - +#include "interpreter_exports.h" +#include "jvmti_break_intf.h" #include "open/jthread.h" #include "open/hythread_ext.h" -// Called when current thread reached breakpoint. -// Returns breakpoint ID received from executing engine on creating of the -// breakpoint -VMEXPORT void* -jvmti_process_interpreter_breakpoint_event(jmethodID method, jlocation 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(); - - DebugUtilsTI *ti = VM_Global_State::loader_env->TI; - ti->brkpntlst_lock._lock(); - - BreakPoint *bp = ti->find_first_bpt(method, location); - assert(bp); // Can't be bytecode without breakpoint - assert(bp->env); // Can't be breakpoint with no environments - void *id = bp->id; - - do - { - TIEnv *env = bp->env; - BreakPoint *next_bp = ti->find_next_bpt(bp, method, location); - - if (env->global_events[JVMTI_EVENT_BREAKPOINT - JVMTI_MIN_EVENT_TYPE_VAL]) - { - jvmtiEventBreakpoint func = (jvmtiEventBreakpoint)env->get_event_callback(JVMTI_EVENT_BREAKPOINT); - if (NULL != func) - { - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; - 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: " - << 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 - } - - TIEventThread *next_et; - for (TIEventThread *et = env->event_threads[JVMTI_EVENT_BREAKPOINT - JVMTI_MIN_EVENT_TYPE_VAL]; - NULL != et; et = next_et) - { - next_et = et->next; - if (et->thread == hythread_self()) - { - jvmtiEventBreakpoint func = (jvmtiEventBreakpoint)env->get_event_callback(JVMTI_EVENT_BREAKPOINT); - if (NULL != func) - { - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; - 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: " - << class_get_name(method_get_class((Method*)method)) << "." - << method_get_name((Method*)method) - << method_get_descriptor((Method*)method) - << " :" << location); - } - } - - et = next_et; - } - - bp = next_bp; - } while(bp); - - ti->brkpntlst_lock._unlock(); - - tmn_suspend_disable(); - oh_discard_local_handle(hThread); - return id; -} - -ConditionCode get_condition_code(InstructionDisassembler::CondJumpType jump_type) -{ - // Right now InstructionDisassembler::CondJumpType enum values are - // equal to enums in ia32/em64t encoder, so this statement is ok - return (ConditionCode)jump_type; -} - -static BreakPoint * -jvmti_check_and_get_single_step_breakpoint( DebugUtilsTI *ti, - VM_thread *vm_thread, - NativeCodePtr native_location) +// Callback function for JVMTI breakpoint processing +bool jvmti_process_breakpoint_event(VmBrkptIntf* intf, VmBrkptRef* bp_ref) { - 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 + VmBrkpt* bp = bp_ref->brpt; + assert(bp); -static void jvmti_send_jit_breakpoint_event(void) -{ - // When we get here we know already that breakpoint occurred in JITted code, - // JVMTI handles it, and registers context is saved for us in TLS - VM_thread *vm_thread = p_TLS_vmthread; - Registers regs = vm_thread->jvmti_saved_exception_registers; - -#if PLATFORM_POSIX && INSTRUMENTATION_BYTE == INSTRUMENTATION_BYTE_INT3 - // Int3 exception address points to the instruction after it - NativeCodePtr native_location = (NativeCodePtr)(((POINTER_SIZE_INT)regs.get_ip()) - 1); -#else - NativeCodePtr native_location = (NativeCodePtr)regs.get_ip(); -#endif + TRACE2("jvmti.break", "BREAKPOINT occured: location=" << bp->location); DebugUtilsTI *ti = VM_Global_State::loader_env->TI; - BreakPoint *bp = ti->find_first_bpt(native_location); - assert(bp); - assert(ti->isEnabled()); - assert(!interpreter_enabled()); - assert(ti->getPhase() == JVMTI_PHASE_LIVE); - - M2nFrame *m2nf = m2n_push_suspended_frame(®s); - jbyte *instruction_buffer; - BEGIN_RAISE_AREA; - - // need to be able to pop the frame - frame_type m2nf_type = m2n_get_frame_type(m2nf); - m2nf_type = (frame_type) (m2nf_type | FRAME_POPABLE); - m2n_set_frame_type(m2nf, m2nf_type); + if (!ti->isEnabled() || ti->getPhase() != JVMTI_PHASE_LIVE) + return false; + jlocation location = bp->location; + jmethodID method = bp->method; + TIBrptData* data = (TIBrptData*)bp_ref->data; + TIEnv *env = data->env; + hythread_t h_thread = hythread_self(); jthread j_thread = jthread_get_java_thread(h_thread); ObjectHandle hThread = oh_allocate_local_handle(); hThread->object = (Java_java_lang_Thread *)j_thread->object; tmn_suspend_enable(); - void *id = bp->id; - jbyte original_byte = (POINTER_SIZE_INT)id; - // Copy disassembler instance in case a breakpoint is deleted - // inside of callbacks - InstructionDisassembler idisasm(*bp->disasm); JNIEnv *jni_env = (JNIEnv *)jni_native_intf; - 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 (ss_breakpoint) - { - TIEnv *ti_env = ti->getEnvironments(); - TIEnv *next_env; - jlocation location = ss_breakpoint->location; - jmethodID method = ss_breakpoint->method; - - while (NULL != ti_env) - { - 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: " - << 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; - } - - 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()) - { - 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); - } - } - } - 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); - } - + jvmtiEventBreakpoint func = + (jvmtiEventBreakpoint)env->get_event_callback(JVMTI_EVENT_BREAKPOINT); - // Send events for all normally set breakpoints for this location - // if there are any - while (bp) + if (NULL != func) { - TIEnv *env = bp->env; - jlocation location = bp->location; - jmethodID method = bp->method; - BreakPoint *next_bp = ti->find_next_bpt(bp, native_location); - - // check if this is a single step breakpoint - if (!bp->env) - { - // Don't send breakpoint event for breakpoint which was - // actually SingleStep breakpoint - bp = next_bp; - continue; - } - if (env->global_events[JVMTI_EVENT_BREAKPOINT - JVMTI_MIN_EVENT_TYPE_VAL]) { - jvmtiEventBreakpoint func = (jvmtiEventBreakpoint)env->get_event_callback(JVMTI_EVENT_BREAKPOINT); - if (NULL != func) - { - 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: " - << 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 + TRACE2("jvmti.break", "Calling global breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location); + + intf->unlock(); + func((jvmtiEnv*)env, jni_env, (jthread)hThread, method, location); + intf->lock(); + + TRACE2("jvmti.break", "Finished global breakpoint callback: " + << class_get_name(method_get_class((Method*)method)) << "." + << method_get_name((Method*)method) + << method_get_descriptor((Method*)method) + << " :" << location); } - - TIEventThread *next_et; - for (TIEventThread *et = env->event_threads[JVMTI_EVENT_BREAKPOINT - JVMTI_MIN_EVENT_TYPE_VAL]; - NULL != et; et = next_et) + else { - next_et = et->next; - if (et->thread == hythread_self()) + TIEventThread *next_et; + TIEventThread *first_et = + env->event_threads[JVMTI_EVENT_BREAKPOINT - JVMTI_MIN_EVENT_TYPE_VAL]; + + for (TIEventThread *et = first_et; NULL != et; et = next_et) { - jvmtiEventBreakpoint func = (jvmtiEventBreakpoint)env->get_event_callback(JVMTI_EVENT_BREAKPOINT); - if (NULL != func) + next_et = et->next; + + if (et->thread == hythread_self()) { - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; - TRACE2("jvmti.break", "Calling JIT local breakpoint callback: " + TRACE2("jvmti.break", "Calling local breakpoint callback: " << class_get_name(method_get_class((Method*)method)) << "." << method_get_name((Method*)method) << method_get_descriptor((Method*)method) - << " :" << location << " :" << native_location); + << " :" << location); - ti->brkpntlst_lock._unlock(); + intf->unlock(); func((jvmtiEnv*)env, jni_env, (jthread)hThread, method, location); - ti->brkpntlst_lock._lock(); + intf->lock(); - TRACE2("jvmti.break", "Finished JIT local breakpoint callback: " + TRACE2("jvmti.break", "Finished local breakpoint callback: " << class_get_name(method_get_class((Method*)method)) << "." << method_get_name((Method*)method) << method_get_descriptor((Method*)method) - << " :" << location << " :" << native_location); + << " :" << location); } } - - et = next_et; } - - bp = next_bp; } - // Now we need to return back to normal code execution, it is - // necessary to execute the original instruction The idea is to - // recreate the original instriction in a special thread local - // buffer followed by a jump to an instruction next after it. In - // case the instruction was a relative jump or call it requires - // special handling. - InstructionDisassembler::Type type = idisasm.get_type(); - - instruction_buffer = vm_thread->jvmti_jit_breakpoints_handling_buffer; - jbyte *interrupted_instruction = (jbyte *)native_location; - jint instruction_length = idisasm.get_length_with_prefix(); - - switch(type) - { - case InstructionDisassembler::UNKNOWN: - { - char *next_instruction = (char *)interrupted_instruction + - instruction_length; - - // Copy original instruction to the exeuction buffer - *instruction_buffer = original_byte; - memcpy(instruction_buffer + 1, interrupted_instruction + 1, - instruction_length - 1); - - // Create JMP $next_instruction instruction in the execution buffer - jump((char *)instruction_buffer + instruction_length, - next_instruction); - break; - } - case InstructionDisassembler::RELATIVE_JUMP: - { - jint instruction_length = idisasm.get_length_with_prefix(); - char *jump_target = (char *)idisasm.get_jump_target_address(); - - // Create JMP to the absolute address which conditional jump - // had in the execution buffer - jump((char *)instruction_buffer, jump_target); - break; - } - case InstructionDisassembler::RELATIVE_COND_JUMP: - { - char *code = (char *)instruction_buffer; - InstructionDisassembler::CondJumpType jump_type = - idisasm.get_cond_jump_type(); - char *next_instruction = (char *)interrupted_instruction + - instruction_length; - char *jump_target = (char *)idisasm.get_jump_target_address(); - - // Create a conditional JMP of the same type over 1 - // instruction forward, the next instruction is JMP to the - // $next_instruction - code = branch8(code, get_condition_code(jump_type), Imm_Opnd(size_8, 0)); - char *branch_address = code - 1; - - code = jump(code, next_instruction); - jint offset = code - branch_address - 1; - *branch_address = offset; - - jump(code, jump_target); - break; - } - case InstructionDisassembler::ABSOLUTE_CALL: - case InstructionDisassembler::RELATIVE_CALL: - { - jbyte *next_instruction = interrupted_instruction + instruction_length; - char *jump_target = (char *)idisasm.get_jump_target_address(); - char *code = (char *)instruction_buffer; - - // Push "return address" to the $next_instruction - code = push(code, Imm_Opnd((POINTER_SIZE_INT)next_instruction)); - - // Jump to the target address of the call instruction - jump(code, jump_target); - break; - } - } - - // Set breakpoints on bytecodes after the current one - ss_breakpoint = jvmti_check_and_get_single_step_breakpoint( ti, - vm_thread, native_location ); - if (ss_breakpoint) - { - jvmti_StepLocation *locations; - unsigned 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); - - jvmtiError UNREF errorCode = jvmti_set_single_step_breakpoints( - ti, vm_thread, locations, locations_count); - assert(JVMTI_ERROR_NONE == errorCode); - } - - ti->brkpntlst_lock._unlock(); - tmn_suspend_disable(); oh_discard_local_handle(hThread); - END_RAISE_AREA; - - // This function does not return. It restores register context and - // transfers execution control to the instruction buffer to - // execute the original instruction with the registers which it - // had before breakpoint happened - StackIterator *si = si_create_from_registers(®s, false, m2n_get_previous_frame(m2nf)); - - m2n_set_last_frame(m2n_get_previous_frame(m2nf)); - STD_FREE(m2nf); - - si_set_ip(si, instruction_buffer, false); - si_transfer_control(si); -} - -bool jvmti_jit_breakpoint_handler(Registers *regs) -{ -#if PLATFORM_POSIX && INSTRUMENTATION_BYTE == INSTRUMENTATION_BYTE_INT3 - // Int3 exception address points to the instruction after it - NativeCodePtr native_location = (NativeCodePtr)(((POINTER_SIZE_INT)regs->get_ip()) - 1); -#else - NativeCodePtr native_location = (NativeCodePtr)regs->get_ip(); -#endif - - TRACE2("jvmti.break", "BREAKPOINT occured: " << native_location); - - DebugUtilsTI *ti = VM_Global_State::loader_env->TI; - if (!ti->isEnabled() || ti->getPhase() != JVMTI_PHASE_LIVE) - return false; - - ti->brkpntlst_lock._lock(); - BreakPoint *bp = ti->find_first_bpt(native_location); - if (NULL == bp) - { - ti->brkpntlst_lock._unlock(); - return false; - } - - assert(ti->isEnabled()); - assert(!interpreter_enabled()); - - // Now it is necessary to set up a transition to - // jvmti_send_jit_breakpoint_event from the exception/signal - // handler - VM_thread *vm_thread = p_TLS_vmthread; - // Copy original registers to TLS - vm_thread->jvmti_saved_exception_registers = *regs; -#ifndef _EM64T_ - regs->eip = (POINTER_SIZE_INT)jvmti_send_jit_breakpoint_event; -#else - regs->rip = (POINTER_SIZE_INT)jvmti_send_jit_breakpoint_event; -#endif - - // Breakpoints list lock is not released until it is unlocked - // inside of jvmti_send_jit_breakpoint_event return true; } -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 - Method *m = (Method *)bp->method; - assert( m->get_state() == Method::ST_Compiled ); - - NativeCodePtr np = bp->native_location; - if( !np ) { - OpenExeJpdaError res = EXE_ERROR_NONE; - for (CodeChunkInfo* cci = m->get_first_JIT_specific_info(); cci; cci = cci->_next) - { - JIT *jit = cci->get_jit(); - 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", "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; - - 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; -} - -void jvmti_set_pending_breakpoints(Method *method) -{ - DebugUtilsTI *ti = VM_Global_State::loader_env->TI; - if (!ti->isEnabled()) - return; - - assert(method->get_pending_breakpoints() > 0); - - LMAutoUnlock lock(&ti->brkpntlst_lock); - - jmethodID mid = (jmethodID)method; - BreakPoint *bp = ti->find_first_bpt(mid); - assert(bp); - - jlocation *locations = (jlocation *)STD_MALLOC(sizeof(jlocation) * - method->get_pending_breakpoints()); - assert(locations); - uint32 location_count = 0; - - do - { - // It is necessary to set breakpoints only once for each - // location, so we need to filter out duplicate breakpoints - for (uint32 iii = 0; iii < location_count; iii++) - if (bp->location == locations[iii]) - continue; - - jvmti_set_jit_mode_breakpoint(ti, bp); - locations[location_count++] = bp->location; - - method->remove_pending_breakpoint(); - bp = ti->find_next_bpt(bp, mid); - } - while(NULL != bp); - - assert(method->get_pending_breakpoints() == 0); - STD_FREE(locations); -} - -jvmtiError jvmti_set_breakpoint_for_jit(DebugUtilsTI *ti, BreakPoint *bp) -{ - // Function is always executed under global TI breakpoints lock - - BreakPoint *other_bp = ti->get_other_breakpoint_same_location(bp); - - if (NULL == other_bp) // No other breakpoints were set in this place - { - Method *m = (Method *)bp->method; - - if (m->get_state() == Method::ST_Compiled) - { - jvmtiError errorCode = jvmti_set_jit_mode_breakpoint(ti, bp); - - if (JVMTI_ERROR_NONE != errorCode) - return JVMTI_ERROR_INTERNAL; - } - else - { - 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; - bp->native_location = other_bp->native_location; - assert(NULL == bp->disasm); - bp->disasm = new InstructionDisassembler(*other_bp->disasm); - } - - ti->add_breakpoint(bp); - return JVMTI_ERROR_NONE; -} - /* * Set Breakpoint * @@ -670,12 +135,7 @@ jmethodID method, jlocation 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); - + TRACE2("jvmti.break", "SetBreakpoint called, method = " << method << " , location = " << location); SuspendEnabledChecker sec; jvmtiError errorCode; @@ -721,72 +181,31 @@ return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; TIEnv *p_env = (TIEnv *)env; - DebugUtilsTI *ti = p_env->vm->vm_env->TI; - LMAutoUnlock lock(&ti->brkpntlst_lock); - BreakPoint *bp = ti->find_breakpoint(method, location, p_env); + VmBrkptIntf* brpt_intf = p_env->brpt_intf; + LMAutoUnlock lock(brpt_intf->get_lock()); + + VmBrkptRef* bp = brpt_intf->find(method, location); if (NULL != bp) return JVMTI_ERROR_DUPLICATE; - errorCode = _allocate(sizeof(BreakPoint), (unsigned char **)&bp); + TIBrptData* data; + errorCode = _allocate(sizeof(TIBrptData), (unsigned char**)&data); if (JVMTI_ERROR_NONE != errorCode) return errorCode; - memset( bp, 0, sizeof(BreakPoint)); - bp->method = method; - bp->location = location; - bp->env = p_env; - - if (interpreter_enabled()) - { - 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); + data->env = p_env; - ti->add_breakpoint(bp); - } - else + if (!brpt_intf->add(method, location, data)) { - errorCode = jvmti_set_breakpoint_for_jit(ti, bp); - - if (JVMTI_ERROR_NONE != errorCode) - return JVMTI_ERROR_INTERNAL; + _deallocate((unsigned char*)data); + return JVMTI_ERROR_INTERNAL; } TRACE2("jvmti.break", "SetBreakpoint successfull"); return JVMTI_ERROR_NONE; } -void jvmti_remove_breakpoint_for_jit(DebugUtilsTI *ti, BreakPoint *bp) -{ - // Function is always executed under global TI breakpoints lock - - if (NULL == ti->get_other_breakpoint_same_location(bp)) - { - Method *m = (Method *)bp->method; - - if (m->get_state() == Method::ST_Compiled) - { - 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); -} - /* * Clear Breakpoint * @@ -800,11 +219,7 @@ jmethodID method, jlocation 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); + TRACE2("jvmti.break", "ClearBreakpoint called, method = " << method << " , location = " << location); SuspendEnabledChecker sec; jvmtiError errorCode; @@ -850,23 +265,16 @@ return JVMTI_ERROR_MUST_POSSESS_CAPABILITY; TIEnv *p_env = (TIEnv *)env; - DebugUtilsTI *ti = p_env->vm->vm_env->TI; - LMAutoUnlock lock(&ti->brkpntlst_lock); - BreakPoint *bp = ti->find_breakpoint(method, location, p_env); + VmBrkptIntf* brpt_intf = p_env->brpt_intf; + LMAutoUnlock lock(brpt_intf->get_lock()); + + VmBrkptRef* bp = brpt_intf->find(method, location); if (NULL == bp) return JVMTI_ERROR_NOT_FOUND; - if (interpreter_enabled()) - { - 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); - - ti->remove_breakpoint(bp); - } - else - jvmti_remove_breakpoint_for_jit(ti, bp); + if (!brpt_intf->remove(bp)) + return JVMTI_ERROR_INTERNAL; TRACE2("jvmti.break", "ClearBreakpoint successfull"); return JVMTI_ERROR_NONE; Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp Sat Sep 23 06:28:16 2006 @@ -36,6 +36,7 @@ #include "jit_intf_cpp.h" #include "vm_log.h" #include "compile.h" +#include "jvmti_break_intf.h" /* * Set Event Callbacks @@ -1601,7 +1602,6 @@ assert(JVMTI_ERROR_NONE == errorCode); vm_thread->ss_state->predicted_breakpoints = NULL; - vm_thread->ss_state->predicted_bp_count = 0; } } else @@ -1612,9 +1612,10 @@ { // Shut down single step state for the thread VM_thread *vm_thread = p_TLS_vmthread; - LMAutoUnlock lock(&ti->brkpntlst_lock); - jvmti_remove_single_step_breakpoints(ti, vm_thread); + LMAutoUnlock lock(ti->vm_brpt->get_lock()); + jvmti_remove_single_step_breakpoints(ti, vm_thread); + ti->vm_brpt->release_intf(vm_thread->ss_state->predicted_breakpoints); _deallocate((unsigned char *)vm_thread->ss_state); vm_thread->ss_state = NULL; } Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_general.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_general.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_general.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_general.cpp Sat Sep 23 06:28:16 2006 @@ -27,6 +27,7 @@ #include "environment.h" #include "cxxlog.h" #include "suspend_checker.h" +#include "jvmti_break_intf.h" /* * Get Phase @@ -106,10 +107,8 @@ _deallocate((unsigned char *)threads); } - // Remove all breakpoints set by this environment - ti->brkpntlst_lock._lock(); - ti->remove_all_breakpoints_env(p_env); - ti->brkpntlst_lock._unlock(); + // Remove all breakpoints set by this environment and release interface + ti->vm_brpt->release_intf(p_env->brpt_intf); // Remove all capabilities for this environment jvmtiRelinquishCapabilities(env, &p_env->posessed_capabilities); Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_method.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_method.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_method.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_method.cpp Sat Sep 23 06:28:16 2006 @@ -36,6 +36,7 @@ #include "environment.h" #include "exceptions.h" #include "interpreter_exports.h" +#include "jvmti_break_intf.h" /* * Get Method Name (and Signature) @@ -529,18 +530,18 @@ if (interpreter_enabled()) { TIEnv *p_env = (TIEnv *)env; - DebugUtilsTI *ti = p_env->vm->vm_env->TI; + VmBreakpoints* vm_brpt = p_env->vm->vm_env->TI->vm_brpt; - LMAutoUnlock lock(&ti->brkpntlst_lock); + LMAutoUnlock lock(vm_brpt->get_lock()); - if (!ti->have_breakpoint(method)) + if (!vm_brpt->has_breakpoint(method)) return JVMTI_ERROR_NONE; - for (BreakPoint* bpt = ti->find_first_bpt(method); bpt; - bpt = ti->find_next_bpt(bpt, method)) + for (VmBrkpt* bpt = vm_brpt->find_first(method); bpt; + bpt = vm_brpt->find_next(bpt, method)) { (*bytecodes_ptr)[bpt->location] = - (unsigned char)(POINTER_SIZE_INT) bpt->id; + (unsigned char)bpt->saved_byte; } } Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_pop_frame.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_pop_frame.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_pop_frame.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_pop_frame.cpp Sat Sep 23 06:28:16 2006 @@ -30,6 +30,7 @@ #include "m2n.h" #include "mon_enter_exit.h" #include "stack_iterator.h" +#include "jvmti_break_intf.h" #include "clog.h" static void jvmti_pop_frame_callback() @@ -328,7 +329,7 @@ VM_thread *vm_thread = p_TLS_vmthread; if (NULL != vm_thread->ss_state) { // remove old single step breakpoints - LMAutoUnlock lock(&ti->brkpntlst_lock); + LMAutoUnlock lock(ti->vm_brpt->get_lock()); jvmti_remove_single_step_breakpoints(ti, vm_thread); // set new single step breakpoints @@ -342,9 +343,7 @@ assert(EXE_ERROR_NONE == result); jvmti_StepLocation locations = {method, bc, ip}; - jvmtiError UNREF error = jvmti_set_single_step_breakpoints(ti, vm_thread, - &locations, 1); - assert( error == JVMTI_ERROR_NONE); + jvmti_set_single_step_breakpoints(ti, vm_thread, &locations, 1); } } return; Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp Sat Sep 23 06:28:16 2006 @@ -28,6 +28,8 @@ #include "interpreter.h" #include "method_lookup.h" #include "open/bytecodes.h" +#include "open/jthread.h" +#include "jvmti_break_intf.h" static JNIEnv * jvmti_test_jenv = jni_native_intf; @@ -379,65 +381,176 @@ return; } // jvmti_SingleStepLocation -jvmtiError jvmti_set_single_step_breakpoints(DebugUtilsTI *ti, VM_thread *vm_thread, - jvmti_StepLocation *locations, unsigned locations_number) +static void +jvmti_setup_jit_single_step(DebugUtilsTI *ti, VmBrkptIntf* intf, + Method* m, jlocation location) { - // Function is always executed under global TI breakpoints lock - BreakPoint **thread_breakpoints; - jvmtiError errorCode = _allocate(sizeof(BreakPoint*) * locations_number, - (unsigned char **)&thread_breakpoints); - if (JVMTI_ERROR_NONE != errorCode) - return errorCode; + VM_thread* vm_thread = p_TLS_vmthread; + jvmti_StepLocation *locations; + unsigned locations_count; - for (unsigned iii = 0; iii < locations_number; iii++) + jvmti_SingleStepLocation(vm_thread, m, (unsigned)location, + &locations, &locations_count); + + jvmti_remove_single_step_breakpoints(ti, vm_thread); + + jvmti_set_single_step_breakpoints(ti, vm_thread, locations, locations_count); +} + +// Callback function for JVMTI single step processing +static bool jvmti_process_jit_single_step_event(VmBrkptIntf* intf, VmBrkptRef* bp_ref) +{ + VmBrkpt* bp = bp_ref->brpt; + assert(bp); + + TRACE2("jvmti.break.ss", "Single Step occured: location=" << bp->location); + + DebugUtilsTI *ti = VM_Global_State::loader_env->TI; + if (!ti->isEnabled() || ti->getPhase() != JVMTI_PHASE_LIVE) + return false; + + JVMTISingleStepState* sss = p_TLS_vmthread->ss_state; + + if (!sss || !ti->is_single_step_enabled()) + return false; + + jlocation location = bp->location; + jmethodID method = bp->method; + Method* m = (Method*)method; + NativeCodePtr addr = bp->addr; + assert(addr); + assert(bp_ref->data == NULL); + + hythread_t h_thread = hythread_self(); + jthread j_thread = jthread_get_java_thread(h_thread); + ObjectHandle hThread = oh_allocate_local_handle(); + hThread->object = (Java_java_lang_Thread *)j_thread->object; + tmn_suspend_enable(); + + JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + TIEnv *env = ti->getEnvironments(); + TIEnv *next_env; + + while (NULL != env) { - BreakPoint *bp; - errorCode = _allocate(sizeof(BreakPoint), (unsigned char **)&bp); - if (JVMTI_ERROR_NONE != errorCode) - return errorCode; + next_env = env->next; - memset( bp, 0, sizeof(BreakPoint)); - bp->method = (jmethodID)locations[iii].method; - bp->location = locations[iii].location; - bp->native_location = locations[iii].native_location; + jvmtiEventSingleStep func = + (jvmtiEventSingleStep)env->get_event_callback(JVMTI_EVENT_SINGLE_STEP); - 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 << " :" << bp->native_location); + if (NULL != func) + { + if (env->global_events[JVMTI_EVENT_SINGLE_STEP - JVMTI_MIN_EVENT_TYPE_VAL]) + { + 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 << " :" << addr); + // fire global event + intf->unlock(); + func((jvmtiEnv*)env, jni_env, (jthread)hThread, method, location); + intf->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 << " :" << addr); - errorCode = jvmti_set_breakpoint_for_jit(ti, bp); - if (JVMTI_ERROR_NONE != errorCode) - return errorCode; + env = next_env; + continue; + } - thread_breakpoints[iii] = bp; + TIEventThread* next_et; + bool found = false; + // fire local events + for (TIEventThread* et = env->event_threads[JVMTI_EVENT_SINGLE_STEP - JVMTI_MIN_EVENT_TYPE_VAL]; + et != NULL; et = next_et) + { + next_et = et->next; + + if (et->thread == hythread_self()) + { + 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 << " :" << addr); + found = true; + intf->unlock(); + func((jvmtiEnv*)env, jni_env, + (jthread)hThread, method, location); + intf->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 << " :" << addr); + } + } + + env = next_env; + } } - JVMTISingleStepState *ss_state = vm_thread->ss_state; - ss_state->predicted_breakpoints = thread_breakpoints; - ss_state->predicted_bp_count = locations_number; + // Set breakpoints on bytecodes after the current one + if (ti->is_single_step_enabled()) + jvmti_setup_jit_single_step(ti, intf, m, location); - return JVMTI_ERROR_NONE; + tmn_suspend_disable(); + oh_discard_local_handle(hThread); + + return true; } -void jvmti_remove_single_step_breakpoints(DebugUtilsTI *ti, VM_thread *vm_thread) +void jvmti_set_single_step_breakpoints(DebugUtilsTI *ti, VM_thread *vm_thread, + jvmti_StepLocation *locations, unsigned locations_number) { // Function is always executed under global TI breakpoints lock + ASSERT_NO_INTERPRETER; + JVMTISingleStepState *ss_state = vm_thread->ss_state; - if(!ss_state->predicted_bp_count) { - // nothing to do - return; + if (NULL == ss_state->predicted_breakpoints) + { // Create SS breakpoints list + ss_state->predicted_breakpoints = + ti->vm_brpt->query_intf(jvmti_process_jit_single_step_event, false); + assert(ss_state->predicted_breakpoints); + // Single Step must be processed earlier then Breakpoints + assert(BREAK_MIN_PRIORITY > BREAK_MAX_PRIORITY); + ss_state->predicted_breakpoints->set_priority(BREAK_MIN_PRIORITY - 1); } - for (unsigned iii = 0; iii < ss_state->predicted_bp_count; iii++) + + for (unsigned iii = 0; iii < locations_number; iii++) { - BreakPoint *bp = ss_state->predicted_breakpoints[iii]; - jvmti_remove_breakpoint_for_jit(ti, bp); + VmBrkptRef* ref = + ss_state->predicted_breakpoints->add((jmethodID)locations[iii].method, + locations[iii].location, + locations[iii].native_location, + NULL); + + TRACE2("jvmti.break.ss", "Set single step breakpoint: " + << class_get_name(method_get_class(locations[iii].method)) << "." + << method_get_name(locations[iii].method) + << method_get_descriptor(locations[iii].method) + << " :" << locations[iii].location + << " :" << locations[iii].native_location); + + assert(ref); } +} + +void jvmti_remove_single_step_breakpoints(DebugUtilsTI *ti, VM_thread *vm_thread) +{ + // Function is always executed under global TI breakpoints lock + JVMTISingleStepState *ss_state = vm_thread->ss_state; - _deallocate((unsigned char *)ss_state->predicted_breakpoints); - ss_state->predicted_bp_count = 0; + if (ss_state && ss_state->predicted_breakpoints) + ss_state->predicted_breakpoints->remove_all(); } jvmtiError jvmti_get_next_bytecodes_stack_from_native(VM_thread *thread, @@ -499,7 +612,9 @@ jvmtiError DebugUtilsTI::jvmti_single_step_start(void) { assert(hythread_is_suspend_enabled()); - LMAutoUnlock lock(&brkpntlst_lock); + + VmBreakpoints* vm_brpt = VM_Global_State::loader_env->TI->vm_brpt; + LMAutoUnlock lock(vm_brpt->get_lock()); hythread_iterator_t threads_iterator; @@ -532,7 +647,6 @@ } vm_thread->ss_state->predicted_breakpoints = NULL; - vm_thread->ss_state->predicted_bp_count = 0; jvmti_StepLocation *locations; unsigned locations_number; @@ -546,14 +660,7 @@ return errorCode; } - errorCode = jvmti_set_single_step_breakpoints(this, vm_thread, locations, - locations_number); - - if (JVMTI_ERROR_NONE != errorCode) - { - hythread_resume_all(NULL); - return errorCode; - } + jvmti_set_single_step_breakpoints(this, vm_thread, locations, locations_number); } single_step_enabled = true; @@ -568,7 +675,9 @@ jvmtiError DebugUtilsTI::jvmti_single_step_stop(void) { assert(hythread_is_suspend_enabled()); - LMAutoUnlock lock(&brkpntlst_lock); + + VmBreakpoints* vm_brpt = VM_Global_State::loader_env->TI->vm_brpt; + LMAutoUnlock lock(vm_brpt->get_lock()); hythread_iterator_t threads_iterator; @@ -588,7 +697,9 @@ // SingleStep state for it continue; } + jvmti_remove_single_step_breakpoints(this, vm_thread); + vm_brpt->release_intf(vm_thread->ss_state->predicted_breakpoints); _deallocate((unsigned char *)vm_thread->ss_state); vm_thread->ss_state = NULL; } Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/linux/signals_ia32.cpp Sat Sep 23 06:28:16 2006 @@ -71,6 +71,7 @@ #include "interpreter.h" #include "crash_handler.h" #include "stack_dump.h" +#include "jvmti_break_intf.h" // Variables used to locate the context from the signal handler static int sc_nest = -1; Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32/nt_exception_filter.cpp URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32/nt_exception_filter.cpp?view=diff&rev=449232&r1=449231&r2=449232 ============================================================================== --- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32/nt_exception_filter.cpp (original) +++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/win/ia32/nt_exception_filter.cpp Sat Sep 23 06:28:16 2006 @@ -25,6 +25,7 @@ #include "exceptions_jit.h" #include "interpreter_exports.h" #include "stack_dump.h" +#include "jvmti_break_intf.h" // Windows specific #include