* src/vm/jit/trap.c (trap_handle): Update executionstates PC register in case
[cacao.git] / src / vm / jit / trap.c
index d03ab5d8f3f80c31b261ae077107ea870aaca469..1ac7ffe7e71e6d016b8d3a8594b75da78803f214 100644 (file)
@@ -29,6 +29,7 @@
 
 /* Include machine dependent trap stuff. */
 
+#include "md.h"
 #include "md-trap.h"
 
 #include "mm/memory.h"
@@ -119,7 +120,7 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
        o = NULL;
        m = NULL;
 
-#if defined(__I386__) || defined(__X86_64__)
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__)
 # if !defined(NDEBUG)
        /* Perform a sanity check on our execution state functions. */
 
@@ -239,27 +240,60 @@ void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xp
 
        stacktrace_stackframeinfo_remove(&sfi);
 
-#if defined(__I386__) || defined(__X86_64__)
-       /* Update execution state and write it back to the current context. */
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__)
+       /* Update execution state and set registers. */
        /* AFTER: removing stackframeinfo */
 
-       if (type == TRAP_COMPILER) {
+       switch (type) {
+       case TRAP_COMPILER:
+               // The normal case for a compiler trap is to jump directly to
+               // the newly compiled method.
+
+               if (p != NULL) {
+                       es.pc = (uint8_t *) (uintptr_t) p;
+                       es.pv = (uint8_t *) (uintptr_t) p;
+                       break;
+               }
+
+               // In case of an exception during JIT compilation, we fetch
+               // the exception here and proceed with exception handling.
+
+               java_handle_t *e = exceptions_get_and_clear_exception();
+               assert(e != NULL);
+
+               // Get and set the PV from the parent Java method.
+
+               es.pv = md_codegen_get_pv_from_pc(ra);
+
+               // XXX: Make the code below a fall-through to default case!
+
+               es.intregs[REG_ITMP1_XPTR] = (uintptr_t) LLNI_DIRECT(e);
+               es.intregs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
+               es.pc                      = (uint8_t *) (uintptr_t) asm_handle_exception;
+               break;
+
+       case TRAP_PATCHER:
+               // The normal case for a patcher trap is to continue execution at
+               // the trap instruction. On some archs the PC may point after the
+               // trap instruction, so we reset it here.
+
                if (p == NULL) {
-                       java_handle_t *e = exceptions_get_and_clear_exception();
-                       es.intregs[REG_ITMP1]     = (uintptr_t) LLNI_DIRECT(e);
-                       es.intregs[REG_ITMP2_XPC] = (uintptr_t) xpc;
-                       es.pc                     = (uint8_t *) (uintptr_t) asm_handle_exception;
-               } else {
-                       es.pc                     = (uint8_t *) (uintptr_t) p;
+                       es.pc = (uint8_t *) (uintptr_t) xpc;
+                       break;
                }
-       } else {
+
+               /* fall-through */
+
+       default:
                if (p != NULL) {
-                       es.intregs[REG_ITMP1]     = (uintptr_t) p;
-                       es.intregs[REG_ITMP2_XPC] = (uintptr_t) xpc;
-                       es.pc                     = (uint8_t *) (uintptr_t) asm_handle_exception;
+                       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;
                }
        }
 
+       /* Write back execution state to current context. */
+
        md_executionstate_write(&es, context);
 #endif