Merged trunk and subtype.
[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, 2008
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 <assert.h>
29 #include <stdint.h>
30
31 #include "vm/types.h"
32
33 #include "mm/memory.h"
34
35 #include "vm/jit/sparc64/codegen.h"
36 #include "vm/jit/sparc64/md.h"
37 #include "vm/jit/sparc64/md-abi.h"
38
39 #include "native/native.h"
40
41 #include "vm/jit/builtin.hpp"
42 #include "vm/class.h"
43 #include "vm/exceptions.hpp"
44 #include "vm/field.hpp"
45 #include "vm/initialize.h"
46 #include "vm/options.h"
47 #include "vm/references.h"
48 #include "vm/resolve.h"
49
50 #include "vm/jit/asmpart.h"
51 #include "vm/jit/patcher.h"
52 #include "vm/jit/methodheader.h"
53 #include "vm/jit/stacktrace.hpp"
54
55 #include "vm/jit/sparc64/solaris/macro_rename.h"
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
69 java_object_t *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
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;
82         java_handle_t *e;
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
125         stacktrace_stackframeinfo_remove(&sfi);
126         printf("patcher closing sfi for xpc=%p\n", xpc);
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->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
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         /* 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
251 bool patcher_aconst(u1 *sp)
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
294 bool patcher_builtin_multianewarray(u1 *sp)
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
336 bool patcher_builtin_arraycheckcast(u1 *sp)
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
377 bool patcher_invokestatic_special(u1 *sp)
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
419 bool patcher_invokevirtual(u1 *sp)
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
458 bool patcher_invokeinterface(u1 *sp)
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
505 bool patcher_checkcast_instanceof_flags(u1 *sp)
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
549 bool patcher_checkcast_interface(u1 *sp)
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
575         md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
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
594 bool patcher_instanceof_interface(u1 *sp)
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
635 bool patcher_checkcast_instanceof_class(u1 *sp)
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
671 bool patcher_clinit(u1 *sp)
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
698 bool patcher_athrow_areturn(u1 *sp)
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
708         if (!resolve_class_eager_no_access_check(uc))
709                 return false;
710
711         return true;
712 }
713 #endif /* ENABLE_VERIFIER */
714
715
716 /* patcher_resolve_native ******************************************************
717
718    XXX
719
720 *******************************************************************************/
721
722 bool patcher_resolve_native(u1 *sp)
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  */