harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ge...@apache.org
Subject svn commit: r447224 - in /incubator/harmony/enhanced/drlvm/trunk/vm/vmcore: include/ src/exception/ src/jit/ src/jvmti/
Date Mon, 18 Sep 2006 04:06:56 GMT
Author: geirm
Date: Sun Sep 17 21:06:56 2006
New Revision: 447224

URL: http://svn.apache.org/viewvc?view=rev&rev=447224
Log:
HARMONY-1455

The implementation of SingleStep even is based on Breakpoints support in JVMTI and HARMONY-1422
next bytecode 
predictor.

This actual patch contains initial SingleStep support added to the breakpoints handler of
JVMTI. It also 
enableds/disables SingleStepping when SingleStepping is turng on/off. It should start SingleStepping
exception 
handler and when running a new Java method from VM native code. When execution control is
transferred to Java, it 
should start SingleStepping it from the transfer location.

TODO is to check that this implementation actually works 

Tested on ubuntu  using smoke and c-unit


Modified:
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_internal.h
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_threads.h
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/exception/exceptions_jit.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_capability.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_step.cpp

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=447224&r1=447223&r2=447224
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_internal.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_internal.h Sun Sep 17 21:06:56
2006
@@ -89,6 +89,19 @@
     BreakPoint(TIEnv *_env) : method(NULL), location(0), next(NULL), env(_env) {}
 };
 
+struct jvmti_StepLocation
+{
+    struct Method* method;
+    unsigned location;
+};
+
+struct JVMTISingleStepState
+{
+    bool enabled;
+    BreakPoint **predicted_breakpoints;
+    unsigned predicted_bp_count;
+};
+
 /*
  * Type which will describe one watched field
  */
@@ -304,12 +317,12 @@
             return NULL;
         }
 
-        BreakPoint *get_other_breakpoint_same_location(jmethodID m, jlocation l, TIEnv *env)
+        BreakPoint *get_other_breakpoint_same_location(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 && bp->env
!= env)
+                if (bp->method == m && bp->location == l)
                     return bp;
 
             return NULL;
@@ -452,6 +465,15 @@
             return global_capabilities & ti_gc;
         }
 
+        bool is_single_step_enabled(void)
+        {
+            return single_step_enabled;
+        }
+
+        // Single step functions
+        jvmtiError jvmti_single_step_start(void);
+        jvmtiError jvmti_single_step_stop(void);
+
     private:
 
     protected:
@@ -469,13 +491,9 @@
         Class **notifyPrepareList;
         unsigned prepareListNumber;
         unsigned global_capabilities;
+        bool single_step_enabled;
 }; /* end of class DebugUtilsTI */
 
-struct jvmti_StepLocation {
-    struct Method* method;
-    unsigned location;
-};
-
 jvmtiError add_event_to_thread(jvmtiEnv *env, jvmtiEvent event_type, jthread event_thread);
 void remove_event_from_thread(jvmtiEnv *env, jvmtiEvent event_type, jthread event_thread);
 void add_event_to_global(jvmtiEnv *env, jvmtiEvent event_type);
@@ -485,6 +503,16 @@
 jint load_agentlib(Agent *agent, const char *str, JavaVM_Internal *vm);
 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_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,
+    VM_thread *vm_thread, jvmti_StepLocation *locations,
+    unsigned locations_number);
+void jvmti_remove_single_step_breakpoints(DebugUtilsTI *ti, VM_thread *vm_thread);
+
 // Object check functions
 Boolean is_valid_thread_object(jthread thread);
 Boolean is_valid_thread_group_object(jthreadGroup group);
@@ -494,7 +522,7 @@
 jvmtiError jvmti_translate_jit_error(OpenExeJpdaError error);
 
 // Single step support
-void jvmti_SingleStepLocation( VM_thread* thread, struct Method *method, unsigned location,

-                               jvmti_StepLocation **next_step, unsigned *count);
+void jvmti_SingleStepLocation(VM_thread* thread, Method *method,
+    unsigned location, jvmti_StepLocation **next_step, unsigned *count);
 
 #endif /* _JVMTI_INTERNAL_H_ */

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_threads.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_threads.h?view=diff&rev=447224&r1=447223&r2=447224
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_threads.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_threads.h Sun Sep 17 21:06:56
2006
@@ -58,6 +58,7 @@
 
 
 struct jvmti_frame_pop_listener;
+struct JVMTISingleStepState;
 
 class VmRegisterContext;
 
