* src/vm/jit/patcher-common.c (patcher_resolve): New function.
[cacao.git] / src / vm / jit / patcher-common.c
1 /* src/vm/jit/patcher-common.c - architecture independent code patching stuff
2
3    Copyright (C) 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <stdint.h>
30
31 #include "codegen.h"                   /* for PATCHER_NOPS */
32 #include "md.h"
33
34 #include "mm/memory.h"
35
36 #include "native/native.h"
37
38 #include "threads/lock-common.h"
39
40 #include "toolbox/list.h"
41 #include "toolbox/logging.h"           /* XXX remove me! */
42
43 #include "vm/exceptions.h"
44 #include "vm/initialize.h"
45 #include "vm/resolve.h"
46 #include "vm/vm.h"                     /* for vm_abort */
47
48 #include "vm/jit/code.h"
49 #include "vm/jit/jit.h"
50 #include "vm/jit/patcher-common.h"
51
52 #include "vmcore/options.h"
53
54
55 /* patcher_function_list *******************************************************
56
57    This is a list which maps patcher function pointers to the according
58    names of the patcher functions. It is only usefull for debugging
59    purposes.
60
61 *******************************************************************************/
62
63 #if !defined(NDEBUG)
64 typedef struct patcher_function_list_t {
65         functionptr  patcher;
66         char        *name;
67 } patcher_function_list_t;
68
69 static patcher_function_list_t patcher_function_list[] = {
70         { PATCHER_initialize_class,              "initialize_class" },
71         { PATCHER_resolve_class,                 "resolve_class" },
72         { PATCHER_resolve_native_function,       "resolve_native_function" },
73         { PATCHER_invokestatic_special,          "invokestatic_special" },
74         { PATCHER_invokevirtual,                 "invokevirtual" },
75         { PATCHER_invokeinterface,               "invokeinterface" },
76         { NULL,                                  "-UNKNOWN PATCHER FUNCTION-" }
77 };
78 #endif
79
80
81 /* patcher_list_create *********************************************************
82
83    Creates an empty patcher list for the given codeinfo.
84
85 *******************************************************************************/
86
87 void patcher_list_create(codeinfo *code)
88 {
89         code->patchers = list_create(OFFSET(patchref_t, linkage));
90 }
91
92
93 /* patcher_list_reset **********************************************************
94
95    Resets the patcher list inside a codeinfo. This is usefull when
96    resetting a codeinfo for recompiling.
97
98 *******************************************************************************/
99
100 void patcher_list_reset(codeinfo *code)
101 {
102         patchref_t *pr;
103
104         /* free all elements of the list */
105
106         while((pr = list_first(code->patchers)) != NULL) {
107                 list_remove(code->patchers, pr);
108
109                 FREE(pr, patchref_t);
110
111 #if defined(ENABLE_STATISTICS)
112                 if (opt_stat)
113                         size_patchref -= sizeof(patchref_t);
114 #endif
115         }
116 }
117
118 /* patcher_list_free ***********************************************************
119
120    Frees the patcher list and all its entries for the given codeinfo.
121
122 *******************************************************************************/
123
124 void patcher_list_free(codeinfo *code)
125 {
126         /* free all elements of the list */
127
128         patcher_list_reset(code);
129
130         /* free the list itself */
131
132         FREE(code->patchers, list_t);
133 }
134
135
136 /* patcher_list_find ***********************************************************
137
138    Find an entry inside the patcher list for the given codeinfo
139    by specifying the program counter of the patcher position.
140
141    NOTE: Caller should hold the patcher list lock or maintain
142    exclusive access otherwise.
143
144 *******************************************************************************/
145
146 static patchref_t *patcher_list_find(codeinfo *code, u1 *pc)
147 {
148         patchref_t *pr;
149
150         /* walk through all patcher references for the given codeinfo */
151
152         pr = list_first(code->patchers);
153
154         while (pr) {
155
156 /*#define TRACE_PATCHER_FIND*/
157 #ifdef TRACE_PATCHER_FIND
158                 log_println("patcher_list_find: %p == %p", pr->mpc, pc);
159 #endif
160
161                 if (pr->mpc == (ptrint) pc)
162                         return pr;
163
164                 pr = list_next(code->patchers, pr);
165         }
166
167         return NULL;
168 }
169
170
171 /* patcher_add_patch_ref *******************************************************
172
173    Appends a new patcher reference to the list of patching positions.
174
175 *******************************************************************************/
176
177 void patcher_add_patch_ref(jitdata *jd, functionptr patcher, voidptr ref,
178                            s4 disp)
179 {
180         codegendata *cd;
181         codeinfo    *code;
182         patchref_t  *pr;
183         s4           patchmpc;
184
185         cd       = jd->cd;
186         code     = jd->code;
187         patchmpc = cd->mcodeptr - cd->mcodebase;
188
189 #if !defined(NDEBUG)
190         if (patcher_list_find(code, (u1 *) (intptr_t) patchmpc) != NULL)
191                 vm_abort("patcher_add_patch_ref: different patchers at same position.");
192 #endif
193
194         /* allocate patchref on heap (at least freed together with codeinfo) */
195
196         pr = NEW(patchref_t);
197         list_add_first(code->patchers, pr);
198
199 #if defined(ENABLE_STATISTICS)
200         if (opt_stat)
201                 size_patchref += sizeof(patchref_t);
202 #endif
203
204         /* set patcher information (mpc is resolved later) */
205
206         pr->mpc     = patchmpc;
207         pr->disp    = disp;
208         pr->patcher = patcher;
209         pr->ref     = ref;
210         pr->mcode   = 0;
211         pr->done    = false;
212
213         /* Generate NOPs for opt_shownops. */
214
215         if (opt_shownops)
216                 PATCHER_NOPS;
217
218 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__SPARC_64__) || defined(__X86_64__))
219
220         /* XXX We can remove that when we don't use UD2 anymore on i386
221            and x86_64. */
222
223         /* On some architectures the patcher stub call instruction might
224            be longer than the actual instruction generated.  On this
225            architectures we store the last patcher call position and after
226            the basic block code generation is completed, we check the
227            range and maybe generate some nop's. */
228         /* The nops are generated in codegen_emit in each codegen */
229
230         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
231 #endif
232 }
233
234
235 /**
236  * Resolve all patchers in the current JIT run.
237  *
238  * @param jd JIT data-structure
239  */
240 void patcher_resolve(jitdata* jd)
241 {
242         codeinfo*   code;
243         patchref_t* pr;
244
245         /* Get required compiler data. */
246
247         code = jd->code;
248
249         for (pr = list_first(code->patchers); pr != NULL; pr = list_next(code->patchers, pr)) {
250                 pr->mpc   += (intptr_t) code->entrypoint;
251                 pr->datap  = (intptr_t) (pr->disp + code->entrypoint);
252         }
253 }
254
255
256 /* patcher_handler *************************************************************
257
258    Handles the request to patch JIT code at the given patching
259    position. This function is normally called by the signal
260    handler.
261
262    NOTE: The patcher list lock is used to maintain exclusive
263    access of the patched position (in fact of the whole code).
264    After patching has suceeded, the patcher reference should be
265    removed from the patcher list to avoid double patching.
266
267 *******************************************************************************/
268
269 #if !defined(NDEBUG)
270 /* XXX this indent is not thread safe! */
271 /* XXX if you want it thread safe, place patcher_depth in threadobject! */
272 static int patcher_depth = 0;
273 #define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
274 #endif /* !defined(NDEBUG) */
275
276 java_handle_t *patcher_handler(u1 *pc)
277 {
278         codeinfo      *code;
279         patchref_t    *pr;
280         bool           result;
281         java_handle_t *e;
282 #if !defined(NDEBUG)
283         patcher_function_list_t *l;
284         int                      i;
285 #endif
286
287         /* define the patcher function */
288
289         bool (*patcher_function)(patchref_t *);
290
291         /* search the codeinfo for the given PC */
292
293         code = code_find_codeinfo_for_pc(pc);
294         assert(code);
295
296         /* enter a monitor on the patcher list */
297
298         LOCK_MONITOR_ENTER(code->patchers);
299
300         /* search the patcher information for the given PC */
301
302         pr = patcher_list_find(code, pc);
303
304         if (pr == NULL)
305                 vm_abort("patcher_handler: Unable to find patcher reference.");
306
307         if (pr->done) {
308 #if !defined(NDEBUG)
309                 if (opt_DebugPatcher) {
310                         log_println("patcher_handler: double-patching detected!");
311                 }
312 #endif
313                 LOCK_MONITOR_EXIT(code->patchers);
314                 return NULL;
315         }
316
317 #if !defined(NDEBUG)
318         if (opt_DebugPatcher) {
319                 for (l = patcher_function_list; l->patcher != NULL; l++)
320                         if (l->patcher == pr->patcher)
321                                 break;
322
323                 TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->mpc);
324                 TRACE_PATCHER_INDENT; printf("\tpatcher function = %s <%p>\n", l->name, (void *) (intptr_t) pr->patcher);
325                 TRACE_PATCHER_INDENT; printf("\tmcodes before = "); for (i=0; i<5; i++) printf("0x%08x ", *((u4 *) pr->mpc + i)); printf("\n");
326                 patcher_depth++;
327                 assert(patcher_depth > 0);
328         }
329 #endif
330
331         /* cast the passed function to a patcher function */
332
333         patcher_function = (bool (*)(patchref_t *)) (ptrint) pr->patcher;
334
335         /* call the proper patcher function */
336
337         result = (patcher_function)(pr);
338
339 #if !defined(NDEBUG)
340         if (opt_DebugPatcher) {
341                 assert(patcher_depth > 0);
342                 patcher_depth--;
343                 TRACE_PATCHER_INDENT; printf("\tmcodes after  = "); for (i=0; i<5; i++) printf("0x%08x ", *((u4 *) pr->mpc + i)); printf("\n");
344                 if (result == false) {
345                         TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
346                 }
347         }
348 #endif
349
350         /* check for return value and exit accordingly */
351
352         if (result == false) {
353                 e = exceptions_get_and_clear_exception();
354
355                 LOCK_MONITOR_EXIT(code->patchers);
356
357                 return e;
358         }
359
360         pr->done = true; /* XXX this is only preliminary to prevent double-patching */
361
362         LOCK_MONITOR_EXIT(code->patchers);
363
364         return NULL;
365 }
366
367
368 /* patcher_initialize_class ****************************************************
369
370    Initalizes a given classinfo pointer.
371    This function does not patch any data.
372
373 *******************************************************************************/
374
375 bool patcher_initialize_class(patchref_t *pr)
376 {
377         classinfo *c;
378
379         /* get stuff from the patcher reference */
380
381         c = (classinfo *) pr->ref;
382
383         /* check if the class is initialized */
384
385         if (!(c->state & CLASS_INITIALIZED))
386                 if (!initialize_class(c))
387                         return false;
388
389         /* patch back original code */
390
391         patcher_patch_code(pr);
392
393         return true;
394 }
395
396
397 /* patcher_resolve_class *******************************************************
398
399    Resolves a given unresolved class reference.
400    This function does not patch any data.
401
402 *******************************************************************************/
403
404 #ifdef ENABLE_VERIFIER
405 bool patcher_resolve_class(patchref_t *pr)
406 {
407         unresolved_class *uc;
408
409         /* get stuff from the patcher reference */
410
411         uc = (unresolved_class *) pr->ref;
412
413         /* resolve the class and check subtype constraints */
414
415         if (!resolve_class_eager_no_access_check(uc))
416                 return false;
417
418         /* patch back original code */
419
420         patcher_patch_code(pr);
421
422         return true;
423 }
424 #endif /* ENABLE_VERIFIER */
425
426
427 /* patcher_resolve_native_function *********************************************
428
429    Resolves the native function for a given methodinfo.
430    This function patches one data segment word.
431
432 *******************************************************************************/
433
434 bool patcher_resolve_native_function(patchref_t *pr)
435 {
436         methodinfo  *m;
437         uint8_t     *datap;
438         functionptr  f;
439
440         /* get stuff from the patcher reference */
441
442         m     = (methodinfo *) pr->ref;
443         datap = (uint8_t *)    pr->datap;
444
445         /* resolve native function */
446
447         if (!(f = native_method_resolve(m)))
448                 return false;
449
450         /* patch native function pointer */
451
452         *((intptr_t *) datap) = (intptr_t) f;
453
454         /* synchronize data cache */
455
456         md_dcacheflush(datap, SIZEOF_VOID_P);
457
458         /* patch back original code */
459
460         patcher_patch_code(pr);
461
462         return true;
463 }
464
465
466 /*
467  * These are local overrides for various environment variables in Emacs.
468  * Please do not remove this and leave it at the end of the file, where
469  * Emacs will automagically detect them.
470  * ---------------------------------------------------------------------
471  * Local variables:
472  * mode: c
473  * indent-tabs-mode: t
474  * c-basic-offset: 4
475  * tab-width: 4
476  * End:
477  * vim:noexpandtab:sw=4:ts=4:
478  */
479