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