Renamed *_checkarraycast to *_arraycheckcast.
[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 2448 2005-05-11 13:03:20Z twisti $
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         /* handle special case when the base register is %r12 */
333
334         if (*(ra + 2) == 0x84)
335                 ra = ra + 1;
336
337         /* patch the field's offset */
338
339         if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
340                 *((u4 *) (ra + 3)) = (u4) (fi->offset);
341                 *((u4 *) (ra + 11 + 3)) = (u4) (fi->offset + 4);
342
343         } else {
344                 *((u4 *) (ra + 3)) = (u4) (fi->offset);
345         }
346
347
348 #if defined(USE_THREADS)
349         /* this position has been patched */
350
351         o->vftbl = (vftbl_t *) 1;
352
353         /* leave the monitor on the patching position */
354
355         builtin_monitorexit(o);
356 #endif
357         *dontfillinexceptionstacktrace=false;
358
359         return true;
360 }
361
362
363 /* patcher_builtin_new *********************************************************
364
365    Machine code:
366
367    48 bf a0 f0 92 00 00 00 00 00    mov    $0x92f0a0,%rdi
368    <patched call position>
369    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
370    48 ff d0                         callq  *%rax
371
372 *******************************************************************************/
373
374 bool patcher_builtin_new(u1 *sp)
375 {
376         u1                *ra;
377         java_objectheader *o;
378         u8                 mcode;
379         constant_classref *cr;
380         classinfo         *c;
381         void              *beginJavaStack;
382         /* get stuff from the stack */
383
384         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
385         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
386         mcode =                       *((u8 *)     (sp + 1 * 8));
387         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
388         beginJavaStack =              (void*) (sp+3*8);
389
390         /* calculate and set the new return address */
391
392         ra = ra - (10 + 5);
393         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
394
395         *dontfillinexceptionstacktrace=true;
396
397 #if defined(USE_THREADS)
398         /* enter a monitor on the patching position */
399
400         builtin_monitorenter(o);
401
402         /* check if the position has already been patched */
403
404         if (o->vftbl) {
405                 builtin_monitorexit(o);
406                 *dontfillinexceptionstacktrace=false;
407                 return true;
408         }
409 #endif
410
411         /* get the classinfo */
412
413         if (!(c = helper_resolve_classinfo(cr))) {
414                 *dontfillinexceptionstacktrace=false;
415                 /*should here be an monitorexit too ?*/
416                 return false;
417         }
418
419         *dontfillinexceptionstacktrace=false;
420         /*printf("ra:%p\n",ra);*/
421         if (!helper_initialize_class(beginJavaStack,c,ra+5)) return false;
422
423         /* patch back original code */
424
425         *((u8 *) (ra + 10)) = mcode;
426
427         /* patch the classinfo pointer */
428
429         *((ptrint *) (ra + 2)) = (ptrint) c;
430
431         /* if we show disassembly, we have to skip the nop's */
432
433         if (showdisassemble)
434                 ra = ra + 5;
435
436         /* patch new function address */
437
438         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_new;
439
440
441 #if defined(USE_THREADS)
442         /* this position has been patched */
443
444         o->vftbl = (vftbl_t *) 1;
445
446         /* leave the monitor on the patching position */
447         *dontfillinexceptionstacktrace=true;
448         builtin_monitorexit(o);
449         *dontfillinexceptionstacktrace=false;
450
451 #endif
452
453         return true;
454 }
455
456
457 /* patcher_builtin_newarray ****************************************************
458
459    Machine code:
460
461    48 be 88 13 9b 00 00 00 00 00    mov    $0x9b1388,%rsi
462    <patched call position>
463    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
464    48 ff d0                         callq  *%rax
465
466 *******************************************************************************/
467
468 bool patcher_builtin_newarray(u1 *sp)
469 {
470         u1                *ra;
471         java_objectheader *o;
472         u8                 mcode;
473         constant_classref *cr;
474         classinfo         *c;
475
476         /* get stuff from the stack */
477
478         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
479         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
480         mcode =                       *((u8 *)     (sp + 1 * 8));
481         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
482
483         /* calculate and set the new return address */
484
485         ra = ra - (10 + 5);
486         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
487
488         *dontfillinexceptionstacktrace=true;
489
490 #if defined(USE_THREADS)
491         /* enter a monitor on the patching position */
492
493         builtin_monitorenter(o);
494
495         /* check if the position has already been patched */
496
497         if (o->vftbl) {
498                 builtin_monitorexit(o);
499                 *dontfillinexceptionstacktrace=false;
500                 return true;
501         }
502 #endif
503
504         /* get the classinfo */
505
506         if (!(c = helper_resolve_classinfo(cr))) {
507                 *dontfillinexceptionstacktrace=false;
508                 return false;
509         }
510
511         /* patch back original code */
512
513         *((u8 *) (ra + 10)) = mcode;
514
515         /* patch the class' vftbl pointer */
516
517         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
518
519         /* if we show disassembly, we have to skip the nop's */
520
521         if (showdisassemble)
522                 ra = ra + 5;
523
524         /* patch new function address */
525
526         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_newarray;
527
528
529 #if defined(USE_THREADS)
530         /* this position has been patched */
531
532         o->vftbl = (vftbl_t *) 1;
533
534         /* leave the monitor on the patching position */
535
536         builtin_monitorexit(o);
537
538 #endif
539         *dontfillinexceptionstacktrace=false;
540
541         return true;
542 }
543
544
545 /* patcher_builtin_multianewarray **********************************************
546
547    Machine code:
548
549    <patched call position>
550    48 bf 02 00 00 00 00 00 00 00    mov    $0x2,%rdi
551    48 be 30 40 b2 00 00 00 00 00    mov    $0xb24030,%rsi
552    48 89 e2                         mov    %rsp,%rdx
553    48 b8 7c 96 4b 00 00 00 00 00    mov    $0x4b967c,%rax
554    48 ff d0                         callq  *%rax
555
556 *******************************************************************************/
557
558 bool patcher_builtin_multianewarray(u1 *sp)
559 {
560         u1                *ra;
561         java_objectheader *o;
562         u8                 mcode;
563         constant_classref *cr;
564         classinfo         *c;
565
566         /* get stuff from the stack */
567
568         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
569         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
570         mcode =                       *((u8 *)     (sp + 1 * 8));
571         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
572
573         /* calculate and set the new return address */
574
575         ra = ra - 5;
576         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
577
578         *dontfillinexceptionstacktrace=true;
579
580 #if defined(USE_THREADS)
581         /* enter a monitor on the patching position */
582
583         builtin_monitorenter(o);
584
585         /* check if the position has already been patched */
586
587         if (o->vftbl) {
588                 builtin_monitorexit(o);
589                 *dontfillinexceptionstacktrace=false;
590                 return true;
591         }
592 #endif
593
594         /* get the classinfo */
595
596         if (!(c = helper_resolve_classinfo(cr))) {
597                 *dontfillinexceptionstacktrace=false;
598                 return false;
599         }
600
601         /* patch back original code */
602
603         *((u8 *) ra) = mcode;
604
605         /* if we show disassembly, we have to skip the nop's */
606
607         if (showdisassemble)
608                 ra = ra + 5;
609
610         /* patch the class' vftbl pointer */
611
612         *((ptrint *) (ra + 10 + 2)) = (ptrint) c->vftbl;
613
614         /* patch new function address */
615
616         *((ptrint *) (ra + 10 + 10 + 3 + 2)) = (ptrint) BUILTIN_multianewarray;
617
618
619 #if defined(USE_THREADS)
620         /* this position has been patched */
621
622         o->vftbl = (vftbl_t *) 1;
623
624         /* leave the monitor on the patching position */
625
626         builtin_monitorexit(o);
627 #endif
628         *dontfillinexceptionstacktrace=false;
629
630         return true;
631 }
632
633
634 /* patcher_builtin_arraycheckcast **********************************************
635
636    Machine code:
637
638    48 be b8 3f b2 00 00 00 00 00    mov    $0xb23fb8,%rsi
639    <patched call position>
640    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
641    48 ff d0                         callq  *%rax
642
643 *******************************************************************************/
644
645 bool patcher_builtin_arraycheckcast(u1 *sp)
646 {
647         u1                *ra;
648         java_objectheader *o;
649         u8                 mcode;
650         constant_classref *cr;
651         classinfo         *c;
652
653         /* get stuff from the stack */
654
655         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
656         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
657         mcode =                       *((u8 *)     (sp + 1 * 8));
658         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
659
660         /* calculate and set the new return address */
661
662         ra = ra - (10 + 5);
663         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
664
665         *dontfillinexceptionstacktrace=true;
666
667 #if defined(USE_THREADS)
668         /* enter a monitor on the patching position */
669
670         builtin_monitorenter(o);
671
672         /* check if the position has already been patched */
673
674         if (o->vftbl) {
675                 builtin_monitorexit(o);
676                 *dontfillinexceptionstacktrace=false;
677                 return true;
678         }
679 #endif
680
681         /* get the classinfo */
682
683         if (!(c = helper_resolve_classinfo(cr))) {
684                 *dontfillinexceptionstacktrace=false;
685                 return false;
686         }
687
688         /* patch back original code */
689
690         *((u8 *) (ra + 10)) = mcode;
691
692         /* patch the class' vftbl pointer */
693
694         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
695
696         /* if we show disassembly, we have to skip the nop's */
697
698         if (showdisassemble)
699                 ra = ra + 5;
700
701         /* patch new function address */
702
703         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_arraycheckcast;
704
705
706 #if defined(USE_THREADS)
707         /* this position has been patched */
708
709         o->vftbl = (vftbl_t *) 1;
710
711         /* leave the monitor on the patching position */
712
713         builtin_monitorexit(o);
714 #endif
715         *dontfillinexceptionstacktrace=false;
716         return true;
717 }
718
719
720 /* patcher_builtin_arrayinstanceof *********************************************
721
722    Machine code:
723
724    48 be 30 3c b2 00 00 00 00 00    mov    $0xb23c30,%rsi
725    <patched call position>
726    48 b8 00 00 00 00 00 00 00 00    mov    $0x0,%rax
727    48 ff d0                         callq  *%rax
728
729 *******************************************************************************/
730
731 bool patcher_builtin_arrayinstanceof(u1 *sp)
732 {
733         u1                *ra;
734         java_objectheader *o;
735         u8                 mcode;
736         constant_classref *cr;
737         classinfo         *c;
738
739         /* get stuff from the stack */
740
741         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
742         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
743         mcode =                       *((u8 *)     (sp + 1 * 8));
744         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
745
746         /* calculate and set the new return address */
747
748         ra = ra - (10 + 5);
749         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
750
751         *dontfillinexceptionstacktrace=true;
752
753 #if defined(USE_THREADS)
754         /* enter a monitor on the patching position */
755
756         builtin_monitorenter(o);
757
758         /* check if the position has already been patched */
759
760         if (o->vftbl) {
761                 builtin_monitorexit(o);
762
763                 return true;
764         }
765 #endif
766
767         /* get the classinfo */
768
769         if (!(c = helper_resolve_classinfo(cr))) {
770                 *dontfillinexceptionstacktrace=false;
771                 return false;
772         }
773
774         /* patch back original code */
775
776         *((u8 *) (ra + 10)) = mcode;
777
778         /* patch the class' vftbl pointer */
779
780         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
781
782         /* if we show disassembly, we have to skip the nop's */
783
784         if (showdisassemble)
785                 ra = ra + 5;
786
787         /* patch new function address */
788
789         *((ptrint *) (ra + 10 + 2)) = (ptrint) BUILTIN_arrayinstanceof;
790
791
792 #if defined(USE_THREADS)
793         /* this position has been patched */
794
795         o->vftbl = (vftbl_t *) 1;
796
797         /* leave the monitor on the patching position */
798
799         builtin_monitorexit(o);
800 #endif
801         *dontfillinexceptionstacktrace=false;
802         return true;
803 }
804
805
806 /* patcher_invokestatic_special ************************************************
807
808    XXX
809
810 *******************************************************************************/
811
812 bool patcher_invokestatic_special(u1 *sp)
813 {
814         u1                *ra;
815         java_objectheader *o;
816         u8                 mcode;
817         unresolved_method *um;
818         methodinfo        *m;
819
820         /* get stuff from the stack */
821
822         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
823         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
824         mcode =                       *((u8 *)     (sp + 1 * 8));
825         um    = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
826
827         /* calculate and set the new return address */
828
829         ra = ra - 5;
830         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
831
832         *dontfillinexceptionstacktrace=true;
833
834 #if defined(USE_THREADS)
835         /* enter a monitor on the patching position */
836
837         builtin_monitorenter(o);
838
839         /* check if the position has already been patched */
840
841         if (o->vftbl) {
842                 builtin_monitorexit(o);
843                 *dontfillinexceptionstacktrace=false;
844                 return true;
845         }
846 #endif
847
848         /* get the fieldinfo */
849
850         if (!(m = helper_resolve_methodinfo(um))) {
851                 *dontfillinexceptionstacktrace=false;
852                 return false;
853         }
854         /* patch back original code */
855
856         *((u8 *) ra) = mcode;
857
858         /* if we show disassembly, we have to skip the nop's */
859
860         if (showdisassemble)
861                 ra = ra + 5;
862
863         /* patch stubroutine */
864
865         *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine;
866
867
868 #if defined(USE_THREADS)
869         /* this position has been patched */
870
871         o->vftbl = (vftbl_t *) 1;
872
873         /* leave the monitor on the patching position */
874
875         builtin_monitorexit(o);
876 #endif
877         *dontfillinexceptionstacktrace=false;
878         return true;
879 }
880
881
882 /* patcher_invokevirtual *******************************************************
883
884    XXX
885
886 *******************************************************************************/
887
888 bool patcher_invokevirtual(u1 *sp)
889 {
890         u1                *ra;
891         java_objectheader *o;
892         u8                 mcode;
893         unresolved_method *um;
894         methodinfo        *m;
895
896         /* get stuff from the stack */
897
898         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
899         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
900         mcode =                       *((u8 *)     (sp + 1 * 8));
901         um    = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
902
903         /* calculate and set the new return address */
904
905         ra = ra - 5;
906         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
907
908         *dontfillinexceptionstacktrace=true;
909
910 #if defined(USE_THREADS)
911         /* enter a monitor on the patching position */
912
913         builtin_monitorenter(o);
914
915         /* check if the position has already been patched */
916
917         if (o->vftbl) {
918                 builtin_monitorexit(o);
919                 *dontfillinexceptionstacktrace=false;
920                 return true;
921         }
922 #endif
923
924         /* get the fieldinfo */
925
926         if (!(m = helper_resolve_methodinfo(um))) {
927                 *dontfillinexceptionstacktrace=false;
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 vftbl index */
941
942         *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, table[0]) +
943                                                                    sizeof(methodptr) * m->vftblindex);
944
945
946 #if defined(USE_THREADS)
947         /* this position has been patched */
948
949         o->vftbl = (vftbl_t *) 1;
950
951         /* leave the monitor on the patching position */
952
953         builtin_monitorexit(o);
954 #endif
955         *dontfillinexceptionstacktrace=false;
956         return true;
957 }
958
959
960 /* patcher_invokeinterface *****************************************************
961
962    XXX
963
964 *******************************************************************************/
965
966 bool patcher_invokeinterface(u1 *sp)
967 {
968         u1                *ra;
969         java_objectheader *o;
970         u8                 mcode;
971         unresolved_method *um;
972         methodinfo        *m;
973
974         /* get stuff from the stack */
975
976         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
977         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
978         mcode =                       *((u8 *)     (sp + 1 * 8));
979         um    = (unresolved_method *) *((ptrint *) (sp + 0 * 8));
980
981         /* calculate and set the new return address */
982
983         ra = ra - 5;
984         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
985
986         *dontfillinexceptionstacktrace=true;
987
988 #if defined(USE_THREADS)
989         /* enter a monitor on the patching position */
990
991         builtin_monitorenter(o);
992
993         /* check if the position has already been patched */
994
995         if (o->vftbl) {
996                 builtin_monitorexit(o);
997                 *dontfillinexceptionstacktrace=true;
998                 return true;
999         }
1000 #endif
1001
1002         /* get the fieldinfo */
1003
1004         if (!(m = helper_resolve_methodinfo(um))) {
1005                 *dontfillinexceptionstacktrace=false;
1006                 return false;
1007         }
1008
1009         /* patch back original code */
1010
1011         *((u8 *) ra) = mcode;
1012
1013         /* if we show disassembly, we have to skip the nop's */
1014
1015         if (showdisassemble)
1016                 ra = ra + 5;
1017
1018         /* patch interfacetable index */
1019
1020         *((s4 *) (ra + 3 + 3)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
1021                                                                    sizeof(methodptr) * m->class->index);
1022
1023         /* patch method offset */
1024
1025         *((s4 *) (ra + 3 + 7 + 3)) =
1026                 (s4) (sizeof(methodptr) * (m - m->class->methods));
1027
1028
1029 #if defined(USE_THREADS)
1030         /* this position has been patched */
1031
1032         o->vftbl = (vftbl_t *) 1;
1033
1034         /* leave the monitor on the patching position */
1035
1036         builtin_monitorexit(o);
1037 #endif
1038         *dontfillinexceptionstacktrace=false;
1039         return true;
1040 }
1041
1042
1043 /* patcher_checkcast_instanceof_flags ******************************************
1044
1045    XXX
1046
1047 *******************************************************************************/
1048
1049 bool patcher_checkcast_instanceof_flags(u1 *sp)
1050 {
1051         u1                *ra;
1052         java_objectheader *o;
1053         u8                 mcode;
1054         constant_classref *cr;
1055         classinfo         *c;
1056
1057         /* get stuff from the stack */
1058
1059         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
1060         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
1061         mcode =                       *((u8 *)     (sp + 1 * 8));
1062         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
1063
1064         /* calculate and set the new return address */
1065
1066         ra = ra - 5;
1067         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
1068
1069         *dontfillinexceptionstacktrace=true;
1070
1071 #if defined(USE_THREADS)
1072         /* enter a monitor on the patching position */
1073
1074         builtin_monitorenter(o);
1075
1076         /* check if the position has already been patched */
1077
1078         if (o->vftbl) {
1079                 builtin_monitorexit(o);
1080                 *dontfillinexceptionstacktrace=false;
1081                 return true;
1082         }
1083 #endif
1084
1085         /* get the fieldinfo */
1086
1087         if (!(c = helper_resolve_classinfo(cr))) {
1088                 *dontfillinexceptionstacktrace=false;
1089                 return false;
1090         }
1091
1092         /* patch back original code */
1093
1094         *((u8 *) ra) = mcode;
1095
1096         /* if we show disassembly, we have to skip the nop's */
1097
1098         if (showdisassemble)
1099                 ra = ra + 5;
1100
1101         /* patch class flags */
1102
1103         *((s4 *) (ra + 2)) = (s4) c->flags;
1104
1105
1106 #if defined(USE_THREADS)
1107         /* this position has been patched */
1108
1109         o->vftbl = (vftbl_t *) 1;
1110
1111         /* leave the monitor on the patching position */
1112
1113         builtin_monitorexit(o);
1114 #endif
1115         *dontfillinexceptionstacktrace=false;
1116         return true;
1117 }
1118
1119
1120 /* patcher_checkcast_instanceof_interface **************************************
1121
1122    XXX
1123
1124 *******************************************************************************/
1125
1126 bool patcher_checkcast_instanceof_interface(u1 *sp)
1127 {
1128         u1                *ra;
1129         java_objectheader *o;
1130         u8                 mcode;
1131         constant_classref *cr;
1132         classinfo         *c;
1133
1134         /* get stuff from the stack */
1135
1136         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
1137         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
1138         mcode =                       *((u8 *)     (sp + 1 * 8));
1139         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
1140
1141         /* calculate and set the new return address */
1142
1143         ra = ra - 5;
1144         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
1145
1146         *dontfillinexceptionstacktrace=true;
1147
1148 #if defined(USE_THREADS)
1149         /* enter a monitor on the patching position */
1150
1151         builtin_monitorenter(o);
1152
1153         /* check if the position has already been patched */
1154
1155         if (o->vftbl) {
1156                 builtin_monitorexit(o);
1157                 *dontfillinexceptionstacktrace=false;
1158                 return true;
1159         }
1160 #endif
1161
1162         /* get the fieldinfo */
1163
1164         if (!(c = helper_resolve_classinfo(cr))) {
1165                 *dontfillinexceptionstacktrace=false;
1166                 return false;
1167         }
1168
1169         /* patch back original code */
1170
1171         *((u8 *) ra) = mcode;
1172
1173         /* if we show disassembly, we have to skip the nop's */
1174
1175         if (showdisassemble)
1176                 ra = ra + 5;
1177
1178         /* patch super class index */
1179
1180         *((s4 *) (ra + 7 + 3)) = (s4) c->index;
1181
1182         *((s4 *) (ra + 7 + 7 + 3 + 6 + 3)) =
1183                 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
1184                           c->index * sizeof(methodptr*));
1185
1186
1187 #if defined(USE_THREADS)
1188         /* this position has been patched */
1189
1190         o->vftbl = (vftbl_t *) 1;
1191
1192         /* leave the monitor on the patching position */
1193
1194         builtin_monitorexit(o);
1195 #endif
1196         *dontfillinexceptionstacktrace=false;
1197         return true;
1198 }
1199
1200
1201 /* patcher_checkcast_class *****************************************************
1202
1203    XXX
1204
1205 *******************************************************************************/
1206
1207 bool patcher_checkcast_class(u1 *sp)
1208 {
1209         u1                *ra;
1210         java_objectheader *o;
1211         u8                 mcode;
1212         constant_classref *cr;
1213         classinfo         *c;
1214
1215         /* get stuff from the stack */
1216
1217         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
1218         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
1219         mcode =                       *((u8 *)     (sp + 1 * 8));
1220         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
1221
1222         /* calculate and set the new return address */
1223
1224         ra = ra - 5;
1225         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
1226
1227         *dontfillinexceptionstacktrace=true;
1228
1229 #if defined(USE_THREADS)
1230         /* enter a monitor on the patching position */
1231
1232         builtin_monitorenter(o);
1233
1234         /* check if the position has already been patched */
1235
1236         if (o->vftbl) {
1237                 builtin_monitorexit(o);
1238                 *dontfillinexceptionstacktrace=false;
1239                 return true;
1240         }
1241 #endif
1242
1243         /* get the fieldinfo */
1244
1245         if (!(c = helper_resolve_classinfo(cr))) {
1246                 *dontfillinexceptionstacktrace=false;
1247                 return false;
1248         }
1249
1250         /* patch back original code */
1251
1252         *((u8 *) ra) = mcode;
1253
1254         /* if we show disassembly, we have to skip the nop's */
1255
1256         if (showdisassemble)
1257                 ra = ra + 5;
1258
1259         /* patch super class' vftbl */
1260
1261         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
1262         *((ptrint *) (ra + 10 + 7 + 7 + 3 + 2)) = (ptrint) c->vftbl;
1263
1264
1265 #if defined(USE_THREADS)
1266         /* this position has been patched */
1267
1268         o->vftbl = (vftbl_t *) 1;
1269
1270         /* leave the monitor on the patching position */
1271
1272         builtin_monitorexit(o);
1273 #endif
1274         *dontfillinexceptionstacktrace=false;
1275         return true;
1276 }
1277
1278
1279 /* patcher_instanceof_class ****************************************************
1280
1281    XXX
1282
1283 *******************************************************************************/
1284
1285 bool patcher_instanceof_class(u1 *sp)
1286 {
1287         u1                *ra;
1288         java_objectheader *o;
1289         u8                 mcode;
1290         constant_classref *cr;
1291         classinfo         *c;
1292
1293         /* get stuff from the stack */
1294
1295         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
1296         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
1297         mcode =                       *((u8 *)     (sp + 1 * 8));
1298         cr    = (constant_classref *) *((ptrint *) (sp + 0 * 8));
1299
1300         /* calculate and set the new return address */
1301
1302         ra = ra - 5;
1303         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
1304
1305         *dontfillinexceptionstacktrace=true;
1306
1307 #if defined(USE_THREADS)
1308         /* enter a monitor on the patching position */
1309
1310         builtin_monitorenter(o);
1311
1312         /* check if the position has already been patched */
1313
1314         if (o->vftbl) {
1315                 builtin_monitorexit(o);
1316                 *dontfillinexceptionstacktrace=false;
1317                 return true;
1318         }
1319 #endif
1320
1321         /* get the fieldinfo */
1322
1323         if (!(c = helper_resolve_classinfo(cr))) {
1324                 *dontfillinexceptionstacktrace=false;
1325                 return false;
1326         }
1327
1328         /* patch back original code */
1329
1330         *((u8 *) ra) = mcode;
1331
1332         /* if we show disassembly, we have to skip the nop's */
1333
1334         if (showdisassemble)
1335                 ra = ra + 5;
1336
1337         /* patch super class' vftbl */
1338
1339         *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
1340
1341
1342 #if defined(USE_THREADS)
1343         /* this position has been patched */
1344
1345         o->vftbl = (vftbl_t *) 1;
1346
1347         /* leave the monitor on the patching position */
1348
1349         builtin_monitorexit(o);
1350 #endif
1351         *dontfillinexceptionstacktrace=false;
1352         return true;
1353 }
1354
1355
1356 /* patcher_clinit **************************************************************
1357
1358    XXX
1359
1360 *******************************************************************************/
1361
1362 bool patcher_clinit(u1 *sp)
1363 {
1364         u1                *ra;
1365         java_objectheader *o;
1366         u8                 mcode;
1367         classinfo         *c;
1368         void              *beginJavaStack;
1369
1370         /* get stuff from the stack */
1371
1372         ra    = (u1 *)                *((ptrint *) (sp + 3 * 8));
1373         o     = (java_objectheader *) *((ptrint *) (sp + 2 * 8));
1374         mcode =                       *((u8 *)     (sp + 1 * 8));
1375         c     = (classinfo *)         *((ptrint *) (sp + 0 * 8));
1376
1377         beginJavaStack =      (void*) (sp + 3 * 8);
1378
1379         /*printf("beginJavaStack: %p, ra %p\n",beginJavaStack,ra);*/
1380         /* calculate and set the new return address */
1381
1382         ra = ra - 5;
1383         *((ptrint *) (sp + 3 * 8)) = (ptrint) ra;
1384
1385 #if defined(USE_THREADS)
1386         /* enter a monitor on the patching position */
1387
1388         builtin_monitorenter(o);
1389
1390         /* check if the position has already been patched */
1391
1392         if (o->vftbl) {
1393                 builtin_monitorexit(o);
1394                 *dontfillinexceptionstacktrace=false;
1395                 return true;
1396         }
1397 #endif
1398
1399         /* check if the class is initialized */
1400         *dontfillinexceptionstacktrace=false;
1401         if (!helper_initialize_class(beginJavaStack,c,ra)) return false;
1402
1403         /* patch back original code */
1404
1405         *((u8 *) ra) = mcode;
1406
1407 #if defined(USE_THREADS)
1408         /* this position has been patched */
1409
1410         o->vftbl = (vftbl_t *) 1;
1411
1412         /* leave the monitor on the patching position */
1413         *dontfillinexceptionstacktrace=true;
1414         builtin_monitorexit(o);
1415         *dontfillinexceptionstacktrace=false;
1416
1417 #endif
1418
1419         return true;
1420 }
1421
1422
1423 /*
1424  * These are local overrides for various environment variables in Emacs.
1425  * Please do not remove this and leave it at the end of the file, where
1426  * Emacs will automagically detect them.
1427  * ---------------------------------------------------------------------
1428  * Local variables:
1429  * mode: c
1430  * indent-tabs-mode: t
1431  * c-basic-offset: 4
1432  * tab-width: 4
1433  * End:
1434  * vim:noexpandtab:sw=4:ts=4:
1435  */