* src/vm/exceptions.h (exceptionptr): Removed.
[cacao.git] / src / vm / jit / i386 / patcher.c
1 /* src/vm/jit/i386/patcher.c - i386 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 7596 2007-03-28 21:05:53Z twisti $
26
27 */
28
29
30 #include "config.h"
31 #include "vm/types.h"
32
33 #include "vm/jit/i386/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 "vm/resolve.h"
50 #include "vmcore/references.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 + 6 * 4));
80         o   = (java_objectheader *) *((ptrint *) (sp + 4 * 4));
81         f   = (functionptr)         *((ptrint *) (sp + 0 * 4));
82
83         /* calculate and set the new return address */
84
85         xpc = xpc - PATCHER_CALL_SIZE;
86
87         *((ptrint *) (sp + 6 * 4)) = (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 + 7 * 4, 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    b8 00 00 00 00             mov    $0x00000000,%eax
135
136 *******************************************************************************/
137
138 bool patcher_get_putstatic(u1 *sp)
139 {
140         u1               *ra;
141         u8                mcode;
142         unresolved_field *uf;
143         fieldinfo        *fi;
144
145         /* get stuff from the stack */
146
147         ra    = (u1 *)               *((ptrint *) (sp + 6 * 4));
148         mcode =                      *((u8 *)     (sp + 2 * 4));
149         uf    = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
150
151         /* get the fieldinfo */
152
153         if (!(fi = resolve_field_eager(uf)))
154                 return false;
155
156         /* check if the field's class is initialized */
157
158         if (!(fi->class->state & CLASS_INITIALIZED))
159                 if (!initialize_class(fi->class))
160                         return false;
161
162         /* patch back original code */
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_shownops)
170                 ra = ra + 5;
171
172         /* patch the field value's address */
173
174         *((ptrint *) (ra + 1)) = (ptrint) &(fi->value);
175
176         return true;
177 }
178
179
180 /* patcher_getfield ************************************************************
181
182    Machine code:
183
184    <patched call position>
185    8b 88 00 00 00 00          mov    0x00000000(%eax),%ecx
186
187 *******************************************************************************/
188
189 bool patcher_getfield(u1 *sp)
190 {
191         u1               *ra;
192         u8                mcode;
193         unresolved_field *uf;
194         fieldinfo        *fi;
195
196         /* get stuff from the stack */
197
198         ra    = (u1 *)               *((ptrint *) (sp + 6 * 4));
199         mcode =                      *((u8 *)     (sp + 2 * 4));
200         uf    = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
201
202         /* get the fieldinfo */
203
204         if (!(fi = resolve_field_eager(uf)))
205                 return false;
206
207         /* patch back original code */
208
209         *((u4 *) (ra + 0)) = (u4) mcode;
210         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
211
212         /* if we show disassembly, we have to skip the nop's */
213
214         if (opt_shownops)
215                 ra = ra + 5;
216
217         /* patch the field's offset */
218
219         *((u4 *) (ra + 2)) = (u4) (fi->offset);
220
221         /* if the field has type long, we need to patch the second move too */
222
223         if (fi->type == TYPE_LNG)
224                 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
225
226         return true;
227 }
228
229
230 /* patcher_putfield ************************************************************
231
232    Machine code:
233
234    <patched call position>
235    8b 88 00 00 00 00          mov    0x00000000(%eax),%ecx
236
237 *******************************************************************************/
238
239 bool patcher_putfield(u1 *sp)
240 {
241         u1               *ra;
242         u8                mcode;
243         unresolved_field *uf;
244         fieldinfo        *fi;
245
246         /* get stuff from the stack */
247
248         ra    = (u1 *)               *((ptrint *) (sp + 6 * 4));
249         mcode =                      *((u8 *)     (sp + 2 * 4));
250         uf    = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
251
252         /* get the fieldinfo */
253
254         if (!(fi = resolve_field_eager(uf)))
255                 return false;
256
257         /* patch back original code */
258
259         *((u4 *) (ra + 0)) = (u4) mcode;
260         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
261
262         /* if we show disassembly, we have to skip the nop's */
263
264         if (opt_shownops)
265                 ra = ra + 5;
266
267         /* patch the field's offset */
268
269         if (fi->type != TYPE_LNG) {
270                 *((u4 *) (ra + 2)) = (u4) (fi->offset);
271         }
272         else {
273                 /* The long code is special:
274                  *
275                  * 89 8d 00 00 00 00          mov    %ecx,0x00000000(%ebp)
276                  * 89 95 00 00 00 00          mov    %edx,0x00000000(%ebp)
277                  */
278
279                 *((u4 *) (ra + 2))     = (u4) (fi->offset);
280                 *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
281         }
282
283         return true;
284 }
285
286
287 /* patcher_putfieldconst *******************************************************
288
289    Machine code:
290
291    <patched call position>
292    c7 85 00 00 00 00 7b 00 00 00    movl   $0x7b,0x0(%ebp)
293
294 *******************************************************************************/
295
296 bool patcher_putfieldconst(u1 *sp)
297 {
298         u1               *ra;
299         u8                mcode;
300         unresolved_field *uf;
301         fieldinfo        *fi;
302
303         /* get stuff from the stack */
304
305         ra    = (u1 *)               *((ptrint *) (sp + 6 * 4));
306         mcode =                      *((u8 *)     (sp + 2 * 4));
307         uf    = (unresolved_field *) *((ptrint *) (sp + 1 * 4));
308
309         /* get the fieldinfo */
310
311         if (!(fi = resolve_field_eager(uf)))
312                 return false;
313
314         /* patch back original code */
315
316         *((u4 *) (ra + 0)) = (u4) mcode;
317         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
318
319         /* if we show disassembly, we have to skip the nop's */
320
321         if (opt_shownops)
322                 ra = ra + 5;
323
324         /* patch the field's offset */
325
326         if (!IS_2_WORD_TYPE(fi->type)) {
327                 *((u4 *) (ra + 2)) = (u4) (fi->offset);
328         }
329         else {
330                 /* long/double code is different:
331                  *
332                  * c7 80 00 00 00 00 c8 01 00 00    movl   $0x1c8,0x0(%eax)
333                  * c7 80 04 00 00 00 00 00 00 00    movl   $0x0,0x4(%eax)
334                  */
335
336                 *((u4 *) (ra + 2))      = (u4) (fi->offset);
337                 *((u4 *) (ra + 10 + 2)) = (u4) (fi->offset + 4);
338         }
339
340         return true;
341 }
342
343
344 /* patcher_aconst **************************************************************
345
346    Machine code:
347
348    <patched call postition>
349    c7 04 24 00 00 00 00       movl   $0x0000000,(%esp)
350    b8 00 00 00 00             mov    $0x0000000,%eax
351
352 *******************************************************************************/
353
354 bool patcher_aconst(u1 *sp)
355 {
356         u1                *ra;
357         u8                 mcode;
358         constant_classref *cr;
359         classinfo         *c;
360
361         /* get stuff from the stack */
362
363         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
364         mcode =                       *((u8 *)     (sp + 2 * 4));
365         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
366
367         /* get the classinfo */
368
369         if (!(c = resolve_classref_eager(cr)))
370                 return false;
371
372         /* patch back original code */
373
374         *((u4 *) (ra + 0)) = (u4) mcode;
375         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
376
377         /* if we show disassembly, we have to skip the nop's */
378
379         if (opt_shownops)
380                 ra = ra + 5;
381
382         /* patch the classinfo pointer */
383
384         *((ptrint *) (ra + 1)) = (ptrint) c;
385
386         return true;
387 }
388
389
390 /* patcher_builtin_multianewarray **********************************************
391
392    Machine code:
393
394    <patched call position>
395    c7 04 24 02 00 00 00       movl   $0x2,(%esp)
396    c7 44 24 04 00 00 00 00    movl   $0x00000000,0x4(%esp)
397    89 e0                      mov    %esp,%eax
398    83 c0 0c                   add    $0xc,%eax
399    89 44 24 08                mov    %eax,0x8(%esp)
400    b8 00 00 00 00             mov    $0x00000000,%eax
401    ff d0                      call   *%eax
402
403 *******************************************************************************/
404
405 bool patcher_builtin_multianewarray(u1 *sp)
406 {
407         u1                *ra;
408         u8                 mcode;
409         constant_classref *cr;
410         classinfo         *c;
411
412         /* get stuff from the stack */
413
414         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
415         mcode =                       *((u8 *)     (sp + 2 * 4));
416         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
417
418         /* get the classinfo */
419
420         if (!(c = resolve_classref_eager(cr)))
421                 return false;
422
423         /* patch back original code */
424
425         *((u4 *) (ra + 0)) = (u4) mcode;
426         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
427
428         /* if we show disassembly, we have to skip the nop's */
429
430         if (opt_shownops)
431                 ra = ra + 5;
432
433         /* patch the classinfo pointer */
434
435         *((ptrint *) (ra + 7 + 4)) = (ptrint) c;
436
437         /* patch new function address */
438
439         *((ptrint *) (ra + 7 + 8 + 2 + 3 + 4 + 1)) =
440                 (ptrint) BUILTIN_multianewarray;
441
442         return true;
443 }
444
445
446 /* patcher_builtin_arraycheckcast **********************************************
447
448    Machine code:
449
450    <patched call position>
451    c7 44 24 04 00 00 00 00    movl   $0x00000000,0x4(%esp)
452    ba 00 00 00 00             mov    $0x00000000,%edx
453    ff d2                      call   *%edx
454
455 *******************************************************************************/
456
457 bool patcher_builtin_arraycheckcast(u1 *sp)
458 {
459         u1                *ra;
460         u8                 mcode;
461         constant_classref *cr;
462         classinfo         *c;
463
464         /* get stuff from the stack */
465
466         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
467         mcode =                       *((u8 *)     (sp + 2 * 4));
468         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
469
470         /* get the classinfo */
471
472         if (!(c = resolve_classref_eager(cr)))
473                 return false;
474
475         /* patch back original code */
476
477         *((u4 *) (ra + 0)) = (u4) mcode;
478         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
479
480         /* if we show disassembly, we have to skip the nop's */
481
482         if (opt_shownops)
483                 ra = ra + 5;
484
485         /* patch the classinfo pointer */
486
487         *((ptrint *) (ra + 4)) = (ptrint) c;
488
489         /* patch new function address */
490
491         *((ptrint *) (ra + 8 + 1)) = (ptrint) BUILTIN_arraycheckcast;
492
493         return true;
494 }
495
496
497 /* patcher_invokestatic_special ************************************************
498
499    Machine code:
500
501    <patched call position>
502    b9 00 00 00 00             mov    $0x00000000,%ecx
503    ff d1                      call   *%ecx
504
505 *******************************************************************************/
506
507 bool patcher_invokestatic_special(u1 *sp)
508 {
509         u1                *ra;
510         u8                 mcode;
511         unresolved_method *um;
512         methodinfo        *m;
513
514         /* get stuff from the stack */
515
516         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
517         mcode =                       *((u8 *)     (sp + 2 * 4));
518         um    = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
519
520         /* get the fieldinfo */
521
522         if (!(m = resolve_method_eager(um)))
523                 return false;
524
525         /* patch back original code */
526
527         *((u4 *) (ra + 0)) = (u4) mcode;
528         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
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 stubroutine */
536
537         *((ptrint *) (ra + 1)) = (ptrint) m->stubroutine;
538
539         return true;
540 }
541
542
543 /* patcher_invokevirtual *******************************************************
544
545    Machine code:
546
547    <patched call position>
548    8b 08                      mov    (%eax),%ecx
549    8b 81 00 00 00 00          mov    0x00000000(%ecx),%eax
550    ff d0                      call   *%eax
551
552 *******************************************************************************/
553
554 bool patcher_invokevirtual(u1 *sp)
555 {
556         u1                *ra;
557         u8                 mcode;
558         unresolved_method *um;
559         methodinfo        *m;
560
561         /* get stuff from the stack */
562
563         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
564         mcode =                       *((u8 *)     (sp + 2 * 4));
565         um    = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
566
567         /* get the fieldinfo */
568
569         if (!(m = resolve_method_eager(um)))
570                 return false;
571
572         /* patch back original code */
573
574         *((u4 *) (ra + 0)) = (u4) mcode;
575         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
576
577         /* if we show disassembly, we have to skip the nop's */
578
579         if (opt_shownops)
580                 ra = ra + 5;
581
582         /* patch vftbl index */
583
584         *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, table[0]) +
585                                                                    sizeof(methodptr) * m->vftblindex);
586
587         return true;
588 }
589
590
591 /* patcher_invokeinterface *****************************************************
592
593    Machine code:
594
595    <patched call position>
596    8b 00                      mov    (%eax),%eax
597    8b 88 00 00 00 00          mov    0x00000000(%eax),%ecx
598    8b 81 00 00 00 00          mov    0x00000000(%ecx),%eax
599    ff d0                      call   *%eax
600
601 *******************************************************************************/
602
603 bool patcher_invokeinterface(u1 *sp)
604 {
605         u1                *ra;
606         u8                 mcode;
607         unresolved_method *um;
608         methodinfo        *m;
609
610         /* get stuff from the stack */
611
612         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
613         mcode =                       *((u8 *)     (sp + 2 * 4));
614         um    = (unresolved_method *) *((ptrint *) (sp + 1 * 4));
615
616         /* get the fieldinfo */
617
618         if (!(m = resolve_method_eager(um)))
619                 return false;
620
621         /* patch back original code */
622
623         *((u4 *) (ra + 0)) = (u4) mcode;
624         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
625
626         /* if we show disassembly, we have to skip the nop's */
627
628         if (opt_shownops)
629                 ra = ra + 5;
630
631         /* patch interfacetable index */
632
633         *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
634                                                                    sizeof(methodptr) * m->class->index);
635
636         /* patch method offset */
637
638         *((s4 *) (ra + 2 + 6 + 2)) =
639                 (s4) (sizeof(methodptr) * (m - m->class->methods));
640
641         return true;
642 }
643
644
645 /* patcher_checkcast_instanceof_flags ******************************************
646
647    Machine code:
648
649    <patched call position>
650    b9 00 00 00 00             mov    $0x00000000,%ecx
651
652 *******************************************************************************/
653
654 bool patcher_checkcast_instanceof_flags(u1 *sp)
655 {
656         u1                *ra;
657         u8                 mcode;
658         constant_classref *cr;
659         classinfo         *c;
660
661         /* get stuff from the stack */
662
663         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
664         mcode =                       *((u8 *)     (sp + 2 * 4));
665         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
666
667         /* get the fieldinfo */
668
669         if (!(c = resolve_classref_eager(cr)))
670                 return false;
671
672         /* patch back original code */
673
674         *((u4 *) (ra + 0)) = (u4) mcode;
675         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
676
677         /* if we show disassembly, we have to skip the nop's */
678
679         if (opt_shownops)
680                 ra = ra + 5;
681
682         /* patch class flags */
683
684         *((s4 *) (ra + 1)) = (s4) c->flags;
685
686         return true;
687 }
688
689
690 /* patcher_checkcast_interface *************************************************
691
692    Machine code:
693
694    <patched call position>
695    8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
696    81 ea 00 00 00 00          sub    $0x00000000,%edx
697    85 d2                      test   %edx,%edx
698    0f 8f 06 00 00 00          jg     0x00000000
699    8b 35 03 00 00 00          mov    0x3,%esi
700    8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
701
702 *******************************************************************************/
703
704 bool patcher_checkcast_interface(u1 *sp)
705 {
706         u1                *ra;
707         u8                 mcode;
708         constant_classref *cr;
709         classinfo         *c;
710
711         /* get stuff from the stack */
712
713         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
714         mcode =                       *((u8 *)     (sp + 2 * 4));
715         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
716
717         /* get the fieldinfo */
718
719         if (!(c = resolve_classref_eager(cr)))
720                 return false;
721
722         /* patch back original code */
723
724         *((u4 *) (ra + 0)) = (u4) mcode;
725         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
726
727         /* if we show disassembly, we have to skip the nop's */
728
729         if (opt_shownops)
730                 ra = ra + 5;
731
732         /* patch super class index */
733
734         *((s4 *) (ra + 6 + 2)) = (s4) c->index;
735
736         *((s4 *) (ra + 6 + 6 + 2 + 6 + 6 + 2)) =
737                 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
738                           c->index * sizeof(methodptr*));
739
740         return true;
741 }
742
743
744 /* patcher_instanceof_interface ************************************************
745
746    Machine code:
747
748    <patched call position>
749    8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
750    81 ea 00 00 00 00          sub    $0x00000000,%edx
751    85 d2                      test   %edx,%edx
752    0f 8e 13 00 00 00          jle    0x00000000
753    8b 91 00 00 00 00          mov    0x00000000(%ecx),%edx
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 + 6 * 4));
767         mcode =                       *((u8 *)     (sp + 2 * 4));
768         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
769
770         /* get the fieldinfo */
771
772         if (!(c = resolve_classref_eager(cr)))
773                 return false;
774
775         /* patch back original code */
776
777         *((u4 *) (ra + 0)) = (u4) mcode;
778         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
779
780         /* if we show disassembly, we have to skip the nop's */
781
782         if (opt_shownops)
783                 ra = ra + 5;
784
785         /* patch super class index */
786
787         *((s4 *) (ra + 6 + 2)) = (s4) c->index;
788
789         *((s4 *) (ra + 6 + 6 + 2 + 6 + 2)) =
790                 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
791                           c->index * sizeof(methodptr*));
792
793         return true;
794 }
795
796
797 /* patcher_checkcast_class *****************************************************
798
799    Machine code:
800
801    <patched call position>
802    ba 00 00 00 00             mov    $0x00000000,%edx
803    8b 89 00 00 00 00          mov    0x00000000(%ecx),%ecx
804    8b 92 00 00 00 00          mov    0x00000000(%edx),%edx
805    29 d1                      sub    %edx,%ecx
806    ba 00 00 00 00             mov    $0x00000000,%edx
807
808 *******************************************************************************/
809
810 bool patcher_checkcast_class(u1 *sp)
811 {
812         u1                *ra;
813         u8                 mcode;
814         constant_classref *cr;
815         classinfo         *c;
816
817         /* get stuff from the stack */
818
819         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
820         mcode =                       *((u8 *)     (sp + 2 * 4));
821         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
822
823         /* get the fieldinfo */
824
825         if (!(c = resolve_classref_eager(cr)))
826                 return false;
827
828         /* patch back original code */
829
830         *((u4 *) (ra + 0)) = (u4) mcode;
831         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
832
833         /* if we show disassembly, we have to skip the nop's */
834
835         if (opt_shownops)
836                 ra = ra + 5;
837
838         /* patch super class' vftbl */
839
840         *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
841         *((ptrint *) (ra + 5 + 6 + 6 + 2 + 1)) = (ptrint) c->vftbl;
842
843         return true;
844 }
845
846
847 /* patcher_instanceof_class ****************************************************
848
849    Machine code:
850
851    <patched call position>
852    b9 00 00 00 00             mov    $0x0,%ecx
853    8b 40 14                   mov    0x14(%eax),%eax
854    8b 51 18                   mov    0x18(%ecx),%edx
855    8b 49 14                   mov    0x14(%ecx),%ecx
856
857 *******************************************************************************/
858
859 bool patcher_instanceof_class(u1 *sp)
860 {
861         u1                *ra;
862         u8                 mcode;
863         constant_classref *cr;
864         classinfo         *c;
865
866         /* get stuff from the stack */
867
868         ra    = (u1 *)                *((ptrint *) (sp + 6 * 4));
869         mcode =                       *((u8 *)     (sp + 2 * 4));
870         cr    = (constant_classref *) *((ptrint *) (sp + 1 * 4));
871
872         /* get the fieldinfo */
873
874         if (!(c = resolve_classref_eager(cr)))
875                 return false;
876
877         /* patch back original code */
878
879         *((u4 *) (ra + 0)) = (u4) mcode;
880         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
881
882         /* if we show disassembly, we have to skip the nop's */
883
884         if (opt_shownops)
885                 ra = ra + 5;
886
887         /* patch super class' vftbl */
888
889         *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
890
891         return true;
892 }
893
894
895 /* patcher_clinit **************************************************************
896
897    Is used int PUT/GETSTATIC and native stub.
898
899    Machine code:
900
901    <patched call position>
902
903 *******************************************************************************/
904
905 bool patcher_clinit(u1 *sp)
906 {
907         u1        *ra;
908         u8         mcode;
909         classinfo *c;
910
911         /* get stuff from the stack */
912
913         ra    = (u1 *)        *((ptrint *) (sp + 6 * 4));
914         mcode =               *((u8 *)     (sp + 2 * 4));
915         c     = (classinfo *) *((ptrint *) (sp + 1 * 4));
916
917         /* check if the class is initialized */
918
919         if (!(c->state & CLASS_INITIALIZED))
920                 if (!initialize_class(c))
921                         return false;
922
923         /* patch back original code */
924
925         *((u4 *) (ra + 0)) = (u4) mcode;
926         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
927
928         return true;
929 }
930
931
932 /* patcher_athrow_areturn ******************************************************
933
934    Machine code:
935
936    <patched call position>
937
938 *******************************************************************************/
939
940 #ifdef ENABLE_VERIFIER
941 bool patcher_athrow_areturn(u1 *sp)
942 {
943         u1               *ra;
944         u8                mcode;
945         unresolved_class *uc;
946
947         /* get stuff from the stack */
948
949         ra    = (u1 *)               *((ptrint *) (sp + 6 * 4));
950         mcode =                      *((u8 *)     (sp + 2 * 4));
951         uc    = (unresolved_class *) *((ptrint *) (sp + 1 * 4));
952
953         /* resolve the class and check subtype constraints */
954
955         if (!resolve_class_eager_no_access_check(uc))
956                 return false;
957
958         /* patch back original code */
959
960         *((u4 *) (ra + 0)) = (u4) mcode;
961         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
962
963         return true;
964 }
965 #endif /* ENABLE_VERIFIER */
966
967
968 /* patcher_resolve_native ******************************************************
969
970    Is used in native stub.
971
972    Machine code:
973
974    <patched call position>
975    c7 44 24 04 28 90 01 40    movl   $0x40019028,0x4(%esp)
976
977 *******************************************************************************/
978
979 #if !defined(WITH_STATIC_CLASSPATH)
980 bool patcher_resolve_native(u1 *sp)
981 {
982         u1          *ra;
983         u8           mcode;
984         methodinfo  *m;
985         functionptr  f;
986
987         /* get stuff from the stack */
988
989         ra    = (u1 *)         *((ptrint *) (sp + 6 * 4));
990         mcode =                *((u8 *)     (sp + 2 * 4));
991         m     = (methodinfo *) *((ptrint *) (sp + 1 * 4));
992
993         /* resolve native function */
994
995         if (!(f = native_resolve_function(m)))
996                 return false;
997
998         /* patch back original code */
999
1000         *((u4 *) (ra + 0)) = (u4) mcode;
1001         *((u1 *) (ra + 4)) = (u1) (mcode >> 32);
1002
1003         /* if we show disassembly, we have to skip the nop's */
1004
1005         if (opt_shownops)
1006                 ra = ra + 5;
1007
1008         /* patch native function pointer */
1009
1010         *((ptrint *) (ra + 4)) = (ptrint) f;
1011
1012         return true;
1013 }
1014 #endif /* !defined(WITH_STATIC_CLASSPATH) */
1015
1016
1017 /*
1018  * These are local overrides for various environment variables in Emacs.
1019  * Please do not remove this and leave it at the end of the file, where
1020  * Emacs will automagically detect them.
1021  * ---------------------------------------------------------------------
1022  * Local variables:
1023  * mode: c
1024  * indent-tabs-mode: t
1025  * c-basic-offset: 4
1026  * tab-width: 4
1027  * End:
1028  * vim:noexpandtab:sw=4:ts=4:
1029  */