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