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