1b599291f49ce6b6891ebe92c6be31853a79b5f4
[cacao.git] / src / vm / jit / x86_64 / patcher.c
1 /* src/vm/jit/x86_64/patcher.c - x86_64 code patching functions
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christian Thalinger
28
29    Changes:
30
31    $Id: patcher.c 2360 2005-04-24 13:07:57Z jowenn $
32
33 */
34
35
36 #include "vm/jit/x86_64/types.h"
37 #include "vm/builtin.h"
38 #include "vm/field.h"
39 #include "vm/initialize.h"
40 #include "vm/references.h"
41 #include "vm/jit/helper.h"
42 #include "vm/exceptions.h"
43
44 /* patcher_get_putstatic *******************************************************
45
46    XXX
47
48    Machine code:
49
50    4d 8b 15 86 fe ff ff             mov    -378(%rip),%r10
51
52 *******************************************************************************/
53
54 bool patcher_get_putstatic(u1 *sp)
55 {
56         u1               *ra;
57         u8                mcode;
58         unresolved_field *uf;
59         fieldinfo        *fi;
60         ptrint           *dataaddress;
61         s4                ripoffset;
62         void             *beginJavaStack;
63         /* get stuff from the stack */
64
65         ra    = (u1 *)               *((ptrint *) (sp + 2 * 8));
66         mcode =                      *((u8 *)     (sp + 1 * 8));
67         uf    = (unresolved_field *) *((ptrint *) (sp + 0 * 8));
68         beginJavaStack=              (void*)(sp+2*8);
69         /* calculate and set the new return address */
70
71         ra = ra - 5;
72         *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
73
74         *dontfillinexceptionstacktrace=true;
75         /* get the fieldinfo */
76         if (!(fi = helper_resolve_fieldinfo(uf)))
77         {
78                 *dontfillinexceptionstacktrace=false;
79                 return false;
80         }
81
82         /* check if the field's class is initialized */
83         *dontfillinexceptionstacktrace=false;
84         if (!fi->class->initialized) {
85                 bool init;
86                 {
87                         /*struct native_stackframeinfo {
88                                 void *oldThreadspecificHeadValue;
89                                 void **addressOfThreadspecificHead;
90                                 methodinfo *method;
91                                 void *beginOfJavaStackframe; only used if != 0
92                                 void *returnToFromNative;
93                         }*/
94                         /* more or less the same as the above sfi setup is done in the assembler code by the prepare/remove functions*/
95                         native_stackframeinfo sfi;
96                         sfi.returnToFromNative=(void*)ra;
97                         sfi.beginOfJavaStackframe=beginJavaStack;
98                         sfi.method=0; /*internal*/
99                         sfi.addressOfThreadspecificHead=builtin_asm_get_stackframeinfo();
100                         sfi.oldThreadspecificHeadValue=*(sfi.addressOfThreadspecificHead);
101                         *(sfi.addressOfThreadspecificHead)=&sfi;
102
103                         init=initialize_class(fi->class);
104
105                         *(sfi.addressOfThreadspecificHead)=sfi.oldThreadspecificHeadValue;
106                 }
107                 if (!init)
108                 {
109                         return false;
110                 }
111         }
112
113         *dontfillinexceptionstacktrace=false;
114
115         /* patch back original code */
116
117         *((u8 *) ra) = mcode;
118
119         /* get RIP offset from machine instruction */
120
121         ripoffset = *((u4 *) (ra + 3));
122
123         /* calculate address in data segment (+ 7: is the size of the RIP move) */
124
125         dataaddress = (ptrint *) (ra + ripoffset + 7);
126
127         /* patch the field value's address */
128
129         *dataaddress = (ptrint) &(fi->value);
130
131         return true;
132 }
133
134
135 /* patcher_get_putfield ********************************************************
136
137    XXX
138
139    Machine code:
140
141    45 8b 8f 00 00 00 00             mov    0x0(%r15),%r9d
142
143 *******************************************************************************/
144
145 bool patcher_get_putfield(u1 *sp)
146 {
147         u1               *ra;
148         u8                mcode;
149         unresolved_field *uf;
150         fieldinfo        *fi;
151
152         /* get stuff from the stack */
153
154         ra    = (u1 *)               *((ptrint *) (sp + 2 * 8));
155         mcode =                      *((u8 *)     (sp + 1 * 8));
156         uf    = (unresolved_field *) *((ptrint *) (sp + 0 * 8));
157
158         /* calculate and set the new return address */
159
160         ra = ra - 5;
161         *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
162
163         *dontfillinexceptionstacktrace=true;
164
165
166         /* get the fieldinfo */
167
168         if (!(fi = helper_resolve_fieldinfo(uf)))
169         {
170                 *dontfillinexceptionstacktrace=false;
171                 return false;
172         }
173
174         /* patch back original code */
175
176         *((u8 *) ra) = mcode;
177
178         /* patch the field's offset: we check for the field type, because the     */
179         /* instructions have different lengths                                    */
180
181         if (IS_FLT_DBL_TYPE(fi->type)) {
182                 *((u4 *) (ra + 5)) = (u4) (fi->offset);
183
184         } else {
185                 u1 byte;
186
187                 /* check for special case: %rsp or %r12 as base register */
188
189                 byte = *(ra + 3);
190
191                 if (byte == 0x24)
192                         *((u4 *) (ra + 4)) = (u4) (fi->offset);
193                 else
194                         *((u4 *) (ra + 3)) = (u4) (fi->offset);
195         }
196
197         *dontfillinexceptionstacktrace=false;
198         return true;
199 }
200
201
202 /* patcher_builtin_new *********************************************************
203
204    XXX
205
206    Machine code:
207
208 *******************************************************************************/
209
210 bool patcher_builtin_new(constant_classref *cr, u1 *sp)
211 {
212         u1                *ra;
213         classinfo         *c;
214
215         /* get stuff from the stack */
216
217         ra = (u1 *)                *((ptrint *) (sp + 0 * 8));
218
219         /* calculate and set the new return address */
220
221         ra = ra - (10 + 10 + 3);
222         *((ptrint *) (sp + 0 * 8)) = (ptrint) ra;
223
224         *dontfillinexceptionstacktrace=true;
225
226         /* get the classinfo */
227
228         if (!(c = helper_resolve_classinfo(cr)))
229         {
230                 *dontfillinexceptionstacktrace=false;
231                 return false;
232         }
233
234         /* patch the classinfo pointer */
235
236         *((ptrint *) (ra + 2)) = (ptrint) c;
237
238         /* patch new function address */
239
240         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_new;
241
242         *dontfillinexceptionstacktrace=false;
243         return true;
244 }
245
246
247 /* patcher_builtin_newarray ****************************************************
248
249    XXX
250
251    Machine code:
252
253 *******************************************************************************/
254
255 bool patcher_builtin_newarray(u1 *sp, constant_classref *cr)
256 {
257         u1                *ra;
258         classinfo         *c;
259
260         /* get stuff from the stack */
261
262         ra = (u1 *) *((ptrint *) (sp + 0 * 8));
263
264         /* calculate and set the new return address */
265
266         ra = ra - (10 + 10 + 3);
267         *((ptrint *) (sp + 0 * 8)) = (ptrint) ra;
268
269
270         *dontfillinexceptionstacktrace=true;
271
272
273         /* get the classinfo */
274
275         if (!(c = helper_resolve_classinfo(cr)))
276         {
277                 *dontfillinexceptionstacktrace=false;
278                 return false;
279         }
280         /* patch the class' vftbl pointer */
281
282         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
283
284         /* patch new function address */
285
286         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_newarray;
287
288         *dontfillinexceptionstacktrace=false;
289         return true;
290 }
291
292
293 /* patcher_builtin_multianewarray **********************************************
294
295    XXX
296
297    Machine code:
298
299 *******************************************************************************/
300
301 bool patcher_builtin_multianewarray(u1 *sp, constant_classref *cr)
302 {
303         u1                *ra;
304         classinfo         *c;
305
306         /* get stuff from the stack */
307
308         ra = (u1 *) *((ptrint *) (sp + 0 * 8));
309
310         /* calculate and set the new return address */
311
312         ra = ra - (10 + 10 + 3 + 10 + 3);
313         *((ptrint *) (sp + 0 * 8)) = (ptrint) ra;
314
315         *dontfillinexceptionstacktrace=true;
316
317         /* get the classinfo */
318
319         if (!(c = helper_resolve_classinfo(cr))) {
320                 *dontfillinexceptionstacktrace=false;
321                 return false;
322         }
323         /* patch the class' vftbl pointer */
324
325         *((ptrint *) (ra + 10 + 2)) = (ptrint) c->vftbl;
326
327         /* patch new function address */
328
329         *((ptrint *) (ra + 10 + 10 + 3 + 2)) = (ptrint) BUILTIN_multianewarray;
330
331         *dontfillinexceptionstacktrace=false;
332         return true;
333 }
334
335
336 /* patcher_builtin_checkarraycast **********************************************
337
338    XXX
339
340    Machine code:
341
342 *******************************************************************************/
343
344 bool patcher_builtin_checkarraycast(u1 *sp, constant_classref *cr)
345 {
346         u1                *ra;
347         classinfo         *c;
348
349         /* get stuff from the stack */
350
351         ra = (u1 *) *((ptrint *) (sp + 0 * 8));
352
353         /* calculate and set the new return address */
354
355         ra = ra - (10 + 10 + 3);
356         *((ptrint *) (sp + 0 * 8)) = (ptrint) ra;
357
358         *dontfillinexceptionstacktrace=true;
359
360         /* get the classinfo */
361
362         if (!(c = helper_resolve_classinfo(cr)))
363         {
364                 *dontfillinexceptionstacktrace=false;
365                 return false;
366         }
367
368         /* patch the class' vftbl pointer */
369
370         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
371
372         /* patch new function address */
373
374         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_checkarraycast;
375
376         *dontfillinexceptionstacktrace=false;
377         return true;
378 }
379
380
381 /* patcher_builtin_arrayinstanceof *********************************************
382
383    XXX
384
385    Machine code:
386
387 *******************************************************************************/
388
389 bool patcher_builtin_arrayinstanceof(u1 *sp, constant_classref *cr)
390 {
391         u1                *ra;
392         classinfo         *c;
393
394         /* get stuff from the stack */
395
396         ra = (u1 *) *((ptrint *) (sp + 0 * 8));
397
398         /* calculate and set the new return address */
399
400         ra = ra - (10 + 10 + 3);
401         *((ptrint *) (sp + 0 * 8)) = (ptrint) ra;
402
403
404         *dontfillinexceptionstacktrace=true;
405
406
407         /* get the classinfo */
408
409         if (!(c = helper_resolve_classinfo(cr)))
410         {
411                 *dontfillinexceptionstacktrace=false;
412                 return false;
413         }
414
415         /* patch the class' vftbl pointer */
416
417         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
418
419         /* patch new function address */
420
421         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_arrayinstanceof;
422
423         *dontfillinexceptionstacktrace=false;
424         return true;
425 }
426
427
428 /* patcher_invokestatic_special ************************************************
429
430    XXX
431
432 *******************************************************************************/
433
434 bool patcher_invokestatic_special(u1 *sp)
435 {
436         u1                *ra;
437         u8                 mcode;
438         unresolved_method *um;
439         methodinfo        *m;
440
441         /* get stuff from the stack */
442
443         ra    = (u1 *)                *((ptrint *) (sp + 2 * 8));
444         mcode =                       *((u8 *)     (sp + 1 * 8));
445         um    = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
446
447         /* calculate and set the new return address */
448
449         ra = ra - 5;
450         *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
451
452         *dontfillinexceptionstacktrace=true;
453
454
455         /* get the fieldinfo */
456
457         if (!(m = helper_resolve_methodinfo(um)))
458         {
459                 *dontfillinexceptionstacktrace=false;
460                 return false;
461         }
462         /* patch back original code */
463
464         *((u8 *) ra) = mcode;
465
466         /* patch stubroutine */
467
468         *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine;
469
470         *dontfillinexceptionstacktrace=false;
471         return true;
472 }
473
474
475 /* patcher_invokevirtual *******************************************************
476
477    XXX
478
479 *******************************************************************************/
480
481 bool patcher_invokevirtual(u1 *sp)
482 {
483         u1                *ra;
484         u8                 mcode;
485         unresolved_method *um;
486         methodinfo        *m;
487
488         /* get stuff from the stack */
489
490         ra    = (u1 *)                *((ptrint *) (sp + 2 * 8));
491         mcode =                       *((u8 *)     (sp + 1 * 8));
492         um    = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
493
494         /* calculate and set the new return address */
495
496         ra = ra - 5;
497         *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
498
499         *dontfillinexceptionstacktrace=true;
500
501         /* get the fieldinfo */
502
503         if (!(m = helper_resolve_methodinfo(um)))
504         {
505                 *dontfillinexceptionstacktrace=false;
506                 return false;
507         }
508
509         /* patch back original code */
510
511         *((u8 *) ra) = mcode;
512
513         /* patch vftbl index */
514
515         *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
516                                                                    sizeof(methodptr) * m->vftblindex);
517
518         *dontfillinexceptionstacktrace=false;
519         return true;
520 }
521
522
523 /* patcher_invokeinterface *****************************************************
524
525    XXX
526
527 *******************************************************************************/
528
529 bool patcher_invokeinterface(u1 *sp)
530 {
531         u1                *ra;
532         u8                 mcode;
533         unresolved_method *um;
534         methodinfo        *m;
535
536         /* get stuff from the stack */
537
538         ra    = (u1 *)                *((ptrint *) (sp + 2 * 8));
539         mcode =                       *((u8 *)     (sp + 1 * 8));
540         um    = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
541
542         /* calculate and set the new return address */
543
544         ra = ra - 5;
545         *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
546
547         *dontfillinexceptionstacktrace=true;
548
549         /* get the fieldinfo */
550
551         if (!(m = helper_resolve_methodinfo(um)))
552         {
553                 *dontfillinexceptionstacktrace=false;
554                 return false;
555         }
556
557         /* patch back original code */
558
559         *((u8 *) ra) = mcode;
560
561         /* patch interfacetable index */
562
563         *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
564                                                                    sizeof(methodptr) * m->class->index);
565
566         /* patch method offset */
567
568         *((s4 *) (ra + 3 + 7 + 3)) =
569                 (s4) (sizeof(methodptr) * (m - m->class->methods));
570
571         *dontfillinexceptionstacktrace=false;
572         return true;
573 }
574
575
576 /* patcher_checkcast_instanceof_flags ******************************************
577
578    XXX
579
580 *******************************************************************************/
581
582 bool patcher_checkcast_instanceof_flags(u1 *sp)
583 {
584         u1                *ra;
585         u8                 mcode;
586         constant_classref *cr;
587         classinfo         *c;
588
589         /* get stuff from the stack */
590
591         ra    = (u1 *)                *((ptrint *) (sp + 2 * 8));
592         mcode =                       *((u8 *)     (sp + 1 * 8));
593         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
594
595         /* calculate and set the new return address */
596
597         ra = ra - 5;
598         *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
599
600         *dontfillinexceptionstacktrace=true;
601
602         /* get the fieldinfo */
603
604         if (!(c = helper_resolve_classinfo(cr)))
605         {
606                 *dontfillinexceptionstacktrace=false;
607                 return false;
608         }
609         /* patch back original code */
610
611         *((u8 *) ra) = mcode;
612
613         /* patch class flags */
614
615         *((s4 *) (ra + 2)) = (s4) c->flags;
616
617         *dontfillinexceptionstacktrace=false;
618         return true;
619 }
620
621
622 /* patcher_checkcast_instanceof_interface **************************************
623
624    XXX
625
626 *******************************************************************************/
627
628 bool patcher_checkcast_instanceof_interface(u1 *sp)
629 {
630         u1                *ra;
631         u8                 mcode;
632         constant_classref *cr;
633         classinfo         *c;
634
635         /* get stuff from the stack */
636
637         ra    = (u1 *)                *((ptrint *) (sp + 2 * 8));
638         mcode =                       *((u8 *)     (sp + 1 * 8));
639         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
640
641         /* calculate and set the new return address */
642
643         ra = ra - 5;
644         *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
645
646
647         *dontfillinexceptionstacktrace=true;
648
649         /* get the fieldinfo */
650
651         if (!(c = helper_resolve_classinfo(cr)))
652         {
653                 *dontfillinexceptionstacktrace=false;
654                 return false;
655         }
656
657         /* patch back original code */
658
659         *((u8 *) ra) = mcode;
660
661         /* patch super class index */
662
663         *((s4 *) (ra + 7 + 3)) = (s4) c->index;
664
665         *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
666                 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
667                           c->index * sizeof(methodptr*));
668
669         *dontfillinexceptionstacktrace=false;
670         return true;
671 }
672
673
674 /* patcher_checkcast_class *****************************************************
675
676    XXX
677
678 *******************************************************************************/
679
680 bool patcher_checkcast_class(u1 *sp)
681 {
682         u1                *ra;
683         u8                 mcode;
684         constant_classref *cr;
685         classinfo         *c;
686
687         /* get stuff from the stack */
688
689         ra    = (u1 *)                *((ptrint *) (sp + 2 * 8));
690         mcode =                       *((u8 *)     (sp + 1 * 8));
691         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
692
693         /* calculate and set the new return address */
694
695         ra = ra - 5;
696         *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
697
698         *dontfillinexceptionstacktrace=true;
699
700         /* get the fieldinfo */
701
702         if (!(c = helper_resolve_classinfo(cr)))
703         {
704                 *dontfillinexceptionstacktrace=false;
705                 return false;
706         }
707
708         /* patch back original code */
709
710         *((u8 *) ra) = mcode;
711
712         /* patch super class' vftbl */
713
714         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
715         *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
716
717         *dontfillinexceptionstacktrace=false;
718         return true;
719 }
720
721
722 /* patcher_instanceof_class ****************************************************
723
724    XXX
725
726 *******************************************************************************/
727
728 bool patcher_instanceof_class(u1 *sp)
729 {
730         u1                *ra;
731         u8                 mcode;
732         constant_classref *cr;
733         classinfo         *c;
734
735         /* get stuff from the stack */
736
737         ra    = (u1 *)                *((ptrint *) (sp + 2 * 8));
738         mcode =                       *((u8 *)     (sp + 1 * 8));
739         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
740
741         /* calculate and set the new return address */
742
743         ra = ra - 5;
744         *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
745
746         *dontfillinexceptionstacktrace=true;
747
748         /* get the fieldinfo */
749
750         if (!(c = helper_resolve_classinfo(cr)))
751         {
752                 *dontfillinexceptionstacktrace=false;
753                 return false;
754         }
755
756         /* patch back original code */
757
758         *((u8 *) ra) = mcode;
759
760         /* patch super class' vftbl */
761
762         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
763
764         *dontfillinexceptionstacktrace=false;
765         return true;
766 }
767
768
769 /* patcher_clinit **************************************************************
770
771    XXX
772
773 *******************************************************************************/
774
775 bool patcher_clinit(u1 *sp)
776 {
777         u1        *ra;
778         u8         mcode;
779         classinfo *c;
780         void      *beginJavaStack;
781
782         /* get stuff from the stack */
783
784         ra    = (u1 *)        *((ptrint *) (sp + 2 * 8));
785         mcode =               *((u8 *)     (sp + 1 * 8));
786         c     = (classinfo *) *((ptrint *) (sp + 0 * 8));
787         beginJavaStack =      (void*) (sp+2*8);
788
789         /* calculate and set the new return address */
790
791         ra = ra - 5;
792         *((ptrint *) (sp + 2 * 8)) = (ptrint) ra;
793
794         /* check if the class is initialized */
795
796         if (!c->initialized)
797         {
798                 bool init;
799                 {
800                         /*struct native_stackframeinfo {
801                                 void *oldThreadspecificHeadValue;
802                                 void **addressOfThreadspecificHead;
803                                 methodinfo *method;
804                                 void *beginOfJavaStackframe; only used if != 0
805                                 void *returnToFromNative;
806                         }*/
807                         /* more or less the same as the above sfi setup is done in the assembler code by the prepare/remove functions*/
808                         native_stackframeinfo sfi;
809                         sfi.returnToFromNative=(void*)ra;
810                         sfi.beginOfJavaStackframe=beginJavaStack;
811                         sfi.method=0; /*internal*/
812                         sfi.addressOfThreadspecificHead=builtin_asm_get_stackframeinfo();
813                         sfi.oldThreadspecificHeadValue=*(sfi.addressOfThreadspecificHead);
814                         *(sfi.addressOfThreadspecificHead)=&sfi;
815
816                         init=initialize_class(c);
817
818                         *(sfi.addressOfThreadspecificHead)=sfi.oldThreadspecificHeadValue;
819                 }
820                 if (!init)
821                 {
822                         return false;
823                 }
824         }
825
826         /* patch back original code */
827
828         *((u8 *) ra) = mcode;
829
830         return true;
831 }
832
833
834 /*
835  * These are local overrides for various environment variables in Emacs.
836  * Please do not remove this and leave it at the end of the file, where
837  * Emacs will automagically detect them.
838  * ---------------------------------------------------------------------
839  * Local variables:
840  * mode: c
841  * indent-tabs-mode: t
842  * c-basic-offset: 4
843  * tab-width: 4
844  * End:
845  * vim:noexpandtab:sw=4:ts=4:
846  */