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