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