CACAO
patcher.cpp
Go to the documentation of this file.
1 /* src/vm/jit/mips/patcher.cpp - SPARC code patching functions
2 
3  Copyright (C) 1996-2013
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 <cassert>
29 #include <stdint.h>
30 
31 #include "vm/types.hpp"
32 
33 #include "mm/memory.hpp"
34 
36 #include "vm/jit/sparc64/md.hpp"
38 
39 #include "native/native.hpp"
40 
41 #include "vm/jit/builtin.hpp"
42 #include "vm/class.hpp"
43 #include "vm/exceptions.hpp"
44 #include "vm/field.hpp"
45 #include "vm/initialize.hpp"
46 #include "vm/options.hpp"
47 #include "vm/references.hpp"
48 #include "vm/resolve.hpp"
49 
50 #include "vm/jit/asmpart.hpp"
51 #include "vm/jit/patcher.hpp"
52 #include "vm/jit/methodheader.hpp"
53 #include "vm/jit/stacktrace.hpp"
54 
56 
57 
58 /* patcher_wrapper *************************************************************
59 
60  Wrapper for all patchers. It also creates the stackframe info
61  structure.
62 
63  If the return value of the patcher function is false, it gets the
64  exception object, clears the exception pointer and returns the
65  exception.
66 
67 *******************************************************************************/
68 
70 {
71  stackframeinfo_t sfi;
72  u1 *xpc;
73  u1 *javasp;
74  java_object_t *o;
75 #if SIZEOF_VOID_P == 8
76  u8 mcode;
77 #else
78  u4 mcode[2];
79 #endif
80  functionptr f;
81  bool result;
83 
84  /* define the patcher function */
85 
86  bool (*patcher_function)(u1 *);
87 
88  assert(pv != NULL);
89 
90  /* get stuff from the stack */
91 
92  xpc = (u1 *) *((ptrint *) (sp + 5 * 8));
93  o = (java_object_t *) *((ptrint *) (sp + 4 * 8));
94  f = (functionptr) *((ptrint *) (sp + 0 * 8));
95 
96  /* store PV into the patcher function position */
97 
98  *((ptrint *) (sp + 0 * 8)) = (ptrint) pv;
99 
100  /* cast the passed function to a patcher function */
101 
102  patcher_function = (bool (*)(u1 *)) (ptrint) f;
103 
104  /* enter a monitor on the patching position */
105 
106  PATCHER_MONITORENTER;
107 
108  /* the (data) sp points directly to the patcher fields */
109  /* calculate the real sp of the current java function considering the WINSAVE regs */
110 
111  javasp = sp - JITSTACK_CNT * 8 - BIAS;
112 
113  /* create the stackframeinfo */
114 
115  printf("patcher opening sfi for xpc=%p\n", xpc);
116 
117  stacktrace_stackframeinfo_add(&sfi, pv, javasp, ra, xpc);
118 
119  /* call the proper patcher function */
120 
121  result = (patcher_function)(sp);
122 
123  /* remove the stackframeinfo */
124 
126  printf("patcher closing sfi for xpc=%p\n", xpc);
127 
128  /* check for return value and exit accordingly */
129 
130  if (result == false) {
132 
133  PATCHER_MONITOREXIT;
134 
135  return e;
136  }
137 
138  /* patch back original (potentially patched) code */
139 
140 #if SIZEOF_VOID_P == 8
141  mcode = *((u8 *) (sp + 3 * 8));
142 
143  *((u4 *) (xpc + 0 * 4)) = mcode >> 32;
144  *((u4 *) (xpc + 1 * 4)) = mcode;
145 #else
146  mcode[0] = *((u4 *) (sp + 3 * 8));
147  mcode[1] = *((u4 *) (sp + 3 * 8 + 4));
148 
149  *((u4 *) (xpc + 0 * 4)) = mcode[0];
150  *((u4 *) (xpc + 1 * 4)) = mcode[1];
151 #endif
152 
153 
154  /* synchronize instruction cache */
155 
157 
158  PATCHER_MARK_PATCHED_MONITOREXIT;
159 
160  return NULL;
161 }
162 
163 
164 /* patcher_get_putstatic *******************************************************
165 
166  Machine code:
167 
168  <patched call position>
169  xxx ldx at,-72(pv)
170  xxx ld a1,0(at)
171 
172 *******************************************************************************/
173 
175 {
176  unresolved_field *uf;
177  s4 disp;
178  u1 *pv;
179  fieldinfo *fi;
180 
181  /* get stuff from the stack */
182 
183  uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
184  disp = *((s4 *) (sp + 1 * 8));
185  pv = (u1 *) *((ptrint *) (sp + 0 * 8));
186 
187  /* get the fieldinfo */
188 
189  if (!(fi = resolve_field_eager(uf)))
190  return false;
191 
192  /* check if the field's class is initialized */
193 
194  if (!(fi->clazz->state & CLASS_INITIALIZED))
195  if (!initialize_class(fi->clazz))
196  return false;
197 
198  /* patch the field value's address */
199 
200  *((intptr_t *) (pv + disp)) = (intptr_t) fi->value;
201 
202  /* synchronize data cache */
203 
204  md_dcacheflush(pv + disp, SIZEOF_VOID_P);
205 
206  return true;
207 }
208 
209 
210 /* patcher_get_putfield ********************************************************
211 
212  Machine code:
213 
214  <patched call position>
215  8ee90020 lw a5,32(s7)
216 
217 *******************************************************************************/
218 
220 {
221  u1 *ra;
222  unresolved_field *uf;
223  fieldinfo *fi;
224 
225 
226  ra = (u1 *) *((ptrint *) (sp + 5 * 8));
227  uf = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
228 
229  /* get the fieldinfo */
230 
231  if (!(fi = resolve_field_eager(uf)))
232  return false;
233 
234  /* store the patched instruction on the stack */
235 
236  *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x00001fff);
237 
238  return true;
239 }
240 
241 
242 /* patcher_aconst **************************************************************
243 
244  Machine code:
245 
246  <patched call postition>
247  xxx ld a0,-104(pv)
248 
249 *******************************************************************************/
250 
252 {
253  constant_classref *cr;
254  s4 disp;
255  u1 *pv;
256  classinfo *c;
257 
258  /* get stuff from the stack */
259 
260  cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
261  disp = *((s4 *) (sp + 1 * 8));
262  pv = (u1 *) *((ptrint *) (sp + 0 * 8));
263 
264  /* get the classinfo */
265 
266  if (!(c = resolve_classref_eager(cr)))
267  return false;
268 
269  /* patch the classinfo pointer */
270 
271  *((ptrint *) (pv + disp)) = (ptrint) c;
272 
273  /* synchronize data cache */
274 
275  md_dcacheflush(pv + disp, SIZEOF_VOID_P);
276 
277  return true;
278 }
279 
280 
281 /* patcher_builtin_multianewarray **********************************************
282 
283  Machine code:
284 
285  <patched call position>
286  dfc5ff90 ld a1,-112(s8)
287  03a03025 move a2,sp
288  dfd9ff88 ld t9,-120(s8)
289  0320f809 jalr t9
290  00000000 nop
291 
292 *******************************************************************************/
293 
295 {
296  constant_classref *cr;
297  s4 disp;
298  u1 *pv;
299  classinfo *c;
300 
301  /* get stuff from the stack */
302 
303  cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
304  disp = *((s4 *) (sp + 1 * 8));
305  pv = (u1 *) *((ptrint *) (sp + 0 * 8));
306 
307  /* get the classinfo */
308 
309  if (!(c = resolve_classref_eager(cr)))
310  return false;
311 
312  /* patch the classinfo pointer */
313 
314  *((ptrint *) (pv + disp)) = (ptrint) c;
315 
316  /* synchronize data cache */
317 
318  md_dcacheflush(pv + disp, SIZEOF_VOID_P);
319 
320  return true;
321 }
322 
323 
324 /* patcher_builtin_arraycheckcast **********************************************
325 
326  Machine code:
327 
328  <patched call position>
329  dfc5ffc0 ld a1,-64(s8)
330  dfd9ffb8 ld t9,-72(s8)
331  0320f809 jalr t9
332  00000000 nop
333 
334 *******************************************************************************/
335 
337 {
338  constant_classref *cr;
339  s4 disp;
340  u1 *pv;
341  classinfo *c;
342 
343  /* get stuff from the stack */
344 
345  cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
346  disp = *((s4 *) (sp + 1 * 8));
347  pv = (u1 *) *((ptrint *) (sp + 0 * 8));
348 
349  /* get the classinfo */
350 
351  if (!(c = resolve_classref_eager(cr)))
352  return false;
353 
354  /* patch the classinfo pointer */
355 
356  *((ptrint *) (pv + disp)) = (ptrint) c;
357 
358  /* synchronize data cache */
359 
360  md_dcacheflush(pv + disp, SIZEOF_VOID_P);
361 
362  return true;
363 }
364 
365 
366 /* patcher_invokestatic_special ************************************************
367 
368  Machine code:
369 
370  <patched call position>
371  dfdeffc0 ld s8,-64(s8)
372  03c0f809 jalr s8
373  00000000 nop
374 
375 ******************************************************************************/
376 
378 {
379  unresolved_method *um;
380  s4 disp;
381  u1 *pv;
382  methodinfo *m;
383 
384  /* get stuff from the stack */
385 
386  um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
387  disp = *((s4 *) (sp + 1 * 8));
388  pv = (u1 *) *((ptrint *) (sp + 0 * 8));
389 
390  /* get the fieldinfo */
391 
392  if (!(m = resolve_method_eager(um)))
393  return false;
394 
395  /* patch stubroutine */
396 
397  *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
398 
399  /* synchronize data cache */
400 
401  md_dcacheflush(pv + disp, SIZEOF_VOID_P);
402 
403  return true;
404 }
405 
406 
407 /* patcher_invokevirtual *******************************************************
408 
409  Machine code:
410 
411  <patched call position>
412  xxx ldx g2,0(o0)
413  xxx ldx o5,64(g2)
414  xxx jmpl o5
415  xxx nop
416 
417 *******************************************************************************/
418 
420 {
421  u1 *ra;
422  unresolved_method *um;
423  methodinfo *m;
424 
425  /* get stuff from the stack */
426 
427  ra = (u1 *) *((ptrint *) (sp + 5 * 8));
428  um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
429 
430  /* get the fieldinfo */
431 
432  if (!(m = resolve_method_eager(um)))
433  return false;
434 
435  /* patch vftbl index */
436 
437  *((s4 *) (sp + 3 * 8 + 4)) |=
438  (s4) ((OFFSET(vftbl_t, table[0]) +
439  sizeof(methodptr) * m->vftblindex) & 0x00001fff);
440 
441  return true;
442 }
443 
444 
445 /* patcher_invokeinterface *****************************************************
446 
447  Machine code:
448 
449  <patched call position>
450  dc990000 ld t9,0(a0)
451  df39ffa0 ld t9,-96(t9)
452  df3e0018 ld s8,24(t9)
453  03c0f809 jalr s8
454  00000000 nop
455 
456 *******************************************************************************/
457 
459 {
460  u1 *ra;
461  unresolved_method *um;
462  methodinfo *m;
463 
464  /* get stuff from the stack */
465 
466  ra = (u1 *) *((ptrint *) (sp + 5 * 8));
467  um = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
468 
469  /* get the fieldinfo */
470 
471  if (!(m = resolve_method_eager(um)))
472  return false;
473 
474  /* patch interfacetable index */
475 
476  *((s4 *) (sp + 3 * 8 + 4)) |=
477  (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
478  sizeof(methodptr*) * m->clazz->index) & 0x00001fff);
479 
480  /* patch method offset */
481 
482  *((s4 *) (ra + 2 * 4)) |=
483  (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x00001fff);
484 
485  /* synchronize instruction cache */
486 
487  md_icacheflush(ra + 2 * 4, 1 * 4);
488 
489  return true;
490 }
491 
492 
493 /* patcher_checkcast_instanceof_flags ******************************************
494 
495  Machine code:
496 
497  <patched call position>
498  8fc3ff24 lw v1,-220(s8)
499  30630200 andi v1,v1,512
500  1060000d beq v1,zero,0x000000001051824c
501  00000000 nop
502 
503 *******************************************************************************/
504 
506 {
507  constant_classref *cr;
508  s4 disp;
509  u1 *pv;
510  classinfo *c;
511 
512  /* get stuff from the stack */
513 
514  cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
515  disp = *((s4 *) (sp + 1 * 8));
516  pv = (u1 *) *((ptrint *) (sp + 0 * 8));
517 
518  /* get the fieldinfo */
519 
520  if (!(c = resolve_classref_eager(cr)))
521  return false;
522 
523  /* patch class flags */
524 
525  *((s4 *) (pv + disp)) = (s4) c->flags;
526 
527  /* synchronize data cache */
528 
529  md_dcacheflush(pv + disp, sizeof(s4));
530 
531  return true;
532 }
533 
534 
535 /* patcher_checkcast_interface **************************************
536 
537  Machine code:
538 
539  <patched call position>
540  dd030000 ld v1,0(a4)
541  8c79001c lw t9,28(v1)
542  27390000 addiu t9,t9,0
543  1b200082 blez t9,zero,0x000000001051843c
544  00000000 nop
545  dc790000 ld t9,0(v1)
546 
547 *******************************************************************************/
548 
550 {
551  u1 *ra;
552  constant_classref *cr;
553  classinfo *c;
554 
555  /* get stuff from the stack */
556 
557  ra = (u1 *) *((ptrint *) (sp + 5 * 8));
558  cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
559 
560  /* get the fieldinfo */
561 
562  if (!(c = resolve_classref_eager(cr)))
563  return false;
564 
565  /* patch super class index */
566 
567  *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x00001fff);
568 
569  *((s4 *) (ra + (3 + EXCEPTION_CHECK_INSTRUCTIONS) * 4)) |=
570  (s4) ((OFFSET(vftbl_t, interfacetable[0])
571  - c->index * sizeof(methodptr*)) & 0x00001fff);
572 
573  /* synchronize instruction cache */
574 
576 
577  return true;
578 }
579 
580 /* patcher_instanceof_interface ************************************************
581 
582  Machine code:
583 
584  <patched call position>
585  dd030000 ld v1,0(a4)
586  8c79001c lw t9,28(v1)
587  27390000 addiu t9,t9,0
588  1b200082 blez t9,zero,0x000000001051843c
589  00000000 nop
590  dc790000 ld t9,0(v1)
591 
592 *******************************************************************************/
593 
595 {
596  u1 *ra;
597  constant_classref *cr;
598  classinfo *c;
599 
600  /* get stuff from the stack */
601 
602  ra = (u1 *) *((ptrint *) (sp + 5 * 8));
603  cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
604 
605  /* get the fieldinfo */
606 
607  if (!(c = resolve_classref_eager(cr)))
608  return false;
609 
610  /* patch super class index */
611 
612  *((s4 *) (ra + 2 * 4)) |= (s4) ((c->index) & 0x00001fff);
613  *((s4 *) (ra + 5 * 4)) |=
614  (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
615  c->index * sizeof(methodptr*)) & 0x00001fff);
616 
617  /* synchronize instruction cache */
618 
619  md_icacheflush(ra, 6 * 4);
620 
621  return true;
622 }
623 
624 
625 /* patcher_checkcast_instanceof_class ******************************************
626 
627  Machine code:
628 
629  <patched call position>
630  dd030000 ld v1,0(a4)
631  dfd9ff18 ld t9,-232(s8)
632 
633 *******************************************************************************/
634 
636 {
637  constant_classref *cr;
638  s4 disp;
639  u1 *pv;
640  classinfo *c;
641 
642  /* get stuff from the stack */
643 
644  cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
645  disp = *((s4 *) (sp + 1 * 8));
646  pv = (u1 *) *((ptrint *) (sp + 0 * 8));
647 
648  /* get the fieldinfo */
649 
650  if (!(c = resolve_classref_eager(cr)))
651  return false;
652 
653  /* patch super class' vftbl */
654 
655  *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
656 
657  /* synchronize data cache */
658 
659  md_dcacheflush(pv + disp, SIZEOF_VOID_P);
660 
661  return true;
662 }
663 
664 
665 /* patcher_clinit **************************************************************
666 
667  No special machine code.
668 
669 *******************************************************************************/
670 
672 {
673  classinfo *c;
674 
675  /* get stuff from the stack */
676 
677  c = (classinfo *) *((ptrint *) (sp + 2 * 8));
678 
679  /* check if the class is initialized */
680 
681  if (!(c->state & CLASS_INITIALIZED))
682  if (!initialize_class(c))
683  return false;
684 
685  return true;
686 }
687 
688 
689 /* patcher_athrow_areturn ******************************************************
690 
691  Machine code:
692 
693  <patched call position>
694 
695 *******************************************************************************/
696 
697 #ifdef ENABLE_VERIFIER
699 {
700  unresolved_class *uc;
701 
702  /* get stuff from the stack */
703 
704  uc = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
705 
706  /* resolve the class and check subtype constraints */
707 
709  return false;
710 
711  return true;
712 }
713 #endif /* ENABLE_VERIFIER */
714 
715 
716 /* patcher_resolve_native ******************************************************
717 
718  XXX
719 
720 *******************************************************************************/
721 
723 {
724  methodinfo *m;
725  s4 disp;
726  u1 *pv;
727  functionptr f;
728 
729  /* get stuff from the stack */
730 
731  m = (methodinfo *) *((ptrint *) (sp + 2 * 8));
732  disp = *((s4 *) (sp + 1 * 8));
733  pv = (u1 *) *((ptrint *) (sp + 0 * 8));
734 
735  /* return address on SPARC is address of jump, therefore correct */
736 
737  /* resolve native function */
738 
739  if (!(f = native_resolve_function(m)))
740  return false;
741 
742  /* patch native function pointer */
743 
744  *((ptrint *) (pv + disp)) = (ptrint) f;
745 
746  /* synchronize data cache */
747 
748  md_dcacheflush(pv + disp, SIZEOF_VOID_P);
749 
750  return true;
751 }
752 
753 
754 /*
755  * These are local overrides for various environment variables in Emacs.
756  * Please do not remove this and leave it at the end of the file, where
757  * Emacs will automagically detect them.
758  * ---------------------------------------------------------------------
759  * Local variables:
760  * mode: c++
761  * indent-tabs-mode: t
762  * c-basic-offset: 4
763  * tab-width: 4
764  * End:
765  * vim:noexpandtab:sw=4:ts=4:
766  */
#define pv
Definition: md-asm.hpp:65
bool patcher_invokestatic_special(patchref_t *pr)
Definition: patcher.cpp:392
bool patcher_get_putstatic(patchref_t *pr)
Definition: patcher.cpp:264
#define ra
Definition: md-asm.hpp:62
methodinfo * methods
Definition: class.hpp:113
bool patcher_invokeinterface(patchref_t *pr)
Definition: patcher.cpp:477
#define PATCHER_CALL_SIZE
Definition: codegen.hpp:68
s4 state
Definition: class.hpp:115
#define BIAS
Definition: md-abi.hpp:107
java_object_t * patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
Definition: patcher.cpp:69
classinfo * resolve_class_eager_no_access_check(unresolved_class *ref)
Definition: resolve.cpp:1044
static void md_dcacheflush(void *addr, int nbytes)
Definition: md.hpp:163
bool patcher_clinit(u1 *sp)
Definition: patcher.cpp:671
uint8_t u1
Definition: types.hpp:40
u1 * methodptr
Definition: global.hpp:40
#define EXCEPTION_CHECK_INSTRUCTIONS
Definition: codegen.hpp:63
bool patcher_resolve_native(u1 *sp)
Definition: patcher.cpp:722
void(* functionptr)(void)
Definition: global.hpp:39
#define xpc
Definition: md-asm.hpp:51
u1 * stubroutine
Definition: method.hpp:102
s4 vftblindex
Definition: method.hpp:81
bool patcher_athrow_areturn(u1 *sp)
Definition: patcher.cpp:698
int32_t offset
Definition: field.hpp:66
classinfo * clazz
Definition: method.hpp:80
bool patcher_invokevirtual(patchref_t *pr)
Definition: patcher.cpp:433
uint64_t u8
Definition: types.hpp:49
imm_union * value
Definition: field.hpp:67
bool patcher_aconst(patchref_t *pr)
Definition: patcher.cpp:285
bool patcher_checkcast_interface(patchref_t *pr)
Definition: patcher.cpp:526
s4 flags
Definition: class.hpp:90
#define exceptions_get_and_clear_exception
Definition: md-asm.hpp:98
int32_t s4
Definition: types.hpp:45
void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, void *pv, void *sp, void *ra, void *xpc)
Definition: stacktrace.cpp:84
classinfo * clazz
Definition: field.hpp:55
s4 index
Definition: class.hpp:116
bool initialize_class(classinfo *c)
Definition: initialize.cpp:110
bool patcher_get_putfield(patchref_t *pr)
Definition: patcher.cpp:308
#define JITSTACK_CNT
Definition: md-abi.hpp:114
MIIterator e
uint32_t u4
Definition: types.hpp:46
vftbl_t * vftbl
Definition: class.hpp:121
fieldinfo * resolve_field_eager(unresolved_field *ref)
Definition: resolve.cpp:1497
#define sp
Definition: md-asm.hpp:81
bool patcher_checkcast_instanceof_class(u1 *sp)
Definition: patcher.cpp:635
bool patcher_checkcast_instanceof_flags(patchref_t *pr)
Definition: patcher.cpp:532
void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
Definition: stacktrace.cpp:204
methodinfo * resolve_method_eager(unresolved_method *ref)
Definition: resolve.cpp:2236
int16_t s2
Definition: types.hpp:42
bool patcher_builtin_arraycheckcast(patchref_t *pr)
Definition: patcher.cpp:367
classinfo * resolve_classref_eager(constant_classref *ref)
Definition: resolve.cpp:961
bool patcher_builtin_multianewarray(patchref_t *pr)
Definition: patcher.cpp:328
uintptr_t ptrint
Definition: types.hpp:54
static void md_icacheflush(void *addr, int nbytes)
Definition: md.hpp:151
#define OFFSET(s, el)
Definition: memory.hpp:90
#define printf(...)
Definition: ssa2.cpp:40
bool patcher_instanceof_interface(patchref_t *pr)
Definition: patcher.cpp:572