ce1e45d0831acfc3df163d58cad31f482452c298
[cacao.git] / src / vm / jit / sparc64 / patcher.c
1 /* src/vm/jit/mips/patcher.c - SPARC code patching functions
2
3    Copyright (C) 1996-2005, 2006 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    $Id: patcher.c 5164 2006-07-19 15:54:01Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <stdint.h>
34
35 #include "vm/types.h"
36
37 #include "mm/memory.h"
38
39 #include "vm/jit/sparc64/md-abi.h"
40 #include "vm/jit/sparc64/codegen.h"
41
42 #include "native/native.h"
43 #include "vm/builtin.h"
44 #include "vm/exceptions.h"
45 #include "vm/initialize.h"
46
47 #include "vm/jit/asmpart.h"
48 #include "vm/jit/patcher.h"
49 #include "vm/jit/md.h"
50 #include "vm/jit/methodheader.h"
51 #include "vm/jit/stacktrace.h"
52
53 #include "vmcore/class.h"
54 #include "vmcore/field.h"
55 #include "vmcore/options.h"
56 #include "vmcore/references.h"
57 #include "vm/resolve.h"
58
59 #include "vm/jit/sparc64/solaris/macro_rename.h"
60
61 /* patcher_wrapper *************************************************************
62
63    Wrapper for all patchers.  It also creates the stackframe info
64    structure.
65
66    If the return value of the patcher function is false, it gets the
67    exception object, clears the exception pointer and returns the
68    exception.
69
70 *******************************************************************************/
71
72 java_object_t *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
73 {
74         stackframeinfo     sfi;
75         u1                *xpc;
76         u1                *javasp;
77         java_object_t *o;
78 #if SIZEOF_VOID_P == 8
79         u8                mcode;
80 #else
81         u4                mcode[2];
82 #endif
83         functionptr        f;
84         bool               result;
85         java_handle_t *e;
86         
87         /* define the patcher function */
88
89         bool (*patcher_function)(u1 *);
90
91         assert(pv != NULL);
92
93         /* get stuff from the stack */
94
95         xpc = (u1 *)                *((ptrint *) (sp + 5 * 8));
96         o   = (java_object_t *) *((ptrint *) (sp + 4 * 8));
97         f   = (functionptr)         *((ptrint *) (sp + 0 * 8));
98
99         /* store PV into the patcher function position */
100
101         *((ptrint *) (sp + 0 * 8)) = (ptrint) pv;
102
103         /* cast the passed function to a patcher function */
104
105         patcher_function = (bool (*)(u1 *)) (ptrint) f;
106
107         /* enter a monitor on the patching position */
108
109         PATCHER_MONITORENTER;
110         
111         /* the (data) sp points directly to the patcher fields */
112         /* calculate the real sp of the current java function considering the WINSAVE regs */
113         
114         javasp = sp - JITSTACK_CNT * 8 - BIAS;
115
116         /* create the stackframeinfo */
117
118         stacktrace_create_extern_stackframeinfo(&sfi, pv, javasp, ra, xpc);
119
120         /* call the proper patcher function */
121
122         result = (patcher_function)(sp);
123
124         /* remove the stackframeinfo */
125
126         stacktrace_remove_stackframeinfo(&sfi);
127
128         /* check for return value and exit accordingly */
129
130         if (result == false) {
131                 e = exceptions_get_and_clear_exception();
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
156         md_icacheflush(xpc, PATCHER_CALL_SIZE);
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
174 bool patcher_get_putstatic(u1 *sp)
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->class->state & CLASS_INITIALIZED))
195                 if (!initialize_class(fi->class))
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
219 bool patcher_get_putfield(u1 *sp)
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         /* if we show disassembly, we have to skip the nop's */
235
236         if (opt_shownops) {
237                 /* patch the field's offset into the instruction */
238
239                 *((u4 *) (ra + 2 * 4)) |= (s2) (fi->offset & 0x00001fff);
240
241                 /* synchronize instruction cache */
242
243                 md_icacheflush(ra + 2 * 4, 1 * 4);
244         }
245         else {
246                 /* otherwise store the patched instruction on the stack */
247
248                 *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x00001fff);
249         }
250
251         return true;
252 }
253
254
255 /* patcher_aconst **************************************************************
256
257    Machine code:
258
259    <patched call postition>
260    xxx         ld       a0,-104(pv)
261
262 *******************************************************************************/
263
264 bool patcher_aconst(u1 *sp)
265 {
266         constant_classref *cr;
267         s4                 disp;
268         u1                *pv;
269         classinfo         *c;
270
271         /* get stuff from the stack */
272
273         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
274         disp     =                       *((s4 *)     (sp + 1 * 8));
275         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
276
277         /* get the classinfo */
278
279         if (!(c = resolve_classref_eager(cr)))
280                 return false;
281
282         /* patch the classinfo pointer */
283
284         *((ptrint *) (pv + disp)) = (ptrint) c;
285
286         /* synchronize data cache */
287
288         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
289
290         return true;
291 }
292
293
294 /* patcher_builtin_multianewarray **********************************************
295
296    Machine code:
297
298    <patched call position>
299    dfc5ff90    ld       a1,-112(s8)
300    03a03025    move     a2,sp
301    dfd9ff88    ld       t9,-120(s8)
302    0320f809    jalr     t9
303    00000000    nop
304
305 *******************************************************************************/
306
307 bool patcher_builtin_multianewarray(u1 *sp)
308 {
309         constant_classref *cr;
310         s4                 disp;
311         u1                *pv;
312         classinfo         *c;
313
314         /* get stuff from the stack */
315
316         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
317         disp     =                       *((s4 *)     (sp + 1 * 8));
318         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
319
320         /* get the classinfo */
321
322         if (!(c = resolve_classref_eager(cr)))
323                 return false;
324
325         /* patch the classinfo pointer */
326
327         *((ptrint *) (pv + disp)) = (ptrint) c;
328
329         /* synchronize data cache */
330
331         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
332
333         return true;
334 }
335
336
337 /* patcher_builtin_arraycheckcast **********************************************
338
339    Machine code:
340
341    <patched call position>
342    dfc5ffc0    ld       a1,-64(s8)
343    dfd9ffb8    ld       t9,-72(s8)
344    0320f809    jalr     t9
345    00000000    nop
346
347 *******************************************************************************/
348
349 bool patcher_builtin_arraycheckcast(u1 *sp)
350 {
351         constant_classref *cr;
352         s4                 disp;
353         u1                *pv;
354         classinfo         *c;
355
356         /* get stuff from the stack */
357
358         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
359         disp     =                       *((s4 *)     (sp + 1 * 8));
360         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
361
362         /* get the classinfo */
363
364         if (!(c = resolve_classref_eager(cr)))
365                 return false;
366
367         /* patch the classinfo pointer */
368
369         *((ptrint *) (pv + disp)) = (ptrint) c;
370
371         /* synchronize data cache */
372
373         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
374
375         return true;
376 }
377
378
379 /* patcher_invokestatic_special ************************************************
380
381    Machine code:
382
383    <patched call position>
384    dfdeffc0    ld       s8,-64(s8)
385    03c0f809    jalr     s8
386    00000000    nop
387
388 ******************************************************************************/
389
390 bool patcher_invokestatic_special(u1 *sp)
391 {
392         unresolved_method *um;
393         s4                 disp;
394         u1                *pv;
395         methodinfo        *m;
396
397         /* get stuff from the stack */
398
399         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
400         disp     =                       *((s4 *)     (sp + 1 * 8));
401         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
402
403         /* get the fieldinfo */
404
405         if (!(m = resolve_method_eager(um)))
406                 return false;
407
408         /* patch stubroutine */
409
410         *((ptrint *) (pv + disp)) = (ptrint) m->stubroutine;
411
412         /* synchronize data cache */
413
414         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
415
416         return true;
417 }
418
419
420 /* patcher_invokevirtual *******************************************************
421
422    Machine code:
423
424    <patched call position>
425    xxx         ldx      g2,0(o0)
426    xxx         ldx      o5,64(g2)
427    xxx         jmpl     o5
428    xxx         nop
429
430 *******************************************************************************/
431
432 bool patcher_invokevirtual(u1 *sp)
433 {
434         u1                *ra;
435         unresolved_method *um;
436         methodinfo        *m;
437
438         /* get stuff from the stack */
439
440         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
441         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
442
443         /* get the fieldinfo */
444
445         if (!(m = resolve_method_eager(um)))
446                 return false;
447
448         /* if we show disassembly, we have to skip the nop's */
449
450         if (opt_shownops) {
451                 ra = ra + PATCHER_CALL_SIZE;
452
453                 /* patch vftbl index */
454
455                 *((s4 *) (ra + 1 * 4)) |=
456                         (s4) ((OFFSET(vftbl_t, table[0]) +
457                                    sizeof(methodptr) * m->vftblindex) & 0x00001fff);
458
459                 /* synchronize instruction cache */
460
461                 md_icacheflush(ra + 1 * 4, 1 * 4);
462         }
463         else {
464                 /* patch vftbl index */
465
466                 *((s4 *) (sp + 3 * 8 + 4)) |=
467                         (s4) ((OFFSET(vftbl_t, table[0]) +
468                                    sizeof(methodptr) * m->vftblindex) & 0x00001fff);
469         }
470
471         return true;
472 }
473
474
475 /* patcher_invokeinterface *****************************************************
476
477    Machine code:
478
479    <patched call position>
480    dc990000    ld       t9,0(a0)
481    df39ffa0    ld       t9,-96(t9)
482    df3e0018    ld       s8,24(t9)
483    03c0f809    jalr     s8
484    00000000    nop
485
486 *******************************************************************************/
487
488 bool patcher_invokeinterface(u1 *sp)
489 {
490         u1                *ra;
491         unresolved_method *um;
492         methodinfo        *m;
493
494         /* get stuff from the stack */
495
496         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
497         um       = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
498
499         /* get the fieldinfo */
500
501         if (!(m = resolve_method_eager(um)))
502                 return false;
503
504         /* if we show disassembly, we have to skip the nop's */
505
506         if (opt_shownops) {
507                 ra = ra + PATCHER_CALL_SIZE;
508
509                 /* patch interfacetable index */
510
511                 *((s4 *) (ra + 1 * 4)) |= 
512                         (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
513                                 sizeof(methodptr*) * m->class->index) & 0x00001fff);
514
515                 /* patch method offset */
516
517                 *((s4 *) (ra + 2 * 4)) |=
518                         (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
519
520                 /* synchronize instruction cache */
521
522                 md_icacheflush(ra + 1 * 4, 2 * 4);
523         }
524 else {
525                 /* patch interfacetable index */
526
527                 *((s4 *) (sp + 3 * 8 + 4)) |=
528                         (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
529                                 sizeof(methodptr*) * m->class->index) & 0x00001fff);
530
531                 /* patch method offset */
532
533                 *((s4 *) (ra + 2 * 4)) |=
534                         (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
535
536                 /* synchronize instruction cache */
537
538                 md_icacheflush(ra + 2 * 4, 1 * 4);
539         }
540
541         return true;
542 }
543
544
545 /* patcher_checkcast_instanceof_flags ******************************************
546
547    Machine code:
548
549    <patched call position>
550    8fc3ff24    lw       v1,-220(s8)
551    30630200    andi     v1,v1,512
552    1060000d    beq      v1,zero,0x000000001051824c
553    00000000    nop
554
555 *******************************************************************************/
556
557 bool patcher_checkcast_instanceof_flags(u1 *sp)
558 {
559         constant_classref *cr;
560         s4                 disp;
561         u1                *pv;
562         classinfo         *c;
563
564         /* get stuff from the stack */
565
566         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
567         disp     =                       *((s4 *)     (sp + 1 * 8));
568         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
569
570         /* get the fieldinfo */
571
572         if (!(c = resolve_classref_eager(cr)))
573                 return false;
574
575         /* patch class flags */
576
577         *((s4 *) (pv + disp)) = (s4) c->flags;
578
579         /* synchronize data cache */
580
581         md_dcacheflush(pv + disp, sizeof(s4));
582
583         return true;
584 }
585
586
587 /* patcher_checkcast_interface **************************************
588
589    Machine code:
590
591    <patched call position>
592    dd030000    ld       v1,0(a4)
593    8c79001c    lw       t9,28(v1)
594    27390000    addiu    t9,t9,0
595    1b200082    blez     t9,zero,0x000000001051843c
596    00000000    nop
597    dc790000    ld       t9,0(v1)
598
599 *******************************************************************************/
600
601 bool patcher_checkcast_interface(u1 *sp)
602 {
603         u1                *ra;
604         constant_classref *cr;
605         classinfo         *c;
606
607         /* get stuff from the stack */
608
609         ra       = (u1 *)                *((ptrint *) (sp + 5 * 8));
610         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
611
612         /* get the fieldinfo */
613
614         if (!(c = resolve_classref_eager(cr)))
615                 return false;
616
617         /* if we show disassembly, we have to skip the nop's */
618
619         if (opt_shownops)
620                 ra = ra + PATCHER_CALL_SIZE;
621
622         /* patch super class index */
623
624         *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x00001fff);
625
626         *((s4 *) (ra + (3 + EXCEPTION_CHECK_INSTRUCTIONS) * 4)) |= 
627                 (s4) ((OFFSET(vftbl_t, interfacetable[0])
628                 - c->index * sizeof(methodptr*)) & 0x00001fff);
629
630         /* synchronize instruction cache */
631
632         if (opt_shownops)
633                 md_icacheflush(ra - 2 * 4, (6 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
634         else
635                 md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
636
637         return true;
638 }
639
640 /* patcher_instanceof_interface ************************************************
641
642    Machine code:
643
644    <patched call position>
645    dd030000    ld       v1,0(a4)
646    8c79001c    lw       t9,28(v1)
647    27390000    addiu    t9,t9,0
648    1b200082    blez     t9,zero,0x000000001051843c
649    00000000    nop
650    dc790000    ld       t9,0(v1)
651
652 *******************************************************************************/
653
654 bool patcher_instanceof_interface(u1 *sp)
655 {
656         u1                *ra;
657         constant_classref *cr;
658         classinfo         *c;
659
660         /* get stuff from the stack */
661
662         ra = (u1 *)                *((ptrint *) (sp + 5 * 8));
663         cr = (constant_classref *) *((ptrint *) (sp + 2 * 8));
664
665         /* get the fieldinfo */
666
667         if (!(c = resolve_classref_eager(cr)))
668                 return false;
669
670         /* if we show disassembly, we have to skip the nop's */
671
672         if (opt_shownops)
673                 ra = ra + PATCHER_CALL_SIZE;
674
675         /* patch super class index */
676
677         *((s4 *) (ra + 2 * 4)) |= (s4) ((c->index) & 0x00001fff);
678         *((s4 *) (ra + 5 * 4)) |=
679                 (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
680                                  c->index * sizeof(methodptr*)) & 0x00001fff);
681
682         /* synchronize instruction cache */
683
684         if (opt_shownops)
685                 md_icacheflush(ra - PATCHER_CALL_SIZE * 4, 8 * 4);
686         else
687                 md_icacheflush(ra, 6 * 4);
688
689         return true;
690 }
691
692
693 /* patcher_checkcast_instanceof_class ******************************************
694
695    Machine code:
696
697    <patched call position>
698    dd030000    ld       v1,0(a4)
699    dfd9ff18    ld       t9,-232(s8)
700
701 *******************************************************************************/
702
703 bool patcher_checkcast_instanceof_class(u1 *sp)
704 {
705         constant_classref *cr;
706         s4                 disp;
707         u1                *pv;
708         classinfo         *c;
709
710         /* get stuff from the stack */
711
712         cr       = (constant_classref *) *((ptrint *) (sp + 2 * 8));
713         disp     =                       *((s4 *)     (sp + 1 * 8));
714         pv       = (u1 *)                *((ptrint *) (sp + 0 * 8));
715
716         /* get the fieldinfo */
717
718         if (!(c = resolve_classref_eager(cr)))
719                 return false;
720
721         /* patch super class' vftbl */
722
723         *((ptrint *) (pv + disp)) = (ptrint) c->vftbl;
724
725         /* synchronize data cache */
726
727         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
728
729         return true;
730 }
731
732
733 /* patcher_clinit **************************************************************
734
735    No special machine code.
736
737 *******************************************************************************/
738
739 bool patcher_clinit(u1 *sp)
740 {
741         classinfo *c;
742
743         /* get stuff from the stack */
744
745         c        = (classinfo *) *((ptrint *) (sp + 2 * 8));
746
747         /* check if the class is initialized */
748
749         if (!(c->state & CLASS_INITIALIZED))
750                 if (!initialize_class(c))
751                         return false;
752
753         return true;
754 }
755
756
757 /* patcher_athrow_areturn ******************************************************
758
759    Machine code:
760
761    <patched call position>
762
763 *******************************************************************************/
764
765 #ifdef ENABLE_VERIFIER
766 bool patcher_athrow_areturn(u1 *sp)
767 {
768         unresolved_class *uc;
769
770         /* get stuff from the stack */
771
772         uc       = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
773
774         /* resolve the class and check subtype constraints */
775
776         if (!resolve_class_eager_no_access_check(uc))
777                 return false;
778
779         return true;
780 }
781 #endif /* ENABLE_VERIFIER */
782
783
784 /* patcher_resolve_native ******************************************************
785
786    XXX
787
788 *******************************************************************************/
789
790 #if !defined(WITH_STATIC_CLASSPATH)
791 bool patcher_resolve_native(u1 *sp)
792 {
793         methodinfo  *m;
794         s4           disp;
795         u1          *pv;
796         functionptr  f;
797
798         /* get stuff from the stack */
799
800         m        = (methodinfo *) *((ptrint *) (sp + 2 * 8));
801         disp     =                *((s4 *)     (sp + 1 * 8));
802         pv       = (u1 *)         *((ptrint *) (sp + 0 * 8));
803
804         /* return address on SPARC is address of jump, therefore correct */
805
806         /* resolve native function */
807
808         if (!(f = native_resolve_function(m)))
809                 return false;
810
811         /* patch native function pointer */
812
813         *((ptrint *) (pv + disp)) = (ptrint) f;
814
815         /* synchronize data cache */
816
817         md_dcacheflush(pv + disp, SIZEOF_VOID_P);
818
819         return true;
820 }
821 #endif /* !defined(WITH_STATIC_CLASSPATH) */
822
823
824 /*
825  * These are local overrides for various environment variables in Emacs.
826  * Please do not remove this and leave it at the end of the file, where
827  * Emacs will automagically detect them.
828  * ---------------------------------------------------------------------
829  * Local variables:
830  * mode: c
831  * indent-tabs-mode: t
832  * c-basic-offset: 4
833  * tab-width: 4
834  * End:
835  * vim:noexpandtab:sw=4:ts=4:
836  */