/* 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.
#include "toolbox/list.hpp"
#include "toolbox/logging.hpp" /* XXX remove me! */
+#include "vm/breakpoint.hpp"
#include "vm/exceptions.hpp"
+#include "vm/hook.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"
{ PATCHER_invokestatic_special, "invokestatic_special" },
{ PATCHER_invokevirtual, "invokevirtual" },
{ PATCHER_invokeinterface, "invokeinterface" },
+ { PATCHER_breakpoint, "breakpoint" },
{ NULL, "-UNKNOWN PATCHER FUNCTION-" }
};
#endif
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;
-
- cd = jd->cd;
- code = jd->code;
- patchmpc = cd->mcodeptr - cd->mcodebase;
+ codegendata *cd = jd->cd;
+ codeinfo *code = jd->code;
#if defined(ALIGN_PATCHER_TRAP)
emit_patcher_alignment(cd);
- patchmpc = cd->mcodeptr - cd->mcodebase;
#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).
pr.mpc = patchmpc;
pr.datap = 0;
pr.disp = disp;
+ pr.disp_mb = 0;
pr.patcher = patcher;
pr.ref = ref;
pr.mcode = 0;
cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
#endif
+
+ return &code->patchers->back();
}
#define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
#endif /* !defined(NDEBUG) */
-java_handle_t *patcher_handler(u1 *pc)
+bool patcher_handler(u1 *pc)
{
codeinfo *code;
patchref_t *pr;
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)
}
#endif
code->patchers->unlock();
- return NULL;
+ return true;
}
#if !defined(NDEBUG)
}
#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;
}
}
+/**
+ * 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