1 /* src/vm/jit/patcher-common.cpp - architecture independent code patching stuff
3 Copyright (C) 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 Copyright (C) 2008 Theobroma Systems Ltd.
7 This file is part of CACAO.
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2, or (at
12 your option) any later version.
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
32 #include "codegen.h" /* for PATCHER_NOPS */
35 #include "mm/memory.h"
37 #include "native/native.h"
39 #include "toolbox/list.h"
40 #include "toolbox/logging.h" /* XXX remove me! */
42 #include "vm/exceptions.hpp"
43 #include "vm/initialize.h"
44 #include "vm/options.h"
45 #include "vm/resolve.h"
46 #include "vm/vm.hpp" /* for vm_abort */
48 #include "vm/jit/code.hpp"
49 #include "vm/jit/disass.h"
50 #include "vm/jit/jit.hpp"
51 #include "vm/jit/patcher-common.hpp"
54 /* patcher_function_list *******************************************************
56 This is a list which maps patcher function pointers to the according
57 names of the patcher functions. It is only usefull for debugging
60 *******************************************************************************/
63 typedef struct patcher_function_list_t {
66 } patcher_function_list_t;
68 static patcher_function_list_t patcher_function_list[] = {
69 { PATCHER_initialize_class, "initialize_class" },
70 { PATCHER_resolve_class, "resolve_class" },
71 { PATCHER_resolve_native_function, "resolve_native_function" },
72 { PATCHER_invokestatic_special, "invokestatic_special" },
73 { PATCHER_invokevirtual, "invokevirtual" },
74 { PATCHER_invokeinterface, "invokeinterface" },
75 { NULL, "-UNKNOWN PATCHER FUNCTION-" }
80 /* patcher_list_create *********************************************************
82 Creates an empty patcher list for the given codeinfo.
84 *******************************************************************************/
86 void patcher_list_create(codeinfo *code)
88 code->patchers = list_create(OFFSET(patchref_t, linkage));
92 /* patcher_list_reset **********************************************************
94 Resets the patcher list inside a codeinfo. This is usefull when
95 resetting a codeinfo for recompiling.
97 *******************************************************************************/
99 void patcher_list_reset(codeinfo *code)
103 /* free all elements of the list */
105 while((pr = (patchref_t*) list_first(code->patchers)) != NULL) {
106 list_remove(code->patchers, pr);
108 FREE(pr, patchref_t);
110 #if defined(ENABLE_STATISTICS)
112 size_patchref -= sizeof(patchref_t);
117 /* patcher_list_free ***********************************************************
119 Frees the patcher list and all its entries for the given codeinfo.
121 *******************************************************************************/
123 void patcher_list_free(codeinfo *code)
125 /* free all elements of the list */
127 patcher_list_reset(code);
129 /* free the list itself */
131 list_free(code->patchers);
135 /* patcher_list_find ***********************************************************
137 Find an entry inside the patcher list for the given codeinfo
138 by specifying the program counter of the patcher position.
140 NOTE: Caller should hold the patcher list lock or maintain
141 exclusive access otherwise.
143 *******************************************************************************/
145 static patchref_t *patcher_list_find(codeinfo *code, void *pc)
149 /* walk through all patcher references for the given codeinfo */
151 pr = (patchref_t*) list_first(code->patchers);
155 /*#define TRACE_PATCHER_FIND*/
156 #ifdef TRACE_PATCHER_FIND
157 log_println("patcher_list_find: %p == %p", pr->mpc, pc);
160 if (pr->mpc == (ptrint) pc)
163 pr = (patchref_t*) list_next(code->patchers, pr);
170 /* patcher_add_patch_ref *******************************************************
172 Appends a new patcher reference to the list of patching positions.
174 *******************************************************************************/
176 void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
185 patchmpc = cd->mcodeptr - cd->mcodebase;
188 if (patcher_list_find(code, (void*) (intptr_t) patchmpc) != NULL)
189 vm_abort("patcher_add_patch_ref: different patchers at same position.");
192 /* allocate patchref on heap (at least freed together with codeinfo) */
194 pr = NEW(patchref_t);
195 list_add_first(code->patchers, pr);
197 #if defined(ENABLE_STATISTICS)
199 size_patchref += sizeof(patchref_t);
202 /* set patcher information (mpc is resolved later) */
206 pr->patcher = patcher;
211 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__SPARC_64__) || defined(__X86_64__))
213 /* XXX We can remove that when we don't use UD2 anymore on i386
216 /* On some architectures the patcher stub call instruction might
217 be longer than the actual instruction generated. On this
218 architectures we store the last patcher call position and after
219 the basic block code generation is completed, we check the
220 range and maybe generate some nop's. */
221 /* The nops are generated in codegen_emit in each codegen */
223 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
229 * Resolve all patchers in the current JIT run.
231 * @param jd JIT data-structure
233 void patcher_resolve(jitdata* jd)
238 /* Get required compiler data. */
242 for (pr = (patchref_t*) list_first(code->patchers); pr != NULL; pr = (patchref_t*) list_next(code->patchers, pr)) {
243 pr->mpc += (intptr_t) code->entrypoint;
244 pr->datap = (intptr_t) (pr->disp + code->entrypoint);
250 * Check if the patcher is already patched. This is done by comparing
251 * the machine instruction.
253 * @param pr Patcher structure.
255 * @return true if patched, false otherwise.
257 bool patcher_is_patched(patchref_t* pr)
259 // Validate the instruction at the patching position is the same
260 // instruction as the patcher structure contains.
261 uint32_t mcode = *((uint32_t*) pr->mpc);
263 if (mcode != pr->mcode) {
275 bool patcher_is_patched_at(void* pc)
277 codeinfo* code = code_find_codeinfo_for_pc(pc);
279 // Get the patcher for the given PC.
280 patchref_t* pr = patcher_list_find(code, pc);
283 // The given PC is not a patcher position.
287 // Validate the instruction.
288 return patcher_is_patched(pr);
292 /* patcher_handler *************************************************************
294 Handles the request to patch JIT code at the given patching
295 position. This function is normally called by the signal
298 NOTE: The patcher list lock is used to maintain exclusive
299 access of the patched position (in fact of the whole code).
300 After patching has suceeded, the patcher reference should be
301 removed from the patcher list to avoid double patching.
303 *******************************************************************************/
306 /* XXX this indent is not thread safe! */
307 /* XXX if you want it thread safe, place patcher_depth in threadobject! */
308 static int patcher_depth = 0;
309 #define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
310 #endif /* !defined(NDEBUG) */
312 java_handle_t *patcher_handler(u1 *pc)
319 patcher_function_list_t *l;
323 /* define the patcher function */
325 bool (*patcher_function)(patchref_t *);
327 /* search the codeinfo for the given PC */
329 code = code_find_codeinfo_for_pc(pc);
332 /* enter a monitor on the patcher list */
334 list_lock(code->patchers);
336 /* search the patcher information for the given PC */
338 pr = patcher_list_find(code, pc);
341 vm_abort("patcher_handler: Unable to find patcher reference.");
345 if (opt_DebugPatcher) {
346 log_println("patcher_handler: double-patching detected!");
349 list_unlock(code->patchers);
354 if (opt_DebugPatcher) {
355 for (l = patcher_function_list; l->patcher != NULL; l++)
356 if (l->patcher == pr->patcher)
359 TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->mpc);
360 TRACE_PATCHER_INDENT; printf("\tpatcher function = %s <%p>\n", l->name, (void *) (intptr_t) pr->patcher);
362 TRACE_PATCHER_INDENT;
363 printf("\tmachine code before = ");
365 # if defined(ENABLE_DISASSEMBLER)
366 disassinstr((u1*) (void*) pr->mpc);
368 printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
372 assert(patcher_depth > 0);
376 /* cast the passed function to a patcher function */
378 patcher_function = (bool (*)(patchref_t *)) (ptrint) pr->patcher;
380 /* call the proper patcher function */
382 result = (patcher_function)(pr);
385 if (opt_DebugPatcher) {
386 assert(patcher_depth > 0);
389 TRACE_PATCHER_INDENT;
390 printf("\tmachine code after = ");
392 # if defined(ENABLE_DISASSEMBLER)
393 disassinstr((u1*) (void*) pr->mpc);
395 printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
398 if (result == false) {
399 TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
404 /* check for return value and exit accordingly */
406 if (result == false) {
407 e = exceptions_get_and_clear_exception();
409 list_unlock(code->patchers);
414 pr->done = true; /* XXX this is only preliminary to prevent double-patching */
416 list_unlock(code->patchers);
422 /* patcher_initialize_class ****************************************************
424 Initalizes a given classinfo pointer.
425 This function does not patch any data.
427 *******************************************************************************/
429 bool patcher_initialize_class(patchref_t *pr)
433 /* get stuff from the patcher reference */
435 c = (classinfo *) pr->ref;
437 /* check if the class is initialized */
439 if (!(c->state & CLASS_INITIALIZED))
440 if (!initialize_class(c))
443 /* patch back original code */
445 patcher_patch_code(pr);
451 /* patcher_resolve_class *******************************************************
453 Resolves a given unresolved class reference.
454 This function does not patch any data.
456 *******************************************************************************/
458 #ifdef ENABLE_VERIFIER
459 bool patcher_resolve_class(patchref_t *pr)
461 unresolved_class *uc;
463 /* get stuff from the patcher reference */
465 uc = (unresolved_class *) pr->ref;
467 /* resolve the class and check subtype constraints */
469 if (!resolve_class_eager_no_access_check(uc))
472 /* patch back original code */
474 patcher_patch_code(pr);
478 #endif /* ENABLE_VERIFIER */
481 /* patcher_resolve_native_function *********************************************
483 Resolves the native function for a given methodinfo.
484 This function patches one data segment word.
486 *******************************************************************************/
488 bool patcher_resolve_native_function(patchref_t *pr)
494 /* get stuff from the patcher reference */
496 m = (methodinfo *) pr->ref;
497 datap = (uint8_t *) pr->datap;
499 /* resolve native function */
501 if (!(f = native_method_resolve(m)))
504 /* patch native function pointer */
506 *((intptr_t *) datap) = (intptr_t) f;
508 /* synchronize data cache */
510 md_dcacheflush(datap, SIZEOF_VOID_P);
512 /* patch back original code */
514 patcher_patch_code(pr);
521 * These are local overrides for various environment variables in Emacs.
522 * Please do not remove this and leave it at the end of the file, where
523 * Emacs will automagically detect them.
524 * ---------------------------------------------------------------------
527 * indent-tabs-mode: t
531 * vim:noexpandtab:sw=4:ts=4: