* Merged with 03e39cff22db.
[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 zu Foerderung der freien virtuellen Machine 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_unsynced(code->patchers);
153         while (pr) {
154
155 /*#define TRACE_PATCHER_FIND*/
156 #ifdef TRACE_PATCHER_FIND
157                 log_println("patcher_list_find: %p == %p", pr->mpc, pc);
158 #endif
159
160                 if (pr->mpc == (ptrint) pc)
161                         return pr;
162
163                 pr = list_next_unsynced(code->patchers, pr);
164         }
165
166         return NULL;
167 }
168
169
170 /* patcher_add_patch_ref *******************************************************
171
172    Appends a new patcher reference to the list of patching positions.
173
174 *******************************************************************************/
175
176 void patcher_add_patch_ref(jitdata *jd, functionptr patcher, voidptr ref,
177                            s4 disp)
178 {
179         codegendata *cd;
180         codeinfo    *code;
181         patchref_t  *pr;
182         s4           patchmpc;
183
184         cd       = jd->cd;
185         code     = jd->code;
186         patchmpc = cd->mcodeptr - cd->mcodebase;
187
188 #if !defined(NDEBUG)
189         if (patcher_list_find(code, (u1 *) (intptr_t) patchmpc) != NULL)
190                 vm_abort("patcher_add_patch_ref: different patchers at same position.");
191 #endif
192
193         /* allocate patchref on heap (at least freed together with codeinfo) */
194
195         pr = NEW(patchref_t);
196         list_add_first_unsynced(code->patchers, pr);
197
198 #if defined(ENABLE_STATISTICS)
199         if (opt_stat)
200                 size_patchref += sizeof(patchref_t);
201 #endif
202
203         /* set patcher information (mpc is resolved later) */
204
205         pr->mpc     = patchmpc;
206         pr->disp    = disp;
207         pr->patcher = patcher;
208         pr->ref     = ref;
209         pr->mcode   = 0;
210         pr->done    = false;
211
212         /* Generate NOPs for opt_shownops. */
213
214         if (opt_shownops)
215                 PATCHER_NOPS;
216
217 #if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__SPARC_64__) || defined(__X86_64__))
218
219         /* XXX We can remove that when we don't use UD2 anymore on i386
220            and x86_64. */
221
222         /* On some architectures the patcher stub call instruction might
223            be longer than the actual instruction generated.  On this
224            architectures we store the last patcher call position and after
225            the basic block code generation is completed, we check the
226            range and maybe generate some nop's. */
227         /* The nops are generated in codegen_emit in each codegen */
228
229         cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
230 #endif
231 }
232
233
234 /* patcher_handler *************************************************************
235
236    Handles the request to patch JIT code at the given patching
237    position. This function is normally called by the signal
238    handler.
239
240    NOTE: The patcher list lock is used to maintain exclusive
241    access of the patched position (in fact of the whole code).
242    After patching has suceeded, the patcher reference should be
243    removed from the patcher list to avoid double patching.
244
245 *******************************************************************************/
246
247 #if !defined(NDEBUG)
248 /* XXX this indent is not thread safe! */
249 /* XXX if you want it thread safe, place patcher_depth in threadobject! */
250 static int patcher_depth = 0;
251 #define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
252 #endif /* !defined(NDEBUG) */
253
254 java_handle_t *patcher_handler(u1 *pc)
255 {
256         codeinfo      *code;
257         patchref_t    *pr;
258         bool           result;
259         java_handle_t *e;
260 #if !defined(NDEBUG)
261         patcher_function_list_t *l;
262         int                      i;
263 #endif
264
265         /* define the patcher function */
266
267         bool (*patcher_function)(patchref_t *);
268
269         /* search the codeinfo for the given PC */
270
271         code = code_find_codeinfo_for_pc(pc);
272         assert(code);
273
274         /* enter a monitor on the patcher list */
275
276         LOCK_MONITOR_ENTER(code->patchers);
277
278         /* search the patcher information for the given PC */
279
280         pr = patcher_list_find(code, pc);
281
282         if (pr == NULL)
283                 vm_abort("patcher_handler: Unable to find patcher reference.");
284
285         if (pr->done) {
286 #if !defined(NDEBUG)
287                 if (opt_DebugPatcher) {
288                         log_println("patcher_handler: double-patching detected!");
289                 }
290 #endif
291                 LOCK_MONITOR_EXIT(code->patchers);
292                 return NULL;
293         }
294
295 #if !defined(NDEBUG)
296         if (opt_DebugPatcher) {
297                 for (l = patcher_function_list; l->patcher != NULL; l++)
298                         if (l->patcher == pr->patcher)
299                                 break;
300
301                 TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->mpc);
302                 TRACE_PATCHER_INDENT; printf("\tpatcher function = %s <%p>\n", l->name, (void *) (intptr_t) pr->patcher);
303                 TRACE_PATCHER_INDENT; printf("\tmcodes before = "); for (i=0; i<5; i++) printf("0x%08x ", *((u4 *) pr->mpc + i)); printf("\n");
304                 patcher_depth++;
305                 assert(patcher_depth > 0);
306         }
307 #endif
308
309         /* cast the passed function to a patcher function */
310
311         patcher_function = (bool (*)(patchref_t *)) (ptrint) pr->patcher;
312
313         /* call the proper patcher function */
314
315         result = (patcher_function)(pr);
316
317 #if !defined(NDEBUG)
318         if (opt_DebugPatcher) {
319                 assert(patcher_depth > 0);
320                 patcher_depth--;
321                 TRACE_PATCHER_INDENT; printf("\tmcodes after  = "); for (i=0; i<5; i++) printf("0x%08x ", *((u4 *) pr->mpc + i)); printf("\n");
322                 if (result == false) {
323                         TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
324                 }
325         }
326 #endif
327
328         /* check for return value and exit accordingly */
329
330         if (result == false) {
331                 e = exceptions_get_and_clear_exception();
332
333                 LOCK_MONITOR_EXIT(code->patchers);
334
335                 return e;
336         }
337
338         pr->done = true; /* XXX this is only preliminary to prevent double-patching */
339
340         LOCK_MONITOR_EXIT(code->patchers);
341
342         return NULL;
343 }
344
345
346 /* patcher_initialize_class ****************************************************
347
348    Initalizes a given classinfo pointer.
349    This function does not patch any data.
350
351 *******************************************************************************/
352
353 bool patcher_initialize_class(patchref_t *pr)
354 {
355         classinfo *c;
356
357         /* get stuff from the patcher reference */
358
359         c = (classinfo *) pr->ref;
360
361         /* check if the class is initialized */
362
363         if (!(c->state & CLASS_INITIALIZED))
364                 if (!initialize_class(c))
365                         return false;
366
367         /* patch back original code */
368
369         patcher_patch_code(pr);
370
371         return true;
372 }
373
374
375 /* patcher_resolve_class *******************************************************
376
377    Resolves a given unresolved class reference.
378    This function does not patch any data.
379
380 *******************************************************************************/
381
382 #ifdef ENABLE_VERIFIER
383 bool patcher_resolve_class(patchref_t *pr)
384 {
385         unresolved_class *uc;
386
387         /* get stuff from the patcher reference */
388
389         uc = (unresolved_class *) pr->ref;
390
391         /* resolve the class and check subtype constraints */
392
393         if (!resolve_class_eager_no_access_check(uc))
394                 return false;
395
396         /* patch back original code */
397
398         patcher_patch_code(pr);
399
400         return true;
401 }
402 #endif /* ENABLE_VERIFIER */
403
404
405 /* patcher_resolve_native_function *********************************************
406
407    Resolves the native function for a given methodinfo.
408    This function patches one data segment word.
409
410 *******************************************************************************/
411
412 bool patcher_resolve_native_function(patchref_t *pr)
413 {
414         methodinfo  *m;
415         uint8_t     *datap;
416         functionptr  f;
417
418         /* get stuff from the patcher reference */
419
420         m     = (methodinfo *) pr->ref;
421         datap = (uint8_t *)    pr->datap;
422
423         /* resolve native function */
424
425         if (!(f = native_method_resolve(m)))
426                 return false;
427
428         /* patch native function pointer */
429
430         *((intptr_t *) datap) = (intptr_t) f;
431
432         /* synchronize data cache */
433
434         md_dcacheflush(datap, SIZEOF_VOID_P);
435
436         /* patch back original code */
437
438         patcher_patch_code(pr);
439
440         return true;
441 }
442
443
444 /*
445  * These are local overrides for various environment variables in Emacs.
446  * Please do not remove this and leave it at the end of the file, where
447  * Emacs will automagically detect them.
448  * ---------------------------------------------------------------------
449  * Local variables:
450  * mode: c
451  * indent-tabs-mode: t
452  * c-basic-offset: 4
453  * tab-width: 4
454  * End:
455  * vim:noexpandtab:sw=4:ts=4:
456  */
457