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