verify that abstract classes are not instantiated
[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 3353 2005-10-05 13:30:10Z edwin $
32
33 */
34
35
36 #include "config.h"
37 #include "vm/types.h"
38
39 #include "mm/memory.h"
40 #include "native/native.h"
41 #include "vm/builtin.h"
42 #include "vm/exceptions.h"
43 #include "vm/field.h"
44 #include "vm/initialize.h"
45 #include "vm/options.h"
46 #include "vm/references.h"
47 #include "vm/jit/helper.h"
48 #include "vm/jit/patcher.h"
49
50
51 /* patcher_get_putstatic *******************************************************
52
53    Machine code:
54
55    <patched call position>
56    4d 8b 15 86 fe ff ff             mov    -378(%rip),%r10
57    49 8b 32                         mov    (%r10),%rsi
58
59 *******************************************************************************/
60
61 bool patcher_get_putstatic(u1 *sp)
62 {
63         u1                *ra;
64         java_objectheader *o;
65         u8                 mcode;
66         unresolved_field  *uf;
67         s4                 disp;
68         fieldinfo         *fi;
69         s4                 offset;
70
71         /* get stuff from the stack */
72
73         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
74         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
75         mcode =                       *((u8 *)     (sp + 2 * 8));
76         uf    = (unresolved_field *)  *((ptrint *) (sp + 1 * 8));
77         disp  =                       *((s4 *)     (sp + 0 * 8));
78
79         /* calculate and set the new return address */
80
81         ra = ra - 5;
82         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
83
84         PATCHER_MONITORENTER;
85
86         /* get the fieldinfo */
87
88         if (!(fi = helper_resolve_fieldinfo(uf))) {
89                 PATCHER_MONITOREXIT;
90
91                 return false;
92         }
93
94         /* check if the field's class is initialized */
95
96         if (!initialize_class(fi->class)) {
97                 PATCHER_MONITOREXIT;
98
99                 return false;
100         }
101
102         /* patch back original code */
103
104         *((u8 *) ra) = mcode;
105
106         /* if we show disassembly, we have to skip the nop's */
107
108         if (opt_showdisassemble)
109                 ra = ra + 5;
110
111         /* get RIP offset from machine instruction */
112
113         offset = *((u4 *) (ra + 3));
114
115         /* patch the field value's address (+ 7: is the size of the RIP move) */
116
117         *((ptrint *) (ra + 7 + offset)) = (ptrint) &(fi->value);
118
119         PATCHER_MARK_PATCHED_MONITOREXIT;
120
121         return true;
122 }
123
124
125 /* patcher_get_putfield ********************************************************
126
127    Machine code:
128
129    <patched call position>
130    45 8b 8f 00 00 00 00             mov    0x0(%r15),%r9d
131
132 *******************************************************************************/
133
134 bool patcher_get_putfield(u1 *sp)
135 {
136         u1                *ra;
137         java_objectheader *o;
138         u8                 mcode;
139         unresolved_field  *uf;
140         fieldinfo         *fi;
141         u1                 byte;
142
143         /* get stuff from the stack */
144
145         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
146         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
147         mcode =                       *((u8 *)     (sp + 2 * 8));
148         uf    = (unresolved_field *)  *((ptrint *) (sp + 1 * 8));
149
150         /* calculate and set the new return address */
151
152         ra = ra - 5;
153         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
154
155         PATCHER_MONITORENTER;
156
157         /* get the fieldinfo */
158
159         if (!(fi = helper_resolve_fieldinfo(uf))) {
160                 PATCHER_MONITOREXIT;
161
162                 return false;
163         }
164
165         /* patch back original code (instruction code is smaller than 8 bytes) */
166
167         *((u4 *) (ra + 0)) = (u4) mcode;
168         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
169
170         /* if we show disassembly, we have to skip the nop's */
171
172         if (opt_showdisassemble)
173                 ra = ra + 5;
174
175         /* patch the field's offset: we check for the field type, because the     */
176         /* instructions have different lengths                                    */
177
178         if (IS_INT_LNG_TYPE(fi->type)) {
179                 /* check for special case: %rsp or %r12 as base register */
180
181                 byte = *(ra + 3);
182
183                 if (byte == 0x24)
184                         *((u4 *) (ra + 4)) = (u4) (fi->offset);
185                 else
186                         *((u4 *) (ra + 3)) = (u4) (fi->offset);
187
188         } else {
189                 /* check for special case: %rsp or %r12 as base register */
190
191                 byte = *(ra + 5);
192
193                 if (byte == 0x24)
194                         *((u4 *) (ra + 6)) = (u4) (fi->offset);
195                 else
196                         *((u4 *) (ra + 5)) = (u4) (fi->offset);
197         }
198
199         PATCHER_MARK_PATCHED_MONITOREXIT;
200
201         return true;
202 }
203
204
205 /* patcher_putfieldconst *******************************************************
206
207    Machine code:
208
209    <patched call position>
210    41 c7 85 00 00 00 00 7b 00 00 00    movl   $0x7b,0x0(%r13)
211
212 *******************************************************************************/
213
214 bool patcher_putfieldconst(u1 *sp)
215 {
216         u1                *ra;
217         java_objectheader *o;
218         u8                 mcode;
219         unresolved_field  *uf;
220         fieldinfo         *fi;
221
222         /* get stuff from the stack */
223
224         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
225         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
226         mcode =                       *((u8 *)     (sp + 2 * 8));
227         uf    = (unresolved_field *)  *((ptrint *) (sp + 1 * 8));
228
229         /* calculate and set the new return address */
230
231         ra = ra - 5;
232         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
233
234         PATCHER_MONITORENTER;
235
236         /* get the fieldinfo */
237
238         if (!(fi = helper_resolve_fieldinfo(uf))) {
239                 PATCHER_MONITOREXIT;
240
241                 return false;
242         }
243
244         /* patch back original code */
245
246         *((u8 *) ra) = mcode;
247
248         /* if we show disassembly, we have to skip the nop's */
249
250         if (opt_showdisassemble)
251                 ra = ra + 5;
252
253         /* patch the field's offset */
254
255         if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
256                 /* handle special case when the base register is %r12 */
257
258                 if (*(ra + 2) == 0x84) {
259                         *((u4 *) (ra + 4)) = (u4) (fi->offset);
260                         *((u4 *) (ra + 12 + 4)) = (u4) (fi->offset + 4);
261
262                 } else {
263                         *((u4 *) (ra + 3)) = (u4) (fi->offset);
264                         *((u4 *) (ra + 11 + 3)) = (u4) (fi->offset + 4);
265                 }
266
267         } else {
268                 /* handle special case when the base register is %r12 */
269
270                 if (*(ra + 2) == 0x84)
271                         *((u4 *) (ra + 4)) = (u4) (fi->offset);
272                 else
273                         *((u4 *) (ra + 3)) = (u4) (fi->offset);
274         }
275
276         PATCHER_MARK_PATCHED_MONITOREXIT;
277
278         return true;
279 }
280
281
282 /* patcher_builtin_new *********************************************************
283
284    Machine code:
285
286    48 bf a0 f0 92 00 00 00 00 00    mov    $0x92f0a0,%rdi
287    <patched call position>
288    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
289    48 ff d0                         callq  *%rax
290
291 *******************************************************************************/
292
293 bool patcher_builtin_new(u1 *sp)
294 {
295         u1                *ra;
296         java_objectheader *o;
297         u8                 mcode;
298         constant_classref *cr;
299         classinfo         *c;
300
301         /* get stuff from the stack */
302
303         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
304         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
305         mcode =                       *((u8 *)     (sp + 2 * 8));
306         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 8));
307
308         /* calculate and set the new return address */
309
310         ra = ra - (10 + 5);
311         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
312
313         PATCHER_MONITORENTER;
314
315         /* get the classinfo */
316
317         if (!(c = helper_resolve_classinfo_nonabstract(cr))) {
318                 PATCHER_MONITOREXIT;
319
320                 return false;
321         }
322
323         if (!initialize_class(c)) {
324                 PATCHER_MONITOREXIT;
325
326                 return false;
327         }
328
329         /* patch back original code */
330
331         *((u8 *) (ra + 10)) = mcode;
332
333         /* patch the classinfo pointer */
334
335         *((ptrint *) (ra + 2)) = (ptrint) c;
336
337         /* if we show disassembly, we have to skip the nop's */
338
339         if (opt_showdisassemble)
340                 ra = ra + 5;
341
342         /* patch new function address */
343
344         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_new;
345
346         PATCHER_MARK_PATCHED_MONITOREXIT;
347
348         return true;
349 }
350
351
352 /* patcher_builtin_newarray ****************************************************
353
354    Machine code:
355
356    48 be 88 13 9b 00 00 00 00 00    mov    $0x9b1388,%rsi
357    <patched call position>
358    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
359    48 ff d0                         callq  *%rax
360
361 *******************************************************************************/
362
363 bool patcher_builtin_newarray(u1 *sp)
364 {
365         u1                *ra;
366         java_objectheader *o;
367         u8                 mcode;
368         constant_classref *cr;
369         classinfo         *c;
370
371         /* get stuff from the stack */
372
373         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
374         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
375         mcode =                       *((u8 *)     (sp + 2 * 8));
376         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 8));
377
378         /* calculate and set the new return address */
379
380         ra = ra - (10 + 5);
381         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
382
383         PATCHER_MONITORENTER;
384
385         /* get the classinfo */
386
387         if (!(c = helper_resolve_classinfo(cr))) {
388                 PATCHER_MONITOREXIT;
389
390                 return false;
391         }
392
393         /* patch back original code */
394
395         *((u8 *) (ra + 10)) = mcode;
396
397         /* patch the class' vftbl pointer */
398
399         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
400
401         /* if we show disassembly, we have to skip the nop's */
402
403         if (opt_showdisassemble)
404                 ra = ra + 5;
405
406         /* patch new function address */
407
408         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_newarray;
409
410         PATCHER_MARK_PATCHED_MONITOREXIT;
411
412         return true;
413 }
414
415
416 /* patcher_builtin_multianewarray **********************************************
417
418    Machine code:
419
420    <patched call position>
421    48 bf 02 00 00 00 00 00 00 00    mov    $0x2,%rdi
422    48 be 30 40 b2 00 00 00 00 00    mov    $0xb24030,%rsi
423    48 89 e2                         mov    %rsp,%rdx
424    48 b8 7c 96 4b 00 00 00 00 00    mov    $0x4b967c,%rax
425    48 ff d0                         callq  *%rax
426
427 *******************************************************************************/
428
429 bool patcher_builtin_multianewarray(u1 *sp)
430 {
431         u1                *ra;
432         java_objectheader *o;
433         u8                 mcode;
434         constant_classref *cr;
435         classinfo         *c;
436
437         /* get stuff from the stack */
438
439         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
440         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
441         mcode =                       *((u8 *)     (sp + 2 * 8));
442         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 8));
443
444         /* calculate and set the new return address */
445
446         ra = ra - 5;
447         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
448
449         PATCHER_MONITORENTER;
450
451         /* get the classinfo */
452
453         if (!(c = helper_resolve_classinfo(cr))) {
454                 PATCHER_MONITOREXIT;
455
456                 return false;
457         }
458
459         /* patch back original code */
460
461         *((u8 *) ra) = mcode;
462
463         /* if we show disassembly, we have to skip the nop's */
464
465         if (opt_showdisassemble)
466                 ra = ra + 5;
467
468         /* patch the class' vftbl pointer */
469
470         *((ptrint *) (ra + 10 + 2)) = (ptrint) c->vftbl;
471
472         /* patch new function address */
473
474         *((ptrint *) (ra + 10 + 10 + 3 + 2)) = (ptrint) BUILTIN_multianewarray;
475
476         PATCHER_MARK_PATCHED_MONITOREXIT;
477
478         return true;
479 }
480
481
482 /* patcher_builtin_arraycheckcast **********************************************
483
484    Machine code:
485
486    <patched call position>
487    48 be b8 3f b2 00 00 00 00 00    mov    $0xb23fb8,%rsi
488    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
489    48 ff d0                         callq  *%rax
490
491 *******************************************************************************/
492
493 bool patcher_builtin_arraycheckcast(u1 *sp)
494 {
495         u1                *ra;
496         java_objectheader *o;
497         u8                 mcode;
498         constant_classref *cr;
499         classinfo         *c;
500
501         /* get stuff from the stack */
502
503         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
504         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
505         mcode =                       *((u8 *)     (sp + 2 * 8));
506         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 8));
507
508         /* calculate and set the new return address */
509
510         ra = ra - 5;
511         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
512
513         PATCHER_MONITORENTER;
514
515         /* get the classinfo */
516
517         if (!(c = helper_resolve_classinfo(cr))) {
518                 PATCHER_MONITOREXIT;
519
520                 return false;
521         }
522
523         /* patch back original code */
524
525         *((u8 *) ra) = mcode;
526
527         /* if we show disassembly, we have to skip the nop's */
528
529         if (opt_showdisassemble)
530                 ra = ra + 5;
531
532         /* patch the class' vftbl pointer */
533
534         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
535
536         /* patch new function address */
537
538         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_arraycheckcast;
539
540         PATCHER_MARK_PATCHED_MONITOREXIT;
541
542         return true;
543 }
544
545
546 /* patcher_builtin_arrayinstanceof *********************************************
547
548    Machine code:
549
550    48 be 30 3c b2 00 00 00 00 00    mov    $0xb23c30,%rsi
551    <patched call position>
552    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
553    48 ff d0                         callq  *%rax
554
555 *******************************************************************************/
556
557 bool patcher_builtin_arrayinstanceof(u1 *sp)
558 {
559         u1                *ra;
560         java_objectheader *o;
561         u8                 mcode;
562         constant_classref *cr;
563         classinfo         *c;
564
565         /* get stuff from the stack */
566
567         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
568         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
569         mcode =                       *((u8 *)     (sp + 2 * 8));
570         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 8));
571
572         /* calculate and set the new return address */
573
574         ra = ra - (10 + 5);
575         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
576
577         PATCHER_MONITORENTER;
578
579         /* get the classinfo */
580
581         if (!(c = helper_resolve_classinfo(cr))) {
582                 PATCHER_MONITOREXIT;
583
584                 return false;
585         }
586
587         /* patch back original code */
588
589         *((u8 *) (ra + 10)) = mcode;
590
591         /* patch the class' vftbl pointer */
592
593         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
594
595         /* if we show disassembly, we have to skip the nop's */
596
597         if (opt_showdisassemble)
598                 ra = ra + 5;
599
600         /* patch new function address */
601
602         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_arrayinstanceof;
603
604         PATCHER_MARK_PATCHED_MONITOREXIT;
605
606         return true;
607 }
608
609
610 /* patcher_invokestatic_special ************************************************
611
612    Machine code:
613
614    <patched call position>
615    49 ba 00 00 00 00 00 00 00 00    mov    $0x0,%r10
616    49 ff d2                         callq  *%r10
617
618 *******************************************************************************/
619
620 bool patcher_invokestatic_special(u1 *sp)
621 {
622         u1                *ra;
623         java_objectheader *o;
624         u8                 mcode;
625         unresolved_method *um;
626         methodinfo        *m;
627
628         /* get stuff from the stack */
629
630         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
631         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
632         mcode =                       *((u8 *)     (sp + 2 * 8));
633         um    = (unresolved_method *) *((ptrint *) (sp + 1 * 8));
634
635         /* calculate and set the new return address */
636
637         ra = ra - 5;
638         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
639
640         PATCHER_MONITORENTER;
641
642         /* get the fieldinfo */
643
644         if (!(m = helper_resolve_methodinfo(um))) {
645                 PATCHER_MONITOREXIT;
646
647                 return false;
648         }
649         /* patch back original code */
650
651         *((u8 *) ra) = mcode;
652
653         /* if we show disassembly, we have to skip the nop's */
654
655         if (opt_showdisassemble)
656                 ra = ra + 5;
657
658         /* patch stubroutine */
659
660         *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine;
661
662         PATCHER_MARK_PATCHED_MONITOREXIT;
663
664         return true;
665 }
666
667
668 /* patcher_invokevirtual *******************************************************
669
670    Machine code:
671
672    <patched call position>
673    4c 8b 17                         mov    (%rdi),%r10
674    49 8b 82 00 00 00 00             mov    0x0(%r10),%rax
675    48 ff d0                         callq  *%rax
676
677 *******************************************************************************/
678
679 bool patcher_invokevirtual(u1 *sp)
680 {
681         u1                *ra;
682         java_objectheader *o;
683         u8                 mcode;
684         unresolved_method *um;
685         methodinfo        *m;
686
687         /* get stuff from the stack */
688
689         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
690         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
691         mcode =                       *((u8 *)     (sp + 2 * 8));
692         um    = (unresolved_method *) *((ptrint *) (sp + 1 * 8));
693
694         /* calculate and set the new return address */
695
696         ra = ra - 5;
697         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
698
699         PATCHER_MONITORENTER;
700
701         /* get the fieldinfo */
702
703         if (!(m = helper_resolve_methodinfo(um))) {
704                 PATCHER_MONITOREXIT;
705
706                 return false;
707         }
708
709         /* patch back original code */
710
711         *((u8 *) ra) = mcode;
712
713         /* if we show disassembly, we have to skip the nop's */
714
715         if (opt_showdisassemble)
716                 ra = ra + 5;
717
718         /* patch vftbl index */
719
720         *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
721                                                                    sizeof(methodptr) * m->vftblindex);
722
723         PATCHER_MARK_PATCHED_MONITOREXIT;
724
725         return true;
726 }
727
728
729 /* patcher_invokeinterface *****************************************************
730
731    Machine code:
732
733    <patched call position>
734    4c 8b 17                         mov    (%rdi),%r10
735    4d 8b 92 00 00 00 00             mov    0x0(%r10),%r10
736    49 8b 82 00 00 00 00             mov    0x0(%r10),%rax
737    48 ff d0                         callq  *%rax
738
739 *******************************************************************************/
740
741 bool patcher_invokeinterface(u1 *sp)
742 {
743         u1                *ra;
744         java_objectheader *o;
745         u8                 mcode;
746         unresolved_method *um;
747         methodinfo        *m;
748
749         /* get stuff from the stack */
750
751         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
752         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
753         mcode =                       *((u8 *)     (sp + 2 * 8));
754         um    = (unresolved_method *) *((ptrint *) (sp + 1 * 8));
755
756         /* calculate and set the new return address */
757
758         ra = ra - 5;
759         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
760
761         PATCHER_MONITORENTER;
762
763         /* get the fieldinfo */
764
765         if (!(m = helper_resolve_methodinfo(um))) {
766                 PATCHER_MONITOREXIT;
767
768                 return false;
769         }
770
771         /* patch back original code */
772
773         *((u8 *) ra) = mcode;
774
775         /* if we show disassembly, we have to skip the nop's */
776
777         if (opt_showdisassemble)
778                 ra = ra + 5;
779
780         /* patch interfacetable index */
781
782         *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
783                                                                    sizeof(methodptr) * m->class->index);
784
785         /* patch method offset */
786
787         *((s4 *) (ra + 3 + 7 + 3)) =
788                 (s4) (sizeof(methodptr) * (m - m->class->methods));
789
790         PATCHER_MARK_PATCHED_MONITOREXIT;
791
792         return true;
793 }
794
795
796 /* patcher_checkcast_instanceof_flags ******************************************
797
798    Machine code:
799
800    <patched call position>
801    41 ba 00 00 00 00                mov    $0x0,%r10d
802    41 81 e2 00 02 00 00             and    $0x200,%r10d
803    0f 84 35 00 00 00                je     0x00002aaaaab01479
804
805 *******************************************************************************/
806
807 bool patcher_checkcast_instanceof_flags(u1 *sp)
808 {
809         u1                *ra;
810         java_objectheader *o;
811         u8                 mcode;
812         constant_classref *cr;
813         classinfo         *c;
814
815         /* get stuff from the stack */
816
817         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
818         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
819         mcode =                       *((u8 *)     (sp + 2 * 8));
820         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 8));
821
822         /* calculate and set the new return address */
823
824         ra = ra - 5;
825         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
826
827         PATCHER_MONITORENTER;
828
829         /* get the fieldinfo */
830
831         if (!(c = helper_resolve_classinfo(cr))) {
832                 PATCHER_MONITOREXIT;
833
834                 return false;
835         }
836
837         /* patch back original code */
838
839         *((u8 *) ra) = mcode;
840
841         /* if we show disassembly, we have to skip the nop's */
842
843         if (opt_showdisassemble)
844                 ra = ra + 5;
845
846         /* patch class flags */
847
848         *((s4 *) (ra + 2)) = (s4) c->flags;
849
850         PATCHER_MARK_PATCHED_MONITOREXIT;
851
852         return true;
853 }
854
855
856 /* patcher_checkcast_instanceof_interface **************************************
857
858    Machine code:
859
860    <patched call position>
861    45 8b 9a 1c 00 00 00             mov    0x1c(%r10),%r11d
862    49 81 eb 00 00 00 00             sub    $0x0,%r11
863    4d 85 db                         test   %r11,%r11
864    0f 8e 94 04 00 00                jle    0x00002aaaaab018f8
865    4d 8b 9a 00 00 00 00             mov    0x0(%r10),%r11
866
867 *******************************************************************************/
868
869 bool patcher_checkcast_instanceof_interface(u1 *sp)
870 {
871         u1                *ra;
872         java_objectheader *o;
873         u8                 mcode;
874         constant_classref *cr;
875         classinfo         *c;
876
877         /* get stuff from the stack */
878
879         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
880         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
881         mcode =                       *((u8 *)     (sp + 2 * 8));
882         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 8));
883
884         /* calculate and set the new return address */
885
886         ra = ra - 5;
887         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
888
889         PATCHER_MONITORENTER;
890
891         /* get the fieldinfo */
892
893         if (!(c = helper_resolve_classinfo(cr))) {
894                 PATCHER_MONITOREXIT;
895
896                 return false;
897         }
898
899         /* patch back original code */
900
901         *((u8 *) ra) = mcode;
902
903         /* if we show disassembly, we have to skip the nop's */
904
905         if (opt_showdisassemble)
906                 ra = ra + 5;
907
908         /* patch super class index */
909
910         *((s4 *) (ra + 7 + 3)) = (s4) c->index;
911
912         *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
913                 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
914                           c->index * sizeof(methodptr*));
915
916         PATCHER_MARK_PATCHED_MONITOREXIT;
917
918         return true;
919 }
920
921
922 /* patcher_checkcast_class *****************************************************
923
924    Machine code:
925
926    <patched call position>
927    49 bb 00 00 00 00 00 00 00 00    mov    $0x0,%r11
928    45 8b 92 20 00 00 00             mov    0x20(%r10),%r10d
929    45 8b 9b 20 00 00 00             mov    0x20(%r11),%r11d
930    4d 29 da                         sub    %r11,%r10
931    49 bb 00 00 00 00 00 00 00 00    mov    $0x0,%r11
932
933 *******************************************************************************/
934
935 bool patcher_checkcast_class(u1 *sp)
936 {
937         u1                *ra;
938         java_objectheader *o;
939         u8                 mcode;
940         constant_classref *cr;
941         classinfo         *c;
942
943         /* get stuff from the stack */
944
945         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
946         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
947         mcode =                       *((u8 *)     (sp + 2 * 8));
948         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 8));
949
950         /* calculate and set the new return address */
951
952         ra = ra - 5;
953         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
954
955         PATCHER_MONITORENTER;
956
957         /* get the fieldinfo */
958
959         if (!(c = helper_resolve_classinfo(cr))) {
960                 PATCHER_MONITOREXIT;
961
962                 return false;
963         }
964
965         /* patch back original code */
966
967         *((u8 *) ra) = mcode;
968
969         /* if we show disassembly, we have to skip the nop's */
970
971         if (opt_showdisassemble)
972                 ra = ra + 5;
973
974         /* patch super class' vftbl */
975
976         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
977         *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
978
979         PATCHER_MARK_PATCHED_MONITOREXIT;
980
981         return true;
982 }
983
984
985 /* patcher_instanceof_class ****************************************************
986
987    Machine code:
988
989    <patched call position>
990    49 ba 00 00 00 00 00 00 00 00    mov    $0x0,%r10
991
992 *******************************************************************************/
993
994 bool patcher_instanceof_class(u1 *sp)
995 {
996         u1                *ra;
997         java_objectheader *o;
998         u8                 mcode;
999         constant_classref *cr;
1000         classinfo         *c;
1001
1002         /* get stuff from the stack */
1003
1004         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
1005         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
1006         mcode =                       *((u8 *)     (sp + 2 * 8));
1007         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 8));
1008
1009         /* calculate and set the new return address */
1010
1011         ra = ra - 5;
1012         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
1013
1014         PATCHER_MONITORENTER;
1015
1016         /* get the fieldinfo */
1017
1018         if (!(c = helper_resolve_classinfo(cr))) {
1019                 PATCHER_MONITOREXIT;
1020
1021                 return false;
1022         }
1023
1024         /* patch back original code */
1025
1026         *((u8 *) ra) = mcode;
1027
1028         /* if we show disassembly, we have to skip the nop's */
1029
1030         if (opt_showdisassemble)
1031                 ra = ra + 5;
1032
1033         /* patch super class' vftbl */
1034
1035         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
1036
1037         PATCHER_MARK_PATCHED_MONITOREXIT;
1038
1039         return true;
1040 }
1041
1042
1043 /* patcher_clinit **************************************************************
1044
1045    May be used for GET/PUTSTATIC and in native stub.
1046
1047    Machine code:
1048
1049    <patched call position>
1050    4d 8b 15 92 ff ff ff             mov    -110(%rip),%r10
1051    49 89 1a                         mov    %rbx,(%r10)
1052
1053 *******************************************************************************/
1054
1055 bool patcher_clinit(u1 *sp)
1056 {
1057         u1                *ra;
1058         java_objectheader *o;
1059         u8                 mcode;
1060         classinfo         *c;
1061
1062         /* get stuff from the stack */
1063
1064         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
1065         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
1066         mcode =                       *((u8 *)     (sp + 2 * 8));
1067         c     = (classinfo *)         *((ptrint *) (sp + 1 * 8));
1068
1069         /* calculate and set the new return address */
1070
1071         ra = ra - 5;
1072         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
1073
1074         PATCHER_MONITORENTER;
1075
1076         /* check if the class is initialized */
1077
1078         if (!initialize_class(c)) {
1079                 PATCHER_MONITOREXIT;
1080
1081                 return false;
1082         }
1083
1084         /* patch back original code */
1085
1086         *((u8 *) ra) = mcode;
1087
1088         PATCHER_MARK_PATCHED_MONITOREXIT;
1089
1090         return true;
1091 }
1092
1093
1094 /* patcher_resolve_native ******************************************************
1095
1096    Machine code:
1097
1098    <patched call position>
1099    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
1100    48 ff d0                         callq  *%rax
1101
1102 *******************************************************************************/
1103
1104 #if !defined(ENABLE_STATICVM)
1105 bool patcher_resolve_native(u1 *sp)
1106 {
1107         u1                *ra;
1108         java_objectheader *o;
1109         u8                 mcode;
1110         methodinfo        *m;
1111         functionptr        f;
1112
1113         /* get stuff from the stack */
1114
1115         ra    = (u1 *)                *((ptrint *) (sp + 4 * 8));
1116         o     = (java_objectheader *) *((ptrint *) (sp + 3 * 8));
1117         mcode =                       *((u8 *)     (sp + 2 * 8));
1118         m     = (methodinfo *)        *((ptrint *) (sp + 1 * 8));
1119
1120         /* calculate and set the new return address */
1121
1122         ra = ra - 5;
1123         *((ptrint *) (sp + 4 * 8)) = (ptrint) ra;
1124
1125         PATCHER_MONITORENTER;
1126
1127         /* resolve native function */
1128
1129         if (!(f = native_resolve_function(m))) {
1130                 PATCHER_MONITOREXIT;
1131
1132                 return false;
1133         }
1134
1135         /* patch back original code */
1136
1137         *((u8 *) ra) = mcode;
1138
1139         /* if we show disassembly, we have to skip the nop's */
1140
1141         if (opt_showdisassemble)
1142                 ra = ra + 5;
1143
1144         /* patch native function pointer */
1145
1146         *((ptrint *) (ra + 2)) = (ptrint) f;
1147
1148         PATCHER_MARK_PATCHED_MONITOREXIT;
1149
1150         return true;
1151 }
1152 #endif /* !defined(ENABLE_STATICVM) */
1153
1154
1155 /*
1156  * These are local overrides for various environment variables in Emacs.
1157  * Please do not remove this and leave it at the end of the file, where
1158  * Emacs will automagically detect them.
1159  * ---------------------------------------------------------------------
1160  * Local variables:
1161  * mode: c
1162  * indent-tabs-mode: t
1163  * c-basic-offset: 4
1164  * tab-width: 4
1165  * End:
1166  * vim:noexpandtab:sw=4:ts=4:
1167  */