From f9e953ab77d67e0b74b9f2165f8d829f2b020974 Mon Sep 17 00:00:00 2001 From: Michael Starzinger Date: Wed, 4 Nov 2009 18:47:29 +0100 Subject: [PATCH] * src/vm/jit/executionstate.c (executionstate_unwind_exception): Added generic 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 | 55 ++++++++++++++++++++++++++++++++++++- src/vm/jit/executionstate.h | 4 ++- src/vm/jit/trap.cpp | 10 +++++++ 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/vm/jit/executionstate.c b/src/vm/jit/executionstate.c index c37bb05f4..953c832a2 100644 --- a/src/vm/jit/executionstate.c +++ b/src/vm/jit/executionstate.c @@ -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 diff --git a/src/vm/jit/executionstate.h b/src/vm/jit/executionstate.h index 08dcc5dd8..e97707d60 100644 --- a/src/vm/jit/executionstate.h +++ b/src/vm/jit/executionstate.h @@ -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); diff --git a/src/vm/jit/trap.cpp b/src/vm/jit/trap.cpp index 57af425e2..2f5d523e9 100644 --- a/src/vm/jit/trap.cpp +++ b/src/vm/jit/trap.cpp @@ -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 } } -- 2.25.1