X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fpatcher-common.cpp;h=6acd9687c493440c8548b4509a9c584a8642b4d6;hb=735bdda890a385d1fa9cc532faadbbc96f2d1218;hp=737631c9acb8370550fde1c4b1e6a590fad49c39;hpb=5e9917d2f37a0a98d8d8b7c7782f0e6566a195b2;p=cacao.git diff --git a/src/vm/jit/patcher-common.cpp b/src/vm/jit/patcher-common.cpp index 737631c9a..6acd9687c 100644 --- a/src/vm/jit/patcher-common.cpp +++ b/src/vm/jit/patcher-common.cpp @@ -1,6 +1,6 @@ /* src/vm/jit/patcher-common.cpp - architecture independent code patching stuff - Copyright (C) 2007, 2008 + Copyright (C) 2007, 2008, 2009 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO Copyright (C) 2008 Theobroma Systems Ltd. @@ -34,19 +34,22 @@ #include "codegen.h" /* for PATCHER_NOPS */ #include "md.h" +#include "trap.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" #include "native/native.hpp" #include "toolbox/list.hpp" -#include "toolbox/logging.h" /* XXX remove me! */ +#include "toolbox/logging.hpp" /* XXX remove me! */ +#include "vm/breakpoint.hpp" #include "vm/exceptions.hpp" -#include "vm/initialize.h" +#include "vm/hook.hpp" +#include "vm/initialize.hpp" #include "vm/options.h" -#include "vm/resolve.h" -#include "vm/vm.hpp" /* for vm_abort */ +#include "vm/os.hpp" +#include "vm/resolve.hpp" #include "vm/jit/code.hpp" #include "vm/jit/disass.h" @@ -70,11 +73,14 @@ typedef struct patcher_function_list_t { static patcher_function_list_t patcher_function_list[] = { { PATCHER_initialize_class, "initialize_class" }, +#ifdef ENABLE_VERIFIER { PATCHER_resolve_class, "resolve_class" }, +#endif /* ENABLE_VERIFIER */ { PATCHER_resolve_native_function, "resolve_native_function" }, { PATCHER_invokestatic_special, "invokestatic_special" }, { PATCHER_invokevirtual, "invokevirtual" }, { PATCHER_invokeinterface, "invokeinterface" }, + { PATCHER_breakpoint, "breakpoint" }, { NULL, "-UNKNOWN PATCHER FUNCTION-" } }; #endif @@ -88,7 +94,7 @@ static patcher_function_list_t patcher_function_list[] = { void patcher_list_create(codeinfo *code) { - code->patchers = new List(); + code->patchers = new LockedList(); } @@ -157,32 +163,84 @@ static patchref_t* patcher_list_find(codeinfo* code, void* pc) } +/** + * Show the content of the whole patcher reference list for + * debugging purposes. + * + * @param code The codeinfo containing the patcher list. + */ +#if !defined(NDEBUG) +void patcher_list_show(codeinfo *code) +{ + for (List::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) { + patchref_t& pr = *it; + + // Lookup name in patcher function list. + patcher_function_list_t* l; + for (l = patcher_function_list; l->patcher != NULL; l++) + if (l->patcher == pr.patcher) + break; + + // Display information about patcher. + printf("\tpatcher pc:"PRINTF_FORMAT_INTPTR_T, pr.mpc); + printf(" datap:"PRINTF_FORMAT_INTPTR_T, pr.datap); + printf(" ref:"PRINTF_FORMAT_INTPTR_T, (intptr_t) pr.ref); +#if PATCHER_CALL_SIZE == 4 + printf(" mcode:%08x", (uint32_t) pr.mcode); +#elif PATCHER_CALL_SIZE == 2 + printf(" mcode:%04x", (uint16_t) pr.mcode); +#else +# error Unknown PATCHER_CALL_SIZE +#endif + printf(" type:%s\n", l->name); + + // Display machine code of patched position. +#if 0 && defined(ENABLE_DISASSEMBLER) + printf("\t\tcurrent -> "); + disassinstr((uint8_t*) pr.mpc); + printf("\t\tapplied -> "); + disassinstr((uint8_t*) &(pr.mcode)); +#endif + } +} +#endif + + /* patcher_add_patch_ref ******************************************************* Appends a new patcher reference to the list of patching positions. + Returns a pointer to the newly created patchref_t. + *******************************************************************************/ -void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp) +patchref_t *patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp) { - codegendata *cd; - codeinfo *code; - s4 patchmpc; + codegendata *cd = jd->cd; + codeinfo *code = jd->code; - cd = jd->cd; - code = jd->code; - patchmpc = cd->mcodeptr - cd->mcodebase; +#if defined(ALIGN_PATCHER_TRAP) + emit_patcher_alignment(cd); +#endif + + int32_t patchmpc = cd->mcodeptr - cd->mcodebase; #if !defined(NDEBUG) if (patcher_list_find(code, (void*) (intptr_t) patchmpc) != NULL) - vm_abort("patcher_add_patch_ref: different patchers at same position."); + os::abort("patcher_add_patch_ref: different patchers at same position."); +#endif + +#if defined(USES_PATCHABLE_MEMORY_BARRIER) + PATCHER_NOPS; #endif // Set patcher information (mpc is resolved later). patchref_t pr; pr.mpc = patchmpc; + pr.datap = 0; pr.disp = disp; + pr.disp_mb = 0; pr.patcher = patcher; pr.ref = ref; pr.mcode = 0; @@ -210,6 +268,8 @@ void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp) cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE; #endif + + return &code->patchers->back(); } @@ -246,7 +306,13 @@ bool patcher_is_patched(patchref_t* pr) // instruction as the patcher structure contains. uint32_t mcode = *((uint32_t*) pr->mpc); +#if PATCHER_CALL_SIZE == 4 if (mcode != pr->mcode) { +#elif PATCHER_CALL_SIZE == 2 + if ((uint16_t) mcode != (uint16_t) pr->mcode) { +#else +#error Unknown PATCHER_CALL_SIZE +#endif // The code differs. return false; } @@ -295,12 +361,11 @@ static int patcher_depth = 0; #define TRACE_PATCHER_INDENT for (i=0; idone) { #if !defined(NDEBUG) @@ -332,7 +397,7 @@ java_handle_t *patcher_handler(u1 *pc) } #endif code->patchers->unlock(); - return NULL; + return true; } #if !defined(NDEBUG) @@ -386,21 +451,17 @@ java_handle_t *patcher_handler(u1 *pc) } #endif - /* check for return value and exit accordingly */ - - if (result == false) { - e = exceptions_get_and_clear_exception(); - - code->patchers->unlock(); - - return e; - } + // Check return value and mangle the pending exception. + if (result == false) + resolve_handle_pending_exception(true); - 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; } @@ -474,7 +535,6 @@ bool patcher_resolve_native_function(patchref_t *pr) { methodinfo *m; uint8_t *datap; - functionptr f; /* get stuff from the patcher reference */ @@ -483,12 +543,15 @@ bool patcher_resolve_native_function(patchref_t *pr) /* resolve native function */ - if (!(f = native_method_resolve(m))) + NativeMethods& nm = VM::get_current()->get_nativemethods(); + void* f = nm.resolve_method(m); + + if (f == NULL) return false; /* patch native function pointer */ - *((intptr_t *) datap) = (intptr_t) f; + *((intptr_t*) datap) = (intptr_t) f; /* synchronize data cache */ @@ -502,6 +565,31 @@ bool patcher_resolve_native_function(patchref_t *pr) } +/** + * Deals with breakpoint instructions (ICMD_BREAKPOINT) compiled + * into a JIT method. This patcher might never patch back the + * original machine code because breakpoints are kept active. + */ +bool patcher_breakpoint(patchref_t *pr) +{ + // Get stuff from the patcher reference. + Breakpoint* breakp = (Breakpoint*) pr->ref; + + // Hook point when a breakpoint was triggered. + Hook::breakpoint(breakp); + + // In case the breakpoint wants to be kept active, we simply + // fail to "patch" at this point. + if (!breakp->is_oneshot) + return false; + + // Patch back original code. + patcher_patch_code(pr); + + return true; +} + + /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where