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