From: Michael Starzinger Date: Thu, 22 Oct 2009 11:30:44 +0000 (+0200) Subject: * src/vm/jit/trap.cpp (trap_handle): Adapted to support "reusable trap points". X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=cacao.git;a=commitdiff_plain;h=1e64951ea564b395e84382841077dcbd8066395e * src/vm/jit/trap.cpp (trap_handle): Adapted to support "reusable trap points". * src/vm/jit/patcher-common.cpp (patcher_handler): Changed to return status instead of the causing exception object itself. * src/vm/jit/patcher-common.hpp: Likewise. --- diff --git a/src/vm/jit/patcher-common.cpp b/src/vm/jit/patcher-common.cpp index e7ec2086e..c364646be 100644 --- a/src/vm/jit/patcher-common.cpp +++ b/src/vm/jit/patcher-common.cpp @@ -356,7 +356,7 @@ static int patcher_depth = 0; #define TRACE_PATCHER_INDENT for (i=0; ipatchers->unlock(); - return NULL; + return true; } #if !defined(NDEBUG) @@ -446,24 +446,17 @@ java_handle_t *patcher_handler(u1 *pc) } #endif - // Check for return value and exit accordingly. - if (result == false) { - // Mangle the pending exception. + // Check return value and mangle the pending exception. + if (result == false) resolve_handle_pending_exception(true); - // Get the exception and return it. - java_handle_t* e = exceptions_get_and_clear_exception(); - - code->patchers->unlock(); - - return e; - } - - pr->done = true; /* XXX this is only preliminary to prevent double-patching */ + // XXX This is only preliminary to prevent double-patching. + else + pr->done = true; code->patchers->unlock(); - return NULL; + return result; } diff --git a/src/vm/jit/patcher-common.hpp b/src/vm/jit/patcher-common.hpp index d4a920339..3f488809e 100644 --- a/src/vm/jit/patcher-common.hpp +++ b/src/vm/jit/patcher-common.hpp @@ -85,7 +85,7 @@ bool patcher_is_patched_at(void* pc); // MD function. bool patcher_is_valid_trap_instruction_at(void* pc); -java_handle_t *patcher_handler(u1 *pc); +bool patcher_handler(u1 *pc); /* empty patcher (just patches back original mcode) ***************************/ diff --git a/src/vm/jit/trap.cpp b/src/vm/jit/trap.cpp index 6d9340c18..8520214de 100644 --- a/src/vm/jit/trap.cpp +++ b/src/vm/jit/trap.cpp @@ -103,10 +103,6 @@ void trap_handle(int sig, void *xpc, void *context) stackframeinfo_t sfi; trapinfo_t trp; - // Prevent compiler warnings. - java_handle_t* o = NULL; - methodinfo* m = NULL; - #if !defined(NDEBUG) // Sanity checking the XPC. if (xpc == NULL) @@ -172,7 +168,18 @@ void trap_handle(int sig, void *xpc, void *context) /* Do some preparations before we enter the nativeworld. */ /* BEFORE: creating stackframeinfo */ + // Prevent compiler warnings. + int32_t index = 0; + java_handle_t* o = NULL; + methodinfo* m = NULL; + switch (type) { + case TRAP_ArrayIndexOutOfBoundsException: + /* Get the index into the array causing the exception. */ + + index = (int32_t) val; + break; + case TRAP_ClassCastException: /* Wrap the value into a handle, as it is a reference. */ @@ -217,9 +224,12 @@ void trap_handle(int sig, void *xpc, void *context) /* Get resulting exception (or pointer to compiled method). */ - int32_t index; java_handle_t* p; void* entry; + bool was_patched; +#if defined(ENABLE_REPLACEMENT) + bool was_replaced; +#endif switch (type) { case TRAP_NullPointerException: @@ -231,7 +241,6 @@ void trap_handle(int sig, void *xpc, void *context) break; case TRAP_ArrayIndexOutOfBoundsException: - index = (int32_t) val; p = exceptions_new_arrayindexoutofboundsexception(index); break; @@ -248,26 +257,25 @@ void trap_handle(int sig, void *xpc, void *context) break; case TRAP_PATCHER: + p = NULL; #if defined(ENABLE_REPLACEMENT) - if (replace_me_wrapper((uint8_t*) xpc, context)) { - p = NULL; + was_replaced = replace_me_wrapper((uint8_t*) xpc, context); + if (was_replaced) break; - } #endif - p = patcher_handler((uint8_t*) xpc); + was_patched = patcher_handler((uint8_t*) xpc); break; case TRAP_COMPILER: - entry = jit_compile_handle(m, sfi.pv, ra, (void*) val); p = NULL; + entry = jit_compile_handle(m, sfi.pv, ra, (void*) val); break; -#if defined(ENABLE_REPLACEMENT) +#if defined(__I386__) && defined(ENABLE_REPLACEMENT) +# warning Port the below stuff to use the patching subsystem. case TRAP_COUNTDOWN: -# if defined(__I386__) - replace_me_wrapper((uint8_t*) xpc - 13, context); -# endif p = NULL; + (void) replace_me_wrapper((uint8_t*) xpc - 13, context); break; #endif @@ -323,12 +331,47 @@ void trap_handle(int sig, void *xpc, void *context) goto trap_handle_exception; case TRAP_PATCHER: +#if defined(ENABLE_REPLACEMENT) + // If on-stack-replacement suceeded, we are not allowed to touch + // the execution state. We assume that there was no exception. + + if (was_replaced) { + assert(exceptions_get_exception() == NULL); + break; + } +#endif + // 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 (was_patched) { + assert(exceptions_get_exception() == NULL); + es.pc = (uint8_t *) (uintptr_t) xpc; + break; + } + + // In case patching was not successful, we try to fetch the pending + // exception here. + + p = exceptions_get_and_clear_exception(); + + // If there is no pending exception, we continue execution behind + // the position still in need of patching. Normally this would + // indicate an error in the patching subsystem, but others might + // want to piggyback patchers and we want to be able to provide + // "reusable trap points" and avoid inifinite loops here. This is + // especially useful to implement breakpoints or profiling points + // of any kind. So before changing the trap logic, think about + // utilizing the patching subsystem on your quest. :) + if (p == NULL) { +#if !defined(NDEBUG) + if (opt_PrintWarnings) + log_println("trap_handle: Detected reusable trap at %p", xpc); +#endif es.pc = (uint8_t *) (uintptr_t) xpc; + es.pc += REPLACEMENT_PATCH_SIZE; break; }