X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fpatcher-common.cpp;h=dcafac7b7eedad04c3333d23124af04a9e970710;hb=a40fe595d0cfe6c65922418de174200ce4873633;hp=e76ecfdc023071c2006e4c5e72a538df0d278f92;hpb=7fbc0badfc433e0113f7044baa760916b987500a;p=cacao.git diff --git a/src/vm/jit/patcher-common.cpp b/src/vm/jit/patcher-common.cpp index e76ecfdc0..dcafac7b7 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,21 @@ #include "codegen.h" /* for PATCHER_NOPS */ #include "md.h" +#include "trap.hpp" -#include "mm/memory.h" +#include "mm/memory.hpp" -#include "native/native.h" +#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/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 +72,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 +93,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 +162,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; + +#if defined(ALIGN_PATCHER_TRAP) + emit_patcher_alignment(cd); +#endif - cd = jd->cd; - code = jd->code; - patchmpc = cd->mcodeptr - cd->mcodebase; + 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 +267,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 +305,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; } @@ -300,7 +365,6 @@ java_handle_t *patcher_handler(u1 *pc) codeinfo *code; patchref_t *pr; bool result; - java_handle_t *e; #if !defined(NDEBUG) patcher_function_list_t *l; int i; @@ -323,7 +387,7 @@ java_handle_t *patcher_handler(u1 *pc) pr = patcher_list_find(code, pc); if (pr == NULL) - vm_abort("patcher_handler: Unable to find patcher reference."); + os::abort("patcher_handler: Unable to find patcher reference."); if (pr->done) { #if !defined(NDEBUG) @@ -386,10 +450,13 @@ java_handle_t *patcher_handler(u1 *pc) } #endif - /* check for return value and exit accordingly */ - + // Check for return value and exit accordingly. if (result == false) { - e = exceptions_get_and_clear_exception(); + // Mangle the pending exception. + resolve_handle_pending_exception(true); + + // Get the exception and return it. + java_handle_t* e = exceptions_get_and_clear_exception(); code->patchers->unlock(); @@ -474,7 +541,6 @@ bool patcher_resolve_native_function(patchref_t *pr) { methodinfo *m; uint8_t *datap; - functionptr f; /* get stuff from the patcher reference */ @@ -483,12 +549,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 +571,36 @@ 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; + +#if defined(ENABLE_JVMTI) + methodinfo* m = breakp->method; + int32_t l = breakp->location; + + log_message_method("JVMTI: Reached breakpoint in method ", m); + log_println("JVMTI: Reached breakpoint at location %d", l); +#endif + + // 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