X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fpatcher-common.cpp;h=57c6fdb39005537ba738f0c2e160324d418083d1;hb=67da78971605bb8a2953a9f6d5a7862857049538;hp=b4799b3138184ab603afefb94ae348f42dab2a79;hpb=bbc14f3688db91816c8112c1a899c9a44c7305af;p=cacao.git diff --git a/src/vm/jit/patcher-common.cpp b/src/vm/jit/patcher-common.cpp index b4799b313..57c6fdb39 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.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.hpp" #include "vm/options.h" +#include "vm/os.hpp" #include "vm/resolve.hpp" -#include "vm/vm.hpp" /* for vm_abort */ #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,6 +162,49 @@ 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. @@ -165,17 +213,22 @@ static patchref_t* patcher_list_find(codeinfo* code, void* pc) void 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). @@ -247,7 +300,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; } @@ -301,7 +360,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; @@ -324,7 +382,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) @@ -387,10 +445,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(); @@ -505,6 +566,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