* src/vm/jit/executionstate.c (executionstate_unwind_exception): Added generic
authorMichael Starzinger <michi@complang.tuwien.ac.at>
Wed, 4 Nov 2009 17:47:29 +0000 (18:47 +0100)
committerMichael Starzinger <michi@complang.tuwien.ac.at>
Wed, 4 Nov 2009 17:47:29 +0000 (18:47 +0100)
function to perform stack unwinding on all architectures. This will become the
replacement for asm_handle_exception on all architectures soon.
* src/vm/jit/executionstate.h: Likewise.
* src/vm/jit/trap.cpp (trap_handle): Activated above function for x86_64.

src/vm/jit/executionstate.c
src/vm/jit/executionstate.h
src/vm/jit/trap.cpp

index c37bb05f4f7c3d00b3a5e0286eb06291f1245586..953c832a215439a90dfa12e14a4bf17697d853f6 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/executionstate.c - execution-state handling
 
-   Copyright (C) 2007, 2008
+   Copyright (C) 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -150,6 +150,59 @@ void executionstate_pop_stackframe(executionstate_t *es)
 }
 
 
+// XXX Move this prototype somewhere else!
+void *exceptions_handle_exception(java_object_t *xptro, void *xpc, void *pv, void *sp);
+
+
+/**
+ * Performs stack unwinding in case of an exception. This is done by
+ * popping frames off the given execution state until a frame is reached
+ * for which there is a handler. Execution will continue at the handler
+ * site once the execution state is written back to the machine.
+ *
+ * @param es Execution state to be modified.
+ * @param e The thrown exception object.
+ *
+ * This is specified in:
+ *    The Java(TM) Virtual Machine Specification, Second Edition
+ *    Section 3.6.5: Abrupt Method Invocation Completion
+ */
+void executionstate_unwind_exception(executionstate_t* es, java_handle_t* e)
+{
+       void* handler = NULL;
+
+       // Iterate until we find an exception handler.
+       while (handler == NULL) {
+
+               // Search an exception handler in the current frame.
+               handler = exceptions_handle_exception(e, es->pc, es->pv, es->sp);
+
+               // Jump directly into the handler in case we found one.
+               if (handler != NULL)
+                       break;
+
+               // Find the codeinfo structure for the current frame.
+               es->code = code_get_codeinfo_for_pv(es->pv);
+
+               // Pop one frame off the stack.
+               executionstate_pop_stackframe(es);
+
+               // Get the PV for the parent Java method.
+               es->pv = md_codegen_get_pv_from_pc(es->pc);
+
+               // After popping the frame the PC points to the instruction just after
+               // the invocation. To get the XPC we need to correct the PC to point
+               // just before the invocation. But we do not know how big the
+               // invocation site actually is, so we subtract one, which should be
+               // sufficient for our purposes.
+               es->pc -= 1;
+       }
+
+       // Update the execution state to continue at the handler site.
+       es->pc = (uint8_t*) handler;
+}
+
+
 /* executionstate_sanity_check *************************************************
 
    Perform some sanity checks for the md_executionstate_read and
index 08dcc5dd8250b87885112e2b9a918e7b472e3e21..e97707d60a8d5955079688af3093b3d7ca0ff5a2 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/executionstate.h - execution-state handling
 
-   Copyright (C) 2007, 2008
+   Copyright (C) 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -81,6 +81,8 @@ extern "C" {
 
 void executionstate_pop_stackframe(executionstate_t *es);
 
+void executionstate_unwind_exception(executionstate_t* es, java_handle_t* e);
+
 #if !defined(NDEBUG)
 void executionstate_sanity_check(void *context);
 void executionstate_println(executionstate_t *es);
index 57af425e2e00d91c976b989fe80305bdb499e2a8..2f5d523e924ee897c20b2f53114965d817fa01cd 100644 (file)
@@ -380,9 +380,19 @@ void trap_handle(int sig, void *xpc, void *context)
        trap_handle_exception:
        default:
                if (p != NULL) {
+#if defined(__X86_64__)
+                       // Perform stack unwinding for exceptions on execution state.
+                       es.pc = (uint8_t *) (uintptr_t) xpc;
+                       es.pv = (uint8_t *) (uintptr_t) sfi.pv;
+                       executionstate_unwind_exception(&es, p);
+
+                       // Pass the exception object to the exception handler.
+                       es.intregs[REG_ITMP1_XPTR] = (uintptr_t) LLNI_DIRECT(p);
+#else
                        es.intregs[REG_ITMP1_XPTR] = (uintptr_t) LLNI_DIRECT(p);
                        es.intregs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
                        es.pc                      = (uint8_t *) (uintptr_t) asm_handle_exception;
+#endif
                }
        }