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