harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ge...@apache.org
Subject svn commit: r449228 - in /incubator/harmony/enhanced/drlvm/trunk/vm/vmcore: include/jvmti_direct.h include/vm_threads.h src/jvmti/jvmti_break.cpp src/util/linux/signals_ia32.cpp src/util/win/ia32/nt_exception_filter.cpp
Date Sat, 23 Sep 2006 13:07:45 GMT
Author: geirm
Date: Sat Sep 23 06:07:44 2006
New Revision: 449228

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

The current implementation of JVMTI breakpoints invokes agent from inside of exception (on
Windows) or signal (on 
Linux) handler. This usually works but may cause problems if for example agent decides to
stop the thread with 
breakpoint for some long time. On Windows exception handler cannot be invoked by another thread
until other exception 
handler is running. This may cause dead locks with any exception happening in other threads,
e.g. C++ exceptions on 
windows are done through the same mechanism. On Linux calling arbitrary functions from inside
of signal handler may 
not work as well.

The solution for this problem is if JVMTI sees that happened breakpoint is actually set by
JVMTI, for processing it 
it should exit the handler. In order to start breakpoint processing the handler exit IP is
changed from the IP 
pointing to the interrupted location to the JVMTI processing handler. Then exception/signal
handler exits and makes 
the kernel happy while execution is transferred to JVMTI breakpoints handler. This also is
done while holding 
breakpoints list lock so that no intermittent modification, like removing the breakpoin which
caused exception is 
possible.

Ubuntu 6 - smoke, c-unit, kernel


Modified:
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_threads.h
    incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_break.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/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=449228&r1=449227&r2=449228
==============================================================================
--- 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:07:44
2006
@@ -110,7 +110,7 @@
 void jvmti_send_class_prepare_event(Class* clss);
 VMEXPORT void jvmti_send_thread_start_end_event(int is_start);
 void jvmti_send_vm_death_event();
-bool jvmti_send_jit_breakpoint_event(Registers *regs);
+bool jvmti_jit_breakpoint_handler(Registers *regs);
 
 #ifdef __cplusplus
 }

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=449228&r1=449227&r2=449228
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_threads.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/vm_threads.h Sat Sep 23 06:07:44
2006
@@ -103,6 +103,7 @@
     jbyte                             jvmti_jit_breakpoints_handling_buffer[50];
     jvmti_frame_pop_listener          *frame_pop_listener;
     JVMTISingleStepState              *ss_state;
+    Registers                         jvmti_saved_exception_registers;
 
     // CPU registers.
     Registers                         regs;

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=449228&r1=449227&r2=449228
==============================================================================
--- 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:07:44 2006
@@ -35,6 +35,7 @@
 #include "encoder.h"
 #include "m2n.h"
 #include "exceptions.h"
+#include "stack_iterator.h"
 
 
 #define INSTRUMENTATION_BYTE_HLT 0xf4 // HLT instruction
@@ -175,35 +176,29 @@
     return ss_breakpoint;
 } // jvmti_check_and_get_single_step_breakpoint
 
-bool jvmti_send_jit_breakpoint_event(Registers *regs)
+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);
+    NativeCodePtr native_location = (NativeCodePtr)(((POINTER_SIZE_INT)regs.get_ip()) - 1);
 #else
-    NativeCodePtr native_location = (NativeCodePtr)regs->get_ip();
+    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(bp);
     assert(ti->isEnabled());
     assert(!interpreter_enabled());
+    assert(ti->getPhase() == JVMTI_PHASE_LIVE);
 
-    Registers orig_regs = *regs;
-
-    M2nFrame *m2nf = m2n_push_suspended_frame(&orig_regs);
+    M2nFrame *m2nf = m2n_push_suspended_frame(&regs);
+    jbyte *instruction_buffer;
     BEGIN_RAISE_AREA;
 
     // need to be able to pop the frame
@@ -224,7 +219,6 @@
     InstructionDisassembler idisasm(*bp->disasm);
     JNIEnv *jni_env = (JNIEnv *)jni_native_intf;
 
-    VM_thread *vm_thread = p_TLS_vmthread;
     BreakPoint *ss_breakpoint = jvmti_check_and_get_single_step_breakpoint( ti,
         vm_thread, native_location );
     // Check if there are Single Step type breakpoints in TLS
@@ -387,7 +381,7 @@
     // special handling.
     InstructionDisassembler::Type type = idisasm.get_type();
 
-    jbyte *instruction_buffer = vm_thread->jvmti_jit_breakpoints_handling_buffer;
+    instruction_buffer = vm_thread->jvmti_jit_breakpoints_handling_buffer;
     jbyte *interrupted_instruction = (jbyte *)native_location;
     jint instruction_length = idisasm.get_length_with_prefix();
 
@@ -456,13 +450,6 @@
     }
     }
 
-    // Set exception or signal return address to the instruction buffer
-#ifndef _EM64T_
-    regs->eip = (POINTER_SIZE_INT)instruction_buffer;
-#else
-    regs->rip = (POINTER_SIZE_INT)instruction_buffer;
-#endif
-
     // Set breakpoints on bytecodes after the current one
     ss_breakpoint = jvmti_check_and_get_single_step_breakpoint( ti,
         vm_thread, native_location );
@@ -487,9 +474,60 @@
     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(&regs, 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;
 }
 

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=449228&r1=449227&r2=449228
==============================================================================
--- 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:07:44 2006
@@ -494,7 +494,7 @@
         (void *)regs.eip);
     assert(!interpreter_enabled());
 
-    bool handled = jvmti_send_jit_breakpoint_event(&regs);
+    bool handled = jvmti_jit_breakpoint_handler(&regs);
     if (handled)
     {
         linux_regs_to_ucontext(uc, &regs);

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=449228&r1=449227&r2=449228
==============================================================================
--- 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:07:44 2006
@@ -418,7 +418,7 @@
             nt_to_vm_context(context, &regs);
             TRACE2("signals", "JVMTI breakpoint detected at " <<
                 (void *)regs.eip);
-            bool handled = jvmti_send_jit_breakpoint_event(&regs);
+            bool handled = jvmti_jit_breakpoint_handler(&regs);
             if (handled)
             {
                 vm_to_nt_context(&regs, context);



Mime
View raw message