@@ -101,6 +102,7 @@
     // has been processed
     jbyte                             jvmti_jit_breakpoints_handling_buffer[50];
     jvmti_frame_pop_listener          *frame_pop_listener;
+    JVMTISingleStepState              *ss_state;
 
     // CPU registers.
     Registers                         regs;

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=447224&r1=447223&r2=447224
==============================================================================
--- 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 Sun
Sep 17 21:06:56 2006
@@ -213,6 +213,19 @@
         interrupted_method_jit = interrupted_cci->get_jit();
     }
 
+    // Remove single step breakpoints which could have been set on the
+    // exception bytecode
+    DebugUtilsTI *ti = VM_Global_State::loader_env->TI;
+    if (ti->isEnabled() && ti->is_single_step_enabled())
+    {
+        VM_thread *vm_thread = p_TLS_vmthread;
+        if (vm_thread->ss_state->enabled)
+        {
+            LMAutoUnlock lock(&ti->brkpntlst_lock);
+            jvmti_remove_single_step_breakpoints(ti, vm_thread);
+        }
+    }
+
     bool same_frame = true;
     while (!si_is_past_end(si) && !si_is_native(si)) {
         CodeChunkInfo *cci = si_get_code_chunk_info(si);
@@ -247,6 +260,29 @@
                 // Setup handler context
                 jit->fix_handler_context(method, si_get_jit_context(si));
                 si_set_ip(si, handler->get_handler_ip(), false);
+
+                // Start single step in exception handler
+                if (ti->isEnabled() && ti->is_single_step_enabled())
+                {
+                    VM_thread *vm_thread = p_TLS_vmthread;
+                    if (vm_thread->ss_state->enabled)
+                    {
+                        LMAutoUnlock lock(&ti->brkpntlst_lock);
+
+                        uint16 bc;
+                        OpenExeJpdaError UNREF result =
+                            jit->get_bc_location_for_native(
+                                method, handler->get_handler_ip(), &bc);
+                        assert(EXE_ERROR_NONE == result);
+
+                        jvmti_StepLocation method_start = {(Method *)method, bc};
+
+                        jvmtiError UNREF errorCode =
+                            jvmti_set_single_step_breakpoints(ti, vm_thread,
+                                &method_start, 1);
+                        assert(JVMTI_ERROR_NONE == errorCode);
+                    }
+                }
 
                 // Create exception if necessary
                 if (!*exn_obj) {

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=447224&r1=447223&r2=447224
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/ini.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/ini.cpp Sun Sep 17 21:06:56 2006
@@ -36,8 +36,32 @@
     assert(NULL != VM_Global_State::loader_env);
     assert(NULL != VM_Global_State::loader_env->em_interface);
     assert(NULL != VM_Global_State::loader_env->em_interface->ExecuteMethod);
+
+    DebugUtilsTI *ti = VM_Global_State::loader_env->TI;
+    if (ti->isEnabled() && ti->is_single_step_enabled())
+    {
+        VM_thread *vm_thread = p_TLS_vmthread;
+        if (vm_thread->ss_state->enabled)
+        {
+            // Start single stepping a new Java method
+            LMAutoUnlock lock(&ti->brkpntlst_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);
+        }
+    }
+
     VM_Global_State::loader_env->em_interface->ExecuteMethod(method, result, args);
     //DEBUG_POP_LOCK(JAVA_CODE_PSEUDO_LOCK);
- 
+
+    // gregory - When method executes *return bytecode in Java it will
+    // set a breakpoint on the bytecode after invoke* or another
+    // bytecode which caused managed to VM transition. This is a
+    // general case of *return handling. So it seems here we don't
+    // have to do anything, *return handling will set a breakpoint up
+    // the stack in java automatically.
 }
 

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=447224&r1=447223&r2=447224
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti.cpp Sun Sep 17 21:06:56
2006
@@ -307,7 +307,8 @@
     MAX_NOTIFY_LIST(1000),
     loadListNumber(0),
     prepareListNumber(0),
-    global_capabilities(0)
+    global_capabilities(0),
+    single_step_enabled(false)
 {
     jvmtiError UNUSED res = _allocate( MAX_NOTIFY_LIST * sizeof(Class**),
         (unsigned char**)&notifyLoadList );

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=447224&r1=447223&r2=447224
==============================================================================
--- 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 Sun Sep 17
21:06:56 2006
@@ -166,7 +166,77 @@
     // 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 = NULL;
+    // Check if there are Single Step type breakpoints in TLS
+    if (ti->is_single_step_enabled())
+    {
+        VM_thread *vm_thread = p_TLS_vmthread;
+        if (vm_thread->ss_state->enabled)
+        {
+            JVMTISingleStepState *ss_state = vm_thread->ss_state;
+            for(unsigned iii = 0; iii < ss_state->predicted_bp_count; iii++)
+            {
+                if (ss_state->predicted_breakpoints[iii]->native_location ==
+                    native_location)
+                {
+                    ss_breakpoint = ss_state->predicted_breakpoints[iii];
+
+                    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 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;
+                    }
+                }
+            }
+        }
+    }
+
+    // Send events for all normally set breakpoints for this location
+    // if there are any
     do
     {
         TIEnv *env = bp->env;
@@ -174,12 +244,16 @@
         jmethodID method = bp->method;
         BreakPoint *next_bp = ti->find_next_bpt(bp, native_location);
 
+        if (bp == ss_breakpoint)
+            // Don't send breakpoint event for breakpoint which was
+            // actually SingleStep breakpoint
+            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)
             {
-                JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
                 TRACE2("jvmti.break", "Calling JIT global breakpoint callback method = "
<<
                     ((Method*)method)->get_name() << " location = " << location);
 
@@ -308,6 +382,26 @@
     regs->rip = (POINTER_SIZE_INT)instruction_buffer;
 #endif
 
+    // Set breakpoints on bytecodes after the current one
+    if (ti->is_single_step_enabled())
+    {
+        VM_thread *vm_thread = p_TLS_vmthread;
+        if (vm_thread->ss_state->enabled)
+        {
+            jvmti_remove_single_step_breakpoints(ti, vm_thread);
+
+            jvmti_StepLocation *locations;
+            unsigned locations_count;
+
+            jvmti_SingleStepLocation(vm_thread, (Method *)ss_breakpoint->method,
+                (unsigned)ss_breakpoint->location, &locations, &locations_count);
+
+            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();
@@ -318,6 +412,8 @@
 
 jvmtiError jvmti_set_jit_mode_breakpoint(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;
@@ -385,6 +481,44 @@
     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->method,
+        bp->location);
+
+    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(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");
+            m->insert_pending_breakpoint();
+        }
+    }
+    else
+    {
+        bp->id = other_bp->id;
+        if (NULL != bp->disasm)
+            bp->disasm = new InstructionDisassembler(*bp->disasm);
+    }
+
+    ti->add_breakpoint(bp);
+    return JVMTI_ERROR_NONE;
+}
+
 /*
 * Set Breakpoint
 *
@@ -457,44 +591,47 @@
     bp->env = p_env;
     bp->disasm = NULL;
 
-    BreakPoint *other_bp = ti->get_other_breakpoint_same_location(method, location, p_env);
-
-    if (NULL == other_bp) // No more environments set breakpoints here
+    if (interpreter_enabled())
     {
-        if (interpreter_enabled())
-            bp->id = interpreter.interpreter_ti_set_breakpoint(method, location);
-        else
-        {
-            Method *m = (Method *)method;
+        BreakPoint *other_bp = ti->get_other_breakpoint_same_location(method, location);
 
-            if (m->get_state() == Method::ST_Compiled)
-                errorCode = jvmti_set_jit_mode_breakpoint(bp);
-            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");
-                m->insert_pending_breakpoint();
-            }
+        if (NULL == other_bp) // No other breakpoints were set in this place
+            bp->id = interpreter.interpreter_ti_set_breakpoint(method, location);
 
-            if (errorCode != JVMTI_ERROR_NONE)
-                return JVMTI_ERROR_INTERNAL;
-        }
+        ti->add_breakpoint(bp);
     }
     else
     {
-        bp->id = other_bp->id;
-        if (NULL != bp->disasm)
-            bp->disasm = new InstructionDisassembler(*bp->disasm);
-    }
+        errorCode = jvmti_set_breakpoint_for_jit(ti, bp);
 
-    ti->add_breakpoint(bp);
+        if (JVMTI_ERROR_NONE != errorCode)
+            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, bp->location))
+    {
+        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;
+        }
+        else
+            m->remove_pending_breakpoint();
+    }
+
+    ti->remove_breakpoint(bp);
+}
+
 /*
 * Clear Breakpoint
 *
@@ -558,26 +695,16 @@
     if (NULL == bp)
         return JVMTI_ERROR_NOT_FOUND;
 
-    if (NULL == ti->get_other_breakpoint_same_location(method, location, p_env))
+    if (interpreter_enabled())
     {
-        // No more environments set breakpoints here
-        if (interpreter_enabled())
+        if (NULL == ti->get_other_breakpoint_same_location(method, location))
+            // No other breakpoints were set in this place
             interpreter.interpreter_ti_clear_breakpoint(method, location, bp->id);
-        else
-        {
-            Method *m = (Method *)method;
 
-            if (m->get_state() == Method::ST_Compiled)
-            {
-                jbyte *target_instruction = (jbyte *)bp->native_location;
-                *target_instruction = (POINTER_SIZE_INT)bp->id;
-            }
-            else
-                m->remove_pending_breakpoint();
-        }
+        ti->remove_breakpoint(bp);
     }
-
-    ti->remove_breakpoint(bp);
+    else
+        jvmti_remove_breakpoint_for_jit(ti, bp);
 
     TRACE2("jvmti.break", "ClearBreakpoint successfull");
     return JVMTI_ERROR_NONE;

Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_capability.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_capability.cpp?view=diff&rev=447224&r1=447223&r2=447224
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_capability.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_capability.cpp Sun Sep
17 21:06:56 2006
@@ -83,7 +83,7 @@
     1, // can_get_source_debug_extension
     1, // can_access_local_variables
     0, // can_maintain_original_method_order
-    0, // can_generate_single_step_events
+    1, // can_generate_single_step_events
     1, // can_generate_exception_events
     1, // can_generate_frame_pop_events
     1, // can_generate_breakpoint_events
@@ -122,7 +122,7 @@
     1, // can_get_source_debug_extension
     0, // can_access_local_variables
     0, // can_maintain_original_method_order
-    0, // can_generate_single_step_events
+    1, // can_generate_single_step_events
     0, // can_generate_exception_events
     0, // can_generate_frame_pop_events
     0, // can_generate_breakpoint_events

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=447224&r1=447223&r2=447224
==============================================================================
--- 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 Sun Sep 17
21:06:56 2006
@@ -307,6 +307,48 @@
     if (event_enabled(event_type) != (jboolean)old_state) {
         if (interpreter_enabled())
             interpreter.interpreter_ti_set_notification_mode(event_type, !old_state);
+        else
+        {
+            if (JVMTI_EVENT_SINGLE_STEP == event_type)
+            {
+                DebugUtilsTI *ti = ((TIEnv *)env)->vm->vm_env->TI;
+
+                if (JVMTI_ENABLE == mode && !ti->is_single_step_enabled())
+                {
+                    jvmtiError errorCode = ti->jvmti_single_step_start();
+
+                    if (JVMTI_ERROR_NONE != errorCode)
+                        return errorCode;
+                }
+                else if (JVMTI_DISABLE == mode && ti->is_single_step_enabled())
+                {
+                    // Check that no environment has SingleStep enabled
+                    LMAutoUnlock lock(&ti->TIenvs_lock);
+                    bool disable = true;
+
+                    for (TIEnv *ti_env = ti->getEnvironments(); ti_env;
+                         ti_env = ti_env->next)
+                    {
+                        if (ti_env->global_events[JVMTI_EVENT_SINGLE_STEP -
+                                JVMTI_MIN_EVENT_TYPE_VAL] ||
+                            NULL != ti_env->event_threads[JVMTI_EVENT_SINGLE_STEP -
+                                JVMTI_MIN_EVENT_TYPE_VAL])
+                        {
+                            disable = false;
+                            break;
+                        }
+                    }
+
+                    if (disable)
+                    {
+                        jvmtiError errorCode = ti->jvmti_single_step_stop();
+
+                        if (JVMTI_ERROR_NONE != errorCode)
+                            return errorCode;
+                    }
+                }
+            }
+        }
     }
 
     return JVMTI_ERROR_NONE;
@@ -1501,10 +1543,44 @@
         
         }
 
-void jvmti_send_thread_start_end_event(int is_start) {
-    is_start ? process_jvmti_event(JVMTI_EVENT_THREAD_START, 0, 0)
-        :process_jvmti_event(JVMTI_EVENT_THREAD_END, 1, 0);
-            }
+void jvmti_send_thread_start_end_event(int is_start)
+{
+    DebugUtilsTI *ti = VM_Global_State::loader_env->TI;
+
+    if (is_start)
+    {
+        process_jvmti_event(JVMTI_EVENT_THREAD_START, 0, 0);
+
+        if (ti->is_single_step_enabled())
+        {
+            // Init single step state for the thread
+            VM_thread *vm_thread = p_TLS_vmthread;
+
+            jvmtiError UNREF errorCode = _allocate(sizeof(JVMTISingleStepState),
+                (unsigned char **)&vm_thread->ss_state);
+            assert(JVMTI_ERROR_NONE == errorCode);
+
+            vm_thread->ss_state->predicted_breakpoints = NULL;
+            vm_thread->ss_state->predicted_bp_count = 0;
+            vm_thread->ss_state->enabled = true;
+        }
+    }
+    else
+    {
+        process_jvmti_event(JVMTI_EVENT_THREAD_END, 1, 0);
+
+        if (ti->is_single_step_enabled())
+        {
+            // 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);
+
+            vm_thread->ss_state->enabled = false;
+            _deallocate((unsigned char *)vm_thread->ss_state);
+        }
+    }
+}
 
 void jvmti_send_wait_monitor_event(jobject monitor, jlong timeout) {
     TRACE2("jvmti.monitor.wait", "Monitor wait event, monitor = " << monitor);

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=447224&r1=447223&r2=447224
==============================================================================
--- 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 Sun Sep 17 21:06:56
2006
@@ -28,6 +28,8 @@
 #include "interpreter.h"
 #include "open/bytecodes.h"
 
+static JNIEnv * jvmti_test_jenv = jni_native_intf;
+
 static inline short
 jvmti_GetHalfWordValue( const unsigned char *bytecode,
                         unsigned location)
@@ -326,7 +328,7 @@
             assert( !is_wide );
             {
                 // create stack iterator, current stack frame should be native
-                StackIterator *si = si_create_from_native();
+                StackIterator *si = si_create_from_native(thread);
                 assert(si_is_native(si));
                 // get previous stack frame, it should be java frame
                 si_goto_previous(si);
@@ -351,7 +353,11 @@
                     error = _allocate( sizeof(jvmti_StepLocation), (unsigned char**)next_step
);
                     assert( error == JVMTI_ERROR_NONE );
                     (*next_step)->method = func;
-                    (*next_step)->location = jvmti_GetNextBytecodeAfterInvoke( func, bc
);
+                    // gregory - IP in stack iterator points to a
+                    // bytecode next after the one which caused call
+                    // of the method. So next location is the BC which
+                    // IP points to.
+                    (*next_step)->location = bc;
                 }
             }
             break;
@@ -454,3 +460,197 @@
 
     return;
 } // jvmti_SingleStepLocation
+
+jvmtiError 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
+    BreakPoint **thread_breakpoints;
+    jvmtiError errorCode = _allocate(sizeof(BreakPoint),
+        (unsigned char **)&thread_breakpoints);
+    if (JVMTI_ERROR_NONE != errorCode)
+        return errorCode;
+
+    for (unsigned iii = 0; iii < locations_number; iii++)
+    {
+        BreakPoint *bp;
+        errorCode = _allocate(sizeof(BreakPoint), (unsigned char **)&bp);
+        if (JVMTI_ERROR_NONE != errorCode)
+            return errorCode;
+
+        bp->method = (jmethodID)locations[iii].method;
+        bp->location = locations[iii].location;
+        bp->env = NULL;
+        bp->disasm = NULL;
+
+        errorCode = jvmti_set_breakpoint_for_jit(ti, bp);
+        if (JVMTI_ERROR_NONE != errorCode)
+            return errorCode;
+
+        thread_breakpoints[iii] = bp;
+    }
+
+    JVMTISingleStepState *ss_state = vm_thread->ss_state;
+    ss_state->predicted_breakpoints = thread_breakpoints;
+    ss_state->predicted_bp_count = locations_number;
+
+    return JVMTI_ERROR_NONE;
+}
+
+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;
+
+    for (unsigned iii = 0; iii < ss_state->predicted_bp_count; iii++)
+    {
+        BreakPoint *bp = ss_state->predicted_breakpoints[iii];
+        jvmti_remove_breakpoint_for_jit(ti, bp);
+    }
+
+    _deallocate((unsigned char *)ss_state->predicted_breakpoints);
+    ss_state->predicted_bp_count = 0;
+}
+
+jvmtiError jvmti_get_next_bytecodes_up_stack_from_native(VM_thread *thread,
+    jvmti_StepLocation **next_step,
+    unsigned *count)
+{
+    StackIterator *si = si_create_from_native(thread);
+
+    // Find first Java frame in the thread stack
+    while (!si_is_past_end(si))
+        if (!si_is_native(si))
+            break;
+
+    *count = 0;
+
+    if (!si_is_past_end(si))
+    {
+        Method *m = si_get_method(si);
+        assert(m);
+
+        CodeChunkInfo *cci = si_get_code_chunk_info(si);
+        JIT *jit = cci->get_jit();
+        // IP address in stack iterator points to the next bytecode after
+        // call
+        NativeCodePtr ip = si_get_ip(si);
+        uint16 bc;
+
+        OpenExeJpdaError UNREF result =
+            jit->get_bc_location_for_native(m, ip, &bc);
+        assert(result == EXE_ERROR_NONE);
+
+        jvmtiError errorCode = _allocate(sizeof(jvmti_StepLocation),
+            (unsigned char **)next_step);
+
+        if (JVMTI_ERROR_NONE != errorCode)
+        {
+            si_free(si);
+            return errorCode;
+        }
+        (*next_step)->method = (Method *)m;
+        (*next_step)->location = bc;
+    }
+
+    si_free(si);
+    return JVMTI_ERROR_NONE;
+}
+
+jvmtiError DebugUtilsTI::jvmti_single_step_start(void)
+{
+    assert(hythread_is_suspend_enabled());
+    LMAutoUnlock lock(&brkpntlst_lock);
+
+    hythread_iterator_t threads_iterator;
+
+    // Suspend all threads except current
+    IDATA tm_ret = hythread_suspend_all(&threads_iterator, NULL);
+    if (TM_ERROR_NONE != tm_ret)
+        return JVMTI_ERROR_INTERNAL;
+
+    hythread_t ht;
+
+    // Set single step in all threads
+    while ((ht = hythread_iterator_next(&threads_iterator)) != NULL)
+    {
+        VM_thread *vm_thread = get_vm_thread(ht);
+
+        // Init single step state for the thread
+        jvmtiError errorCode = _allocate(sizeof(JVMTISingleStepState),
+            (unsigned char **)&vm_thread->ss_state);
+
+        if (JVMTI_ERROR_NONE != errorCode)
+        {
+            hythread_resume_all(NULL);
+            return errorCode;
+        }
+
+        vm_thread->ss_state->predicted_breakpoints = NULL;
+        vm_thread->ss_state->predicted_bp_count = 0;
+        vm_thread->ss_state->enabled = true;
+
+        vm_thread->ss_state->enabled = true;
+
+        jvmti_StepLocation *locations;
+        unsigned locations_number;
+
+        errorCode = jvmti_get_next_bytecodes_up_stack_from_native(
+            vm_thread, &locations, &locations_number);
+
+        if (JVMTI_ERROR_NONE != errorCode)
+        {
+            hythread_resume_all(NULL);
+            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;
+        }
+    }
+    
+    single_step_enabled = true;
+
+    tm_ret = hythread_resume_all(NULL);
+    if (TM_ERROR_NONE != tm_ret)
+        return JVMTI_ERROR_INTERNAL;
+
+    return JVMTI_ERROR_NONE;
+}
+
+jvmtiError DebugUtilsTI::jvmti_single_step_stop(void)
+{
+    assert(hythread_is_suspend_enabled());
+    LMAutoUnlock lock(&brkpntlst_lock);
+
+    hythread_iterator_t threads_iterator;
+
+    // Suspend all threads except current
+    IDATA tm_ret = hythread_suspend_all(&threads_iterator, NULL);
+    if (TM_ERROR_NONE != tm_ret)
+        return JVMTI_ERROR_INTERNAL;
+
+    hythread_t ht;
+
+    // Clear single step in all threads
+    while ((ht = hythread_iterator_next(&threads_iterator)) != NULL)
+    {
+        VM_thread *vm_thread = get_vm_thread(ht);
+        jvmti_remove_single_step_breakpoints(this, vm_thread);
+        vm_thread->ss_state->enabled = false;
+        _deallocate((unsigned char *)vm_thread->ss_state);
+    }
+
+    single_step_enabled = false;
+
+    tm_ret = hythread_resume_all(NULL);
+    if (TM_ERROR_NONE != tm_ret)
+        return JVMTI_ERROR_INTERNAL;
+
+    return JVMTI_ERROR_NONE;
+}



Mime
View raw message