* Removed all Id tags.
[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, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25 */
26
27
28 #include "config.h"
29
30 #include <stdint.h>
31
32 #include "vm/types.h"
33
34 #include "vm/jit/x86_64/codegen.h"
35
36 #include "mm/memory.h"
37
38 #include "native/native.h"
39
40 #include "vm/builtin.h"
41 #include "vm/exceptions.h"
42 #include "vm/initialize.h"
43
44 #include "vm/jit/patcher.h"
45 #include "vm/jit/stacktrace.h"
46
47 #include "vmcore/class.h"
48 #include "vmcore/field.h"
49 #include "vmcore/options.h"
50 #include "vmcore/references.h"
51 #include "vm/resolve.h"
52
53
54 /* patcher_wrapper *************************************************************
55
56    Wrapper for all patchers.  It also creates the stackframe info
57    structure.
58
59    If the return value of the patcher function is false, it gets the
60    exception object, clears the exception pointer and returns the
61    exception.
62
63 *******************************************************************************/
64
65 java_object_t *patcher_wrapper(u1 *sp, u1 *pv, u1 *ra)
66 {
67         stackframeinfo     sfi;
68         u1                *xpc;
69         java_object_t     *o;
70         functionptr        f;
71         bool               result;
72         java_handle_t     *e;
73
74         /* define the patcher function */
75
76         bool (*patcher_function)(u1 *);
77
78         /* get stuff from the stack */
79
80         xpc = (u1 *)                *((ptrint *) (sp + 5 * 8));
81         o   = (java_object_t *)     *((ptrint *) (sp + 4 * 8));
82         f   = (functionptr)         *((ptrint *) (sp + 0 * 8));
83
84         /* calculate and set the new return address */
85
86         xpc = xpc - PATCHER_CALL_SIZE;
87
88         *((ptrint *) (sp + 5 * 8)) = (ptrint) xpc;
89
90         /* cast the passed function to a patcher function */
91
92         patcher_function = (bool (*)(u1 *)) (ptrint) f;
93
94         /* enter a monitor on the patching position */
95
96         PATCHER_MONITORENTER;
97
98         /* create the stackframeinfo */
99
100         /* RA is passed as NULL, but the XPC is correct and can be used in
101            stacktrace_create_extern_stackframeinfo for
102            md_codegen_get_pv_from_pc. */
103
104         stacktrace_create_extern_stackframeinfo(&sfi, pv, sp + 6 * 8, xpc, xpc);
105
106         /* call the proper patcher function */
107
108         result = (patcher_function)(sp);
109
110         /* remove the stackframeinfo */
111
112         stacktrace_remove_stackframeinfo(&sfi);
113
114         /* check for return value and exit accordingly */
115
116         if (result == false) {
117                 e = exceptions_get_and_clear_exception();
118
119                 PATCHER_MONITOREXIT;
120
121                 return e;
122         }
123
124         PATCHER_MARK_PATCHED_MONITOREXIT;
125
126         return NULL;
127 }
128
129
130 /* patcher_get_putstatic *******************************************************
131
132    Machine code:
133
134    <patched call position>
135    4d 8b 15 86 fe ff ff             mov    -378(%rip),%r10
136    49 8b 32                         mov    (%r10),%rsi
137
138 *******************************************************************************/
139
140 bool patcher_get_putstatic(u1 *sp)
141 {
142         u1               *ra;
143         u8                mcode;
144         unresolved_field *uf;
145         s4                disp;
146         fieldinfo        *fi;
147
148         /* get stuff from the stack */
149
150         ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
151         mcode =                      *((u8 *)     (sp + 3 * 8));
152         uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
153         disp  =                      *((s4 *)     (sp + 1 * 8));
154
155         /* get the fieldinfo */
156
157         if (!(fi = resolve_field_eager(uf)))
158                 return false;
159
160         /* check if the field's class is initialized */
161
162         if (!(fi->class->state & CLASS_INITIALIZED))
163                 if (!initialize_class(fi->class))
164                         return false;
165
166         /* patch back original code */
167
168         *((u8 *) ra) = mcode;
169
170         /* if we show disassembly, we have to skip the nop's */
171
172         if (opt_shownops)
173                 ra = ra + 5;
174
175         /* patch the field value's address */
176
177         *((intptr_t *) (ra + 7 + disp)) = (intptr_t) fi->value;
178
179         return true;
180 }
181
182
183 /* patcher_get_putfield ********************************************************
184
185    Machine code:
186
187    <patched call position>
188    45 8b 8f 00 00 00 00             mov    0x0(%r15),%r9d
189
190 *******************************************************************************/
191
192 bool patcher_get_putfield(u1 *sp)
193 {
194         u1               *ra;
195         u8                mcode;
196         unresolved_field *uf;
197         fieldinfo        *fi;
198         u1                byte;
199
200         /* get stuff from the stack */
201
202         ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
203         mcode =                      *((u8 *)     (sp + 3 * 8));
204         uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
205
206         /* get the fieldinfo */
207
208         if (!(fi = resolve_field_eager(uf)))
209                 return false;
210
211         /* patch back original code (instruction code is smaller than 8 bytes) */
212
213         *((u4 *) (ra + 0)) = (u4) mcode;
214         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
215
216         /* if we show disassembly, we have to skip the nop's */
217
218         if (opt_shownops)
219                 ra = ra + 5;
220
221         /* patch the field's offset: we check for the field type, because the     */
222         /* instructions have different lengths                                    */
223
224         if (IS_INT_LNG_TYPE(fi->type)) {
225                 /* check for special case: %rsp or %r12 as base register */
226
227                 byte = *(ra + 3);
228
229                 if (byte == 0x24)
230                         *((int32_t *) (ra + 4)) = fi->offset;
231                 else
232                         *((int32_t *) (ra + 3)) = fi->offset;
233         }
234         else {
235                 /* check for special case: %rsp or %r12 as base register */
236
237                 byte = *(ra + 5);
238
239                 if (byte == 0x24)
240                         *((int32_t *) (ra + 6)) = fi->offset;
241                 else
242                         *((int32_t *) (ra + 5)) = fi->offset;
243         }
244
245         return true;
246 }
247
248
249 /* patcher_putfieldconst *******************************************************
250
251    Machine code:
252
253    <patched call position>
254    41 c7 85 00 00 00 00 7b 00 00 00    movl   $0x7b,0x0(%r13)
255
256 *******************************************************************************/
257
258 bool patcher_putfieldconst(u1 *sp)
259 {
260         u1               *ra;
261         u8                mcode;
262         unresolved_field *uf;
263         fieldinfo        *fi;
264
265         /* get stuff from the stack */
266
267         ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
268         mcode =                      *((u8 *)     (sp + 3 * 8));
269         uf    = (unresolved_field *) *((ptrint *) (sp + 2 * 8));
270
271         /* get the fieldinfo */
272
273         if (!(fi = resolve_field_eager(uf)))
274                 return false;
275
276         /* patch back original code */
277
278         *((u8 *) ra) = mcode;
279
280         /* if we show disassembly, we have to skip the nop's */
281
282         if (opt_shownops)
283                 ra = ra + 5;
284
285         /* patch the field's offset */
286
287         if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
288                 /* handle special case when the base register is %r12 */
289
290                 if (*(ra + 2) == 0x84) {
291                         *((uint32_t *) (ra + 4))      = fi->offset;
292                         *((uint32_t *) (ra + 12 + 4)) = fi->offset + 4;
293                 }
294                 else {
295                         *((uint32_t *) (ra + 3))      = fi->offset;
296                         *((uint32_t *) (ra + 11 + 3)) = fi->offset + 4;
297                 }
298         }
299         else {
300                 /* handle special case when the base register is %r12 */
301
302                 if (*(ra + 2) == 0x84)
303                         *((uint32_t *) (ra + 4)) = fi->offset;
304                 else
305                         *((uint32_t *) (ra + 3)) = fi->offset;
306         }
307
308         return true;
309 }
310
311
312 /* patcher_aconst **************************************************************
313
314    Machine code:
315
316    <patched call position>
317    48 bf a0 f0 92 00 00 00 00 00    mov    $0x92f0a0,%rdi
318
319 *******************************************************************************/
320
321 bool patcher_aconst(u1 *sp)
322 {
323         u1                *ra;
324         u8                 mcode;
325         constant_classref *cr;
326         classinfo         *c;
327
328         /* get stuff from the stack */
329
330         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
331         mcode =                       *((u8 *)     (sp + 3 * 8));
332         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
333
334         /* get the classinfo */
335
336         if (!(c = resolve_classref_eager(cr)))
337                 return false;
338
339         /* patch back original code */
340
341         *((u8 *) ra) = mcode;
342
343         /* if we show disassembly, we have to skip the nop's */
344
345         if (opt_shownops)
346                 ra = ra + 5;
347
348         /* patch the classinfo pointer */
349
350         *((ptrint *) (ra + 2)) = (ptrint) c;
351
352         return true;
353 }
354
355
356 /* patcher_builtin_multianewarray **********************************************
357
358    Machine code:
359
360    <patched call position>
361    48 bf 02 00 00 00 00 00 00 00    mov    $0x2,%rdi
362    48 be 30 40 b2 00 00 00 00 00    mov    $0xb24030,%rsi
363    48 89 e2                         mov    %rsp,%rdx
364    48 b8 7c 96 4b 00 00 00 00 00    mov    $0x4b967c,%rax
365    48 ff d0                         callq  *%rax
366
367 *******************************************************************************/
368
369 bool patcher_builtin_multianewarray(u1 *sp)
370 {
371         u1                *ra;
372         u8                 mcode;
373         constant_classref *cr;
374         classinfo         *c;
375
376         /* get stuff from the stack */
377
378         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
379         mcode =                       *((u8 *)     (sp + 3 * 8));
380         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
381
382         /* get the classinfo */
383
384         if (!(c = resolve_classref_eager(cr)))
385                 return false;
386
387         /* patch back original code */
388
389         *((u8 *) ra) = mcode;
390
391         /* if we show disassembly, we have to skip the nop's */
392
393         if (opt_shownops)
394                 ra = ra + 5;
395
396         /* patch the classinfo pointer */
397
398         *((ptrint *) (ra + 10 + 2)) = (ptrint) c;
399
400         return true;
401 }
402
403
404 /* patcher_builtin_arraycheckcast **********************************************
405
406    Machine code:
407
408    <patched call position>
409    48 be b8 3f b2 00 00 00 00 00    mov    $0xb23fb8,%rsi
410    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
411    48 ff d0                         callq  *%rax
412
413 *******************************************************************************/
414
415 bool patcher_builtin_arraycheckcast(u1 *sp)
416 {
417         u1                *ra;
418         u8                 mcode;
419         constant_classref *cr;
420         classinfo         *c;
421
422         /* get stuff from the stack */
423
424         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
425         mcode =                       *((u8 *)     (sp + 3 * 8));
426         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
427
428         /* get the classinfo */
429
430         if (!(c = resolve_classref_eager(cr)))
431                 return false;
432
433         /* patch back original code */
434
435         *((u8 *) ra) = mcode;
436
437         /* if we show disassembly, we have to skip the nop's */
438
439         if (opt_shownops)
440                 ra = ra + 5;
441
442         /* patch the classinfo pointer */
443
444         *((ptrint *) (ra + 2)) = (ptrint) c;
445
446         return true;
447 }
448
449
450 /* patcher_invokestatic_special ************************************************
451
452    Machine code:
453
454    <patched call position>
455    49 ba 00 00 00 00 00 00 00 00    mov    $0x0,%r10
456    49 ff d2                         callq  *%r10
457
458 *******************************************************************************/
459
460 bool patcher_invokestatic_special(u1 *sp)
461 {
462         u1                *ra;
463         u8                 mcode;
464         unresolved_method *um;
465         s4                 disp;
466         methodinfo        *m;
467
468         /* get stuff from the stack */
469
470         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
471         mcode =                       *((u8 *)     (sp + 3 * 8));
472         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
473         disp  =                       *((s4 *)     (sp + 1 * 8));
474
475         /* get the fieldinfo */
476
477         if (!(m = resolve_method_eager(um)))
478                 return false;
479
480         /* patch back original code */
481
482         *((u8 *) ra) = mcode;
483
484         /* if we show disassembly, we have to skip the nop's */
485
486         if (opt_shownops)
487                 ra = ra + PATCHER_CALL_SIZE;
488
489         /* patch stubroutine */
490
491 /*      *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine; */
492         *((ptrint *) (ra + 7 + disp)) = (ptrint) m->stubroutine;
493
494         return true;
495 }
496
497
498 /* patcher_invokevirtual *******************************************************
499
500    Machine code:
501
502    <patched call position>
503    4c 8b 17                         mov    (%rdi),%r10
504    49 8b 82 00 00 00 00             mov    0x0(%r10),%rax
505    48 ff d0                         callq  *%rax
506
507 *******************************************************************************/
508
509 bool patcher_invokevirtual(u1 *sp)
510 {
511         u1                *ra;
512         u8                 mcode;
513         unresolved_method *um;
514         methodinfo        *m;
515
516         /* get stuff from the stack */
517
518         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
519         mcode =                       *((u8 *)     (sp + 3 * 8));
520         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
521
522         /* get the fieldinfo */
523
524         if (!(m = resolve_method_eager(um)))
525                 return false;
526
527         /* patch back original code */
528
529         *((u8 *) ra) = mcode;
530
531         /* if we show disassembly, we have to skip the nop's */
532
533         if (opt_shownops)
534                 ra = ra + 5;
535
536         /* patch vftbl index */
537
538         *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
539                                                                    sizeof(methodptr) * m->vftblindex);
540
541         return true;
542 }
543
544
545 /* patcher_invokeinterface *****************************************************
546
547    Machine code:
548
549    <patched call position>
550    4c 8b 17                         mov    (%rdi),%r10
551    4d 8b 92 00 00 00 00             mov    0x0(%r10),%r10
552    49 8b 82 00 00 00 00             mov    0x0(%r10),%rax
553    48 ff d0                         callq  *%rax
554
555 *******************************************************************************/
556
557 bool patcher_invokeinterface(u1 *sp)
558 {
559         u1                *ra;
560         u8                 mcode;
561         unresolved_method *um;
562         methodinfo        *m;
563
564         /* get stuff from the stack */
565
566         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
567         mcode =                       *((u8 *)     (sp + 3 * 8));
568         um    = (unresolved_method *) *((ptrint *) (sp + 2 * 8));
569
570         /* get the fieldinfo */
571
572         if (!(m = resolve_method_eager(um)))
573                 return false;
574
575         /* patch back original code */
576
577         *((u8 *) ra) = mcode;
578
579         /* if we show disassembly, we have to skip the nop's */
580
581         if (opt_shownops)
582                 ra = ra + 5;
583
584         /* patch interfacetable index */
585
586         *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
587                                                                    sizeof(methodptr) * m->class->index);
588
589         /* patch method offset */
590
591         *((s4 *) (ra + 3 + 7 + 3)) =
592                 (s4) (sizeof(methodptr) * (m - m->class->methods));
593
594         return true;
595 }
596
597
598 /* patcher_checkcast_instanceof_flags ******************************************
599
600    Machine code:
601
602    <patched call position>
603    41 ba 00 00 00 00                mov    $0x0,%r10d
604    41 81 e2 00 02 00 00             and    $0x200,%r10d
605    0f 84 35 00 00 00                je     0x00002aaaaab01479
606
607 *******************************************************************************/
608
609 bool patcher_checkcast_instanceof_flags(u1 *sp)
610 {
611         u1                *ra;
612         u8                 mcode;
613         constant_classref *cr;
614         classinfo         *c;
615
616         /* get stuff from the stack */
617
618         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
619         mcode =                       *((u8 *)     (sp + 3 * 8));
620         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
621
622         /* get the fieldinfo */
623
624         if (!(c = resolve_classref_eager(cr)))
625                 return false;
626
627         /* patch back original code */
628
629         *((u8 *) ra) = mcode;
630
631         /* if we show disassembly, we have to skip the nop's */
632
633         if (opt_shownops)
634                 ra = ra + 5;
635
636         /* patch class flags */
637
638         *((s4 *) (ra + 2)) = (s4) c->flags;
639
640         return true;
641 }
642
643
644 /* patcher_checkcast_interface *************************************************
645
646    Machine code:
647
648    <patched call position>
649    45 8b 9a 1c 00 00 00             mov    0x1c(%r10),%r11d
650    41 81 fb 00 00 00 00             cmp    $0x0,%r11d
651    0f 8f 08 00 00 00                jg     0x00002aaaaae511d5
652    48 8b 0c 25 03 00 00 00          mov    0x3,%rcx
653    4d 8b 9a 00 00 00 00             mov    0x0(%r10),%r11
654
655 *******************************************************************************/
656
657 bool patcher_checkcast_interface(u1 *sp)
658 {
659         u1                *ra;
660         u8                 mcode;
661         constant_classref *cr;
662         classinfo         *c;
663
664         /* get stuff from the stack */
665
666         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
667         mcode =                       *((u8 *)     (sp + 3 * 8));
668         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
669
670         /* get the fieldinfo */
671
672         if (!(c = resolve_classref_eager(cr)))
673                 return false;
674
675         /* patch back original code */
676
677         *((u8 *) ra) = mcode;
678
679         /* if we show disassembly, we have to skip the nop's */
680
681         if (opt_shownops)
682                 ra = ra + PATCHER_CALL_SIZE;
683
684         /* patch super class index */
685
686         *((s4 *) (ra + 7 + 3)) = (s4) c->index;
687
688         *((s4 *) (ra + 7 + 7 + 6 + 8 + 3)) =
689                 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
690                           c->index * sizeof(methodptr*));
691
692         return true;
693 }
694
695
696 /* patcher_checkcast_class *****************************************************
697
698    Machine code:
699
700    <patched call position>
701    49 bb 00 00 00 00 00 00 00 00    mov    $0x0,%r11
702    45 8b 92 20 00 00 00             mov    0x20(%r10),%r10d
703    45 8b 9b 20 00 00 00             mov    0x20(%r11),%r11d
704    4d 29 da                         sub    %r11,%r10
705    49 bb 00 00 00 00 00 00 00 00    mov    $0x0,%r11
706
707 *******************************************************************************/
708
709 bool patcher_checkcast_class(u1 *sp)
710 {
711         u1                *ra;
712         u8                 mcode;
713         constant_classref *cr;
714         classinfo         *c;
715
716         /* get stuff from the stack */
717
718         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
719         mcode =                       *((u8 *)     (sp + 3 * 8));
720         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
721
722         /* get the fieldinfo */
723
724         if (!(c = resolve_classref_eager(cr)))
725                 return false;
726
727         /* patch back original code */
728
729         *((u8 *) ra) = mcode;
730
731         /* if we show disassembly, we have to skip the nop's */
732
733         if (opt_shownops)
734                 ra = ra + 5;
735
736         /* patch super class' vftbl */
737
738         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
739         *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
740
741         return true;
742 }
743
744
745 /* patcher_instanceof_interface ************************************************
746
747    Machine code:
748
749    <patched call position>
750    45 8b 9a 1c 00 00 00             mov    0x1c(%r10),%r11d
751    41 81 fb 00 00 00 00             cmp    $0x0,%r11d
752    0f 8e 94 04 00 00                jle    0x00002aaaaab018f8
753    4d 8b 9a 00 00 00 00             mov    0x0(%r10),%r11
754
755 *******************************************************************************/
756
757 bool patcher_instanceof_interface(u1 *sp)
758 {
759         u1                *ra;
760         u8                 mcode;
761         constant_classref *cr;
762         classinfo         *c;
763
764         /* get stuff from the stack */
765
766         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
767         mcode =                       *((u8 *)     (sp + 3 * 8));
768         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
769
770         /* get the fieldinfo */
771
772         if (!(c = resolve_classref_eager(cr)))
773                 return false;
774
775         /* patch back original code */
776
777         *((u8 *) ra) = mcode;
778
779         /* if we show disassembly, we have to skip the nop's */
780
781         if (opt_shownops)
782                 ra = ra + PATCHER_CALL_SIZE;
783
784         /* patch super class index */
785
786         *((s4 *) (ra + 7 + 3)) = (s4) c->index;
787
788         *((s4 *) (ra + 7 + 7 + 6 + 3)) =
789                 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
790                           c->index * sizeof(methodptr*));
791
792         return true;
793 }
794
795
796 /* patcher_instanceof_class ****************************************************
797
798    Machine code:
799
800    <patched call position>
801    49 ba 00 00 00 00 00 00 00 00    mov    $0x0,%r10
802
803 *******************************************************************************/
804
805 bool patcher_instanceof_class(u1 *sp)
806 {
807         u1                *ra;
808         u8                 mcode;
809         constant_classref *cr;
810         classinfo         *c;
811
812         /* get stuff from the stack */
813
814         ra    = (u1 *)                *((ptrint *) (sp + 5 * 8));
815         mcode =                       *((u8 *)     (sp + 3 * 8));
816         cr    = (constant_classref *) *((ptrint *) (sp + 2 * 8));
817
818         /* get the fieldinfo */
819
820         if (!(c = resolve_classref_eager(cr)))
821                 return false;
822
823         /* patch back original code */
824
825         *((u8 *) ra) = mcode;
826
827         /* if we show disassembly, we have to skip the nop's */
828
829         if (opt_shownops)
830                 ra = ra + 5;
831
832         /* patch super class' vftbl */
833
834         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
835
836         return true;
837 }
838
839
840 /* patcher_clinit **************************************************************
841
842    May be used for GET/PUTSTATIC and in native stub.
843
844    Machine code:
845
846    <patched call position>
847    4d 8b 15 92 ff ff ff             mov    -110(%rip),%r10
848    49 89 1a                         mov    %rbx,(%r10)
849
850 *******************************************************************************/
851
852 bool patcher_clinit(u1 *sp)
853 {
854         u1        *ra;
855         u8         mcode;
856         classinfo *c;
857
858         /* get stuff from the stack */
859
860         ra    = (u1 *)        *((ptrint *) (sp + 5 * 8));
861         mcode =               *((u8 *)     (sp + 3 * 8));
862         c     = (classinfo *) *((ptrint *) (sp + 2 * 8));
863
864         /* check if the class is initialized */
865
866         if (!(c->state & CLASS_INITIALIZED))
867                 if (!initialize_class(c))
868                         return false;
869
870         /* patch back original code */
871
872         *((u8 *) ra) = mcode;
873
874         return true;
875 }
876
877
878 /* patcher_athrow_areturn ******************************************************
879
880    Machine code:
881
882    <patched call position>
883
884 *******************************************************************************/
885
886 #ifdef ENABLE_VERIFIER
887 bool patcher_athrow_areturn(u1 *sp)
888 {
889         u1               *ra;
890         u8                mcode;
891         unresolved_class *uc;
892
893         /* get stuff from the stack */
894
895         ra    = (u1 *)               *((ptrint *) (sp + 5 * 8));
896         mcode =                      *((u8 *)     (sp + 3 * 8));
897         uc    = (unresolved_class *) *((ptrint *) (sp + 2 * 8));
898
899         /* resolve the class and check subtype constraints */
900
901         if (!resolve_class_eager_no_access_check(uc))
902                 return false;
903
904         /* patch back original code */
905
906         *((u8 *) ra) = mcode;
907
908         return true;
909 }
910 #endif /* ENABLE_VERIFIER */
911
912
913 /* patcher_resolve_native ******************************************************
914
915    Machine code:
916
917    <patched call position>
918    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
919    48 ff d0                         callq  *%rax
920
921 *******************************************************************************/
922
923 #if !defined(WITH_STATIC_CLASSPATH)
924 bool patcher_resolve_native(u1 *sp)
925 {
926         u1          *ra;
927         u8           mcode;
928         methodinfo  *m;
929         functionptr  f;
930
931         /* get stuff from the stack */
932
933         ra    = (u1 *)         *((ptrint *) (sp + 5 * 8));
934         mcode =                *((u8 *)     (sp + 3 * 8));
935         m     = (methodinfo *) *((ptrint *) (sp + 2 * 8));
936
937         /* resolve native function */
938
939         if (!(f = native_resolve_function(m)))
940                 return false;
941
942         /* patch back original code */
943
944         *((u8 *) ra) = mcode;
945
946         /* if we show disassembly, we have to skip the nop's */
947
948         if (opt_shownops)
949                 ra = ra + 5;
950
951         /* patch native function pointer */
952
953         *((ptrint *) (ra + 2)) = (ptrint) f;
954
955         return true;
956 }
957 #endif /* !defined(WITH_STATIC_CLASSPATH) */
958
959
960 /*
961  * These are local overrides for various environment variables in Emacs.
962  * Please do not remove this and leave it at the end of the file, where
963  * Emacs will automagically detect them.
964  * ---------------------------------------------------------------------
965  * Local variables:
966  * mode: c
967  * indent-tabs-mode: t
968  * c-basic-offset: 4
969  * tab-width: 4
970  * End:
971  * vim:noexpandtab:sw=4:ts=4:
972  */