Merged 7484:52fc709fd248.
[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
35 #include "mm/memory.h"
36
37 #include "native/native.h"
38
39 #include "threads/lock-common.h"
40
41 #include "toolbox/list.h"
42 #include "toolbox/logging.h"           /* XXX remove me! */
43
44 #include "vm/exceptions.h"
45 #include "vm/initialize.h"
46 #include "vm/resolve.h"
47 #include "vm/vm.h"                     /* for vm_abort */
48
49 #include "vm/jit/code.h"
50 #include "vm/jit/jit.h"
51 #include "vm/jit/md.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                 log_println("patcher_handler: double-patching detected!");
289                 LOCK_MONITOR_EXIT(code->patchers);
290                 return NULL;
291         }
292
293 #if !defined(NDEBUG)
294         if (opt_DebugPatcher) {
295                 for (l = patcher_function_list; l->patcher != NULL; l++)
296                         if (l->patcher == pr->patcher)
297                                 break;
298
299                 TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->mpc);
300                 TRACE_PATCHER_INDENT; printf("\tpatcher function = %s <%p>\n", l->name, (void *) pr->patcher);
301                 TRACE_PATCHER_INDENT; printf("\tmcodes before = "); for (i=0; i<5; i++) printf("0x%08x ", *((u4 *) pr->mpc + i)); printf("\n");
302                 patcher_depth++;
303                 assert(patcher_depth > 0);
304         }
305 #endif
306
307         /* cast the passed function to a patcher function */
308
309         patcher_function = (bool (*)(patchref_t *)) (ptrint) pr->patcher;
310
311         /* call the proper patcher function */
312
313         result = (patcher_function)(pr);
314
315 #if !defined(NDEBUG)
316         if (opt_DebugPatcher) {
317                 assert(patcher_depth > 0);
318                 patcher_depth--;
319                 TRACE_PATCHER_INDENT; printf("\tmcodes after  = "); for (i=0; i<5; i++) printf("0x%08x ", *((u4 *) pr->mpc + i)); printf("\n");
320                 if (result == false) {
321                         TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
322                 }
323         }
324 #endif
325
326         /* check for return value and exit accordingly */
327
328         if (result == false) {
329                 e = exceptions_get_and_clear_exception();
330
331                 LOCK_MONITOR_EXIT(code->patchers);
332
333                 return e;
334         }
335
336         pr->done = true; /* XXX this is only preliminary to prevent double-patching */
337
338         LOCK_MONITOR_EXIT(code->patchers);
339
340         return NULL;
341 }
342
343
344 /* patcher_initialize_class ****************************************************
345
346    Initalizes a given classinfo pointer.
347    This function does not patch any data.
348
349 *******************************************************************************/
350
351 bool patcher_initialize_class(patchref_t *pr)
352 {
353         classinfo *c;
354
355         /* get stuff from the patcher reference */
356
357         c = (classinfo *) pr->ref;
358
359         /* check if the class is initialized */
360
361         if (!(c->state & CLASS_INITIALIZED))
362                 if (!initialize_class(c))
363                         return false;
364
365         /* patch back original code */
366
367         patcher_patch_code(pr);
368
369         return true;
370 }
371
372
373 /* patcher_resolve_class *******************************************************
374
375    Resolves a given unresolved class reference.
376    This function does not patch any data.
377
378 *******************************************************************************/
379
380 #ifdef ENABLE_VERIFIER
381 bool patcher_resolve_class(patchref_t *pr)
382 {
383         unresolved_class *uc;
384
385         /* get stuff from the patcher reference */
386
387         uc = (unresolved_class *) pr->ref;
388
389         /* resolve the class and check subtype constraints */
390
391         if (!resolve_class_eager_no_access_check(uc))
392                 return false;
393
394         /* patch back original code */
395
396         patcher_patch_code(pr);
397
398         return true;
399 }
400 #endif /* ENABLE_VERIFIER */
401
402
403 /* patcher_resolve_native_function *********************************************
404
405    Resolves the native function for a given methodinfo.
406    This function patches one data segment word.
407
408 *******************************************************************************/
409
410 bool patcher_resolve_native_function(patchref_t *pr)
411 {
412         methodinfo  *m;
413         uint8_t     *datap;
414         functionptr  f;
415
416         /* get stuff from the patcher reference */
417
418         m     = (methodinfo *) pr->ref;
419         datap = (uint8_t *)    pr->datap;
420
421         /* resolve native function */
422
423         if (!(f = native_resolve_function(m)))
424                 return false;
425
426         /* patch native function pointer */
427
428         *((intptr_t *) datap) = (intptr_t) f;
429
430         /* synchronize data cache */
431
432         md_dcacheflush(datap, SIZEOF_VOID_P);
433
434         /* patch back original code */
435
436         patcher_patch_code(pr);
437
438         return true;
439 }
440
441
442 /*
443  * These are local overrides for various environment variables in Emacs.
444  * Please do not remove this and leave it at the end of the file, where
445  * Emacs will automagically detect them.
446  * ---------------------------------------------------------------------
447  * Local variables:
448  * mode: c
449  * indent-tabs-mode: t
450  * c-basic-offset: 4
451  * tab-width: 4
452  * End:
453  * vim:noexpandtab:sw=4:ts=4:
454  */
455