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
35 #include "codegen.h" /* for PATCHER_NOPS */
38 #include "mm/memory.h"
40 #include "native/native.hpp"
42 #include "toolbox/list.hpp"
43 #include "toolbox/logging.h" /* XXX remove me! */
45 #include "vm/exceptions.hpp"
46 #include "vm/initialize.hpp"
47 #include "vm/options.h"
48 #include "vm/resolve.hpp"
49 #include "vm/vm.hpp" /* for vm_abort */
51 #include "vm/jit/code.hpp"
52 #include "vm/jit/disass.h"
53 #include "vm/jit/jit.hpp"
54 #include "vm/jit/patcher-common.hpp"
57 /* patcher_function_list *******************************************************
59 This is a list which maps patcher function pointers to the according
60 names of the patcher functions. It is only usefull for debugging
63 *******************************************************************************/
66 typedef struct patcher_function_list_t {
69 } patcher_function_list_t;
71 static patcher_function_list_t patcher_function_list[] = {
72 { PATCHER_initialize_class, "initialize_class" },
73 { PATCHER_resolve_class, "resolve_class" },
74 { PATCHER_resolve_native_function, "resolve_native_function" },
75 { PATCHER_invokestatic_special, "invokestatic_special" },
76 { PATCHER_invokevirtual, "invokevirtual" },
77 { PATCHER_invokeinterface, "invokeinterface" },
78 { NULL, "-UNKNOWN PATCHER FUNCTION-" }
83 /* patcher_list_create *********************************************************
85 Creates an empty patcher list for the given codeinfo.
87 *******************************************************************************/
89 void patcher_list_create(codeinfo *code)
91 code->patchers = new List<patchref_t>();
95 /* patcher_list_reset **********************************************************
97 Resets the patcher list inside a codeinfo. This is usefull when
98 resetting a codeinfo for recompiling.
100 *******************************************************************************/
102 void patcher_list_reset(codeinfo *code)
104 #if defined(ENABLE_STATISTICS)
106 size_patchref -= sizeof(patchref_t) * code->patchers->size();
109 // Free all elements of the list.
110 code->patchers->clear();
113 /* patcher_list_free ***********************************************************
115 Frees the patcher list and all its entries for the given codeinfo.
117 *******************************************************************************/
119 void patcher_list_free(codeinfo *code)
121 // Free all elements of the list.
122 patcher_list_reset(code);
124 // Free the list itself.
125 delete code->patchers;
130 * Find an entry inside the patcher list for the given codeinfo by
131 * specifying the program counter of the patcher position.
133 * NOTE: Caller should hold the patcher list lock or maintain
134 * exclusive access otherwise.
136 * @param pc Program counter to find.
138 * @return Pointer to patcher.
141 struct foo : public std::binary_function<patchref_t, void*, bool> {
142 bool operator() (const patchref_t& pr, const void* pc) const
144 return (pr.mpc == (uintptr_t) pc);
148 static patchref_t* patcher_list_find(codeinfo* code, void* pc)
150 // Search for a patcher with the given PC.
151 List<patchref_t>::iterator it = std::find_if(code->patchers->begin(), code->patchers->end(), std::bind2nd(foo(), pc));
153 if (it == code->patchers->end())
160 /* patcher_add_patch_ref *******************************************************
162 Appends a new patcher reference to the list of patching positions.
164 *******************************************************************************/
166 void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
174 patchmpc = cd->mcodeptr - cd->mcodebase;
177 if (patcher_list_find(code, (void*) (intptr_t) patchmpc) != NULL)
178 vm_abort("patcher_add_patch_ref: different patchers at same position.");
181 // Set patcher information (mpc is resolved later).
187 pr.patcher = patcher;
192 #if defined(ENABLE_JITCACHE)
193 pr.attached_ref = NULL;
196 // Store patcher in the list (NOTE: structure is copied).
197 code->patchers->push_back(pr);
199 #if defined(ENABLE_STATISTICS)
201 size_patchref += sizeof(patchref_t);
204 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__SPARC_64__) || defined(__X86_64__))
206 /* XXX We can remove that when we don't use UD2 anymore on i386
209 /* On some architectures the patcher stub call instruction might
210 be longer than the actual instruction generated. On this
211 architectures we store the last patcher call position and after
212 the basic block code generation is completed, we check the
213 range and maybe generate some nop's. */
214 /* The nops are generated in codegen_emit in each codegen */
216 cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
222 * Resolve all patchers in the current JIT run.
224 * @param jd JIT data-structure
226 void patcher_resolve(jitdata* jd)
228 // Get required compiler data.
229 codeinfo* code = jd->code;
231 for (List<patchref_t>::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) {
232 patchref_t& pr = *it;
234 pr.mpc += (intptr_t) code->entrypoint;
235 pr.datap = (intptr_t) (pr.disp + code->entrypoint);
241 * Check if the patcher is already patched. This is done by comparing
242 * the machine instruction.
244 * @param pr Patcher structure.
246 * @return true if patched, false otherwise.
248 bool patcher_is_patched(patchref_t* pr)
250 // Validate the instruction at the patching position is the same
251 // instruction as the patcher structure contains.
252 uint32_t mcode = *((uint32_t*) pr->mpc);
254 if (mcode != pr->mcode) {
266 bool patcher_is_patched_at(void* pc)
268 codeinfo* code = code_find_codeinfo_for_pc(pc);
270 // Get the patcher for the given PC.
271 patchref_t* pr = patcher_list_find(code, pc);
274 // The given PC is not a patcher position.
278 // Validate the instruction.
279 return patcher_is_patched(pr);
283 /* patcher_handler *************************************************************
285 Handles the request to patch JIT code at the given patching
286 position. This function is normally called by the signal
289 NOTE: The patcher list lock is used to maintain exclusive
290 access of the patched position (in fact of the whole code).
291 After patching has suceeded, the patcher reference should be
292 removed from the patcher list to avoid double patching.
294 *******************************************************************************/
297 /* XXX this indent is not thread safe! */
298 /* XXX if you want it thread safe, place patcher_depth in threadobject! */
299 static int patcher_depth = 0;
300 #define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
301 #endif /* !defined(NDEBUG) */
303 java_handle_t *patcher_handler(u1 *pc)
310 patcher_function_list_t *l;
314 /* define the patcher function */
316 bool (*patcher_function)(patchref_t *);
318 /* search the codeinfo for the given PC */
320 code = code_find_codeinfo_for_pc(pc);
323 // Enter a mutex on the patcher list.
324 code->patchers->lock();
326 /* search the patcher information for the given PC */
328 pr = patcher_list_find(code, pc);
331 vm_abort("patcher_handler: Unable to find patcher reference.");
335 if (opt_DebugPatcher) {
336 log_println("patcher_handler: double-patching detected!");
339 code->patchers->unlock();
344 if (opt_DebugPatcher) {
345 for (l = patcher_function_list; l->patcher != NULL; l++)
346 if (l->patcher == pr->patcher)
349 TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->mpc);
350 TRACE_PATCHER_INDENT; printf("\tpatcher function = %s <%p>\n", l->name, (void *) (intptr_t) pr->patcher);
352 TRACE_PATCHER_INDENT;
353 printf("\tmachine code before = ");
355 # if defined(ENABLE_DISASSEMBLER)
356 disassinstr((u1*) (void*) pr->mpc);
358 printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
362 assert(patcher_depth > 0);
366 /* cast the passed function to a patcher function */
368 patcher_function = (bool (*)(patchref_t *)) (ptrint) pr->patcher;
370 /* call the proper patcher function */
372 result = (patcher_function)(pr);
375 if (opt_DebugPatcher) {
376 assert(patcher_depth > 0);
379 TRACE_PATCHER_INDENT;
380 printf("\tmachine code after = ");
382 # if defined(ENABLE_DISASSEMBLER)
383 disassinstr((u1*) (void*) pr->mpc);
385 printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
388 if (result == false) {
389 TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
394 #if defined(ENABLE_JITCACHE)
395 /* Put cached reference into the code and remove it from the patcher */
396 if (pr->attached_ref)
398 jitcache_handle_cached_ref(pr->attached_ref, code);
399 pr->attached_ref = NULL;
403 /* check for return value and exit accordingly */
405 if (result == false) {
406 e = exceptions_get_and_clear_exception();
408 code->patchers->unlock();
413 pr->done = true; /* XXX this is only preliminary to prevent double-patching */
415 code->patchers->unlock();
421 /* patcher_initialize_class ****************************************************
423 Initalizes a given classinfo pointer.
424 This function does not patch any data.
426 *******************************************************************************/
428 bool patcher_initialize_class(patchref_t *pr)
432 /* get stuff from the patcher reference */
434 c = (classinfo *) pr->ref;
436 /* check if the class is initialized */
438 if (!(c->state & CLASS_INITIALIZED))
439 if (!initialize_class(c))
442 /* patch back original code */
444 patcher_patch_code(pr);
450 /* patcher_resolve_class *******************************************************
452 Resolves a given unresolved class reference.
453 This function does not patch any data.
455 *******************************************************************************/
457 #ifdef ENABLE_VERIFIER
458 bool patcher_resolve_class(patchref_t *pr)
460 unresolved_class *uc;
462 /* get stuff from the patcher reference */
464 uc = (unresolved_class *) pr->ref;
466 /* resolve the class and check subtype constraints */
468 if (!resolve_class_eager_no_access_check(uc))
471 /* patch back original code */
473 patcher_patch_code(pr);
477 #endif /* ENABLE_VERIFIER */
480 /* patcher_resolve_native_function *********************************************
482 Resolves the native function for a given methodinfo.
483 This function patches one data segment word.
485 *******************************************************************************/
487 bool patcher_resolve_native_function(patchref_t *pr)
492 /* get stuff from the patcher reference */
494 m = (methodinfo *) pr->ref;
495 datap = (uint8_t *) pr->datap;
497 /* resolve native function */
499 NativeMethods& nm = VM::get_current()->get_nativemethods();
500 void* f = nm.resolve_method(m);
505 /* patch native function pointer */
507 *((intptr_t*) datap) = (intptr_t) f;
509 /* synchronize data cache */
511 md_dcacheflush(datap, SIZEOF_VOID_P);
513 /* patch back original code */
515 patcher_patch_code(pr);
520 /** Placeholder functions to calm down linker */
521 #if defined(__I386__)
522 bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
527 bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
532 bool patcher_resolve_classref_to_index(patchref_t *pr)
537 bool patcher_resolve_classref_to_flags(patchref_t *pr)
544 * These are local overrides for various environment variables in Emacs.
545 * Please do not remove this and leave it at the end of the file, where
546 * Emacs will automagically detect them.
547 * ---------------------------------------------------------------------
550 * indent-tabs-mode: t
554 * vim:noexpandtab:sw=4:ts=4: