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