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