1 /* src/vm/jit/intrp/codegen.c - code generator for Interpreter
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Christian Thalinger
30 Changes: Edwin Steiner
32 $Id: codegen.c 5667 2006-10-04 15:14:19Z edwin $
44 #elif defined(WITH_FFCALL)
47 # error neither WITH_FFI nor WITH_FFCALL defined
54 #include "vm/jit/intrp/codegen.h"
55 #include "vm/jit/intrp/intrp.h"
57 #include "native/native.h"
58 #include "vm/builtin.h"
60 #include "vm/exceptions.h"
61 #include "vm/global.h"
62 #include "vm/options.h"
63 #include "vm/stringlocal.h"
65 #include "vm/jit/asmpart.h"
66 #include "vm/jit/codegen-common.h"
67 #include "vm/jit/dseg.h"
68 #include "vm/jit/jit.h"
69 #include "vm/jit/parse.h"
70 #include "vm/jit/patcher.h"
71 #include "vm/jit/stack.h"
74 #define gen_branch(_inst) { \
76 codegen_addreference(cd, BLOCK_OF(iptr->dst.insindex)); \
79 #define index2offset(_i) (-(_i) * SIZEOF_VOID_P)
81 /* functions used by cacao-gen.i */
83 void genarg_v(codegendata *cd1, Cell v)
85 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
86 *((Cell *) *mcodepp) = v;
90 void genarg_i(codegendata *cd1, s4 i)
92 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
93 *((Cell *) *mcodepp) = i;
97 void genarg_b(codegendata *cd1, s4 i)
102 void genarg_f(codegendata *cd1, float f)
110 void genarg_l(codegendata *cd1, s8 l)
112 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
113 vm_l2twoCell(l, ((Cell *) *mcodepp)[1], ((Cell *) *mcodepp)[0]);
117 void genarg_aRef(codegendata *cd1, java_objectheader *a)
119 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
120 *((java_objectheader **) *mcodepp) = a;
124 void genarg_aArray(codegendata *cd1, java_arrayheader *a)
126 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
127 *((java_arrayheader **) *mcodepp) = a;
131 void genarg_aaTarget(codegendata *cd1, Inst **a)
133 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
134 *((Inst ***) *mcodepp) = a;
138 void genarg_aClass(codegendata *cd1, classinfo *a)
140 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
141 *((classinfo **) *mcodepp) = a;
145 void genarg_acr(codegendata *cd1, constant_classref *a)
147 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
148 *((constant_classref **) *mcodepp) = a;
152 void genarg_addr(codegendata *cd1, u1 *a)
154 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
155 *((u1 **) *mcodepp) = a;
159 void genarg_af(codegendata *cd1, functionptr a)
161 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
162 *((functionptr *) *mcodepp) = a;
166 void genarg_afi(codegendata *cd1, fieldinfo *a)
168 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
169 *((fieldinfo **) *mcodepp) = a;
173 void genarg_am(codegendata *cd1, methodinfo *a)
175 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
176 *((methodinfo **) *mcodepp) = a;
180 void genarg_acell(codegendata *cd1, Cell *a)
182 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
183 *((Cell **) *mcodepp) = a;
187 void genarg_ainst(codegendata *cd1, Inst *a)
189 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
190 *((Inst **) *mcodepp) = a;
194 void genarg_auf(codegendata *cd1, unresolved_field *a)
196 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
197 *((unresolved_field **) *mcodepp) = a;
201 void genarg_aum(codegendata *cd1, unresolved_method *a)
203 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
204 *((unresolved_method **) *mcodepp) = a;
208 void genarg_avftbl(codegendata *cd1, vftbl_t *a)
210 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
211 *((vftbl_t **) *mcodepp) = a;
216 /* include the interpreter generation functions *******************************/
218 #include "vm/jit/intrp/java-gen.i"
221 typedef void (*genfunctionptr) (codegendata *);
223 typedef struct builtin_gen builtin_gen;
230 struct builtin_gen builtin_gen_table[] = {
231 {BUILTIN_new, gen_NEW, },
232 {BUILTIN_newarray, gen_NEWARRAY, },
233 {BUILTIN_newarray_boolean, gen_NEWARRAY_BOOLEAN,},
234 {BUILTIN_newarray_byte, gen_NEWARRAY_BYTE, },
235 {BUILTIN_newarray_char, gen_NEWARRAY_CHAR, },
236 {BUILTIN_newarray_short, gen_NEWARRAY_SHORT, },
237 {BUILTIN_newarray_int, gen_NEWARRAY_INT, },
238 {BUILTIN_newarray_long, gen_NEWARRAY_LONG, },
239 {BUILTIN_newarray_float, gen_NEWARRAY_FLOAT, },
240 {BUILTIN_newarray_double, gen_NEWARRAY_DOUBLE, },
241 {BUILTIN_arrayinstanceof, gen_ARRAYINSTANCEOF, },
243 #if defined(ENABLE_THREADS)
244 {LOCK_monitor_enter, gen_MONITORENTER, },
245 {LOCK_monitor_exit, gen_MONITOREXIT, },
248 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
249 {BUILTIN_f2l, gen_F2L, },
252 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
253 {BUILTIN_d2l, gen_D2L, },
256 #if !(SUPPORT_FLOAT && SUPPORT_F2I)
257 {BUILTIN_f2i, gen_F2I, },
260 #if !(SUPPORT_DOUBLE && SUPPORT_D2I)
261 {BUILTIN_d2i, gen_D2I, },
264 #if !SUPPORT_DIVISION
265 {BUILTIN_idiv, gen_IDIV, },
266 {BUILTIN_irem, gen_IREM, },
269 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
270 {BUILTIN_ldiv, gen_LDIV, },
271 {BUILTIN_lrem, gen_LREM, },
274 {BUILTIN_frem, gen_FREM, },
275 {BUILTIN_drem, gen_DREM, },
279 /* codegen *********************************************************************
281 Generates machine code.
283 *******************************************************************************/
285 bool intrp_codegen(jitdata *jd)
290 s4 i, len, s1, s2, d;
295 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
296 unresolved_method *um;
297 builtintable_entry *bte;
300 unresolved_field *uf;
303 /* get required compiler data */
309 /* prevent compiler warnings */
316 /* create method header */
318 (void) dseg_addaddress(cd, jd->code); /* CodeinfoPointer */
319 (void) dseg_adds4(cd, m->maxlocals * SIZEOF_VOID_P); /* FrameSize */
321 #if defined(ENABLE_THREADS)
322 if (checksync && (m->flags & ACC_SYNCHRONIZED))
323 (void) dseg_adds4(cd, 1); /* IsSync */
326 (void) dseg_adds4(cd, 0); /* IsSync */
328 (void) dseg_adds4(cd, 0); /* IsLeaf */
329 (void) dseg_adds4(cd, 0); /* IntSave */
330 (void) dseg_adds4(cd, 0); /* FltSave */
332 dseg_addlinenumbertablesize(cd);
334 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
336 /* create exception table */
338 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
339 dseg_addtarget(cd, ex->start);
340 dseg_addtarget(cd, ex->end);
341 dseg_addtarget(cd, ex->handler);
342 (void) dseg_addaddress(cd, ex->catchtype.any);
346 /* initialize mcode variables */
348 cd->mcodeptr = cd->mcodebase;
349 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
354 #if defined(ENABLE_THREADS)
355 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
356 if (m->flags & ACC_STATIC)
357 gen_ACONST(cd, (java_objectheader *) m->class);
361 gen_MONITORENTER(cd);
366 gen_TRACECALL(cd, m);
370 /* walk through all basic blocks */
372 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
374 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
376 if (bptr->flags != BBDELETED) {
378 /* walk through all instructions */
384 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
385 if (iptr->line != currentline) {
386 dseg_addlinenumber(cd, iptr->line);
387 currentline = iptr->line;
390 MCODECHECK(64); /* an instruction usually needs < 64 words */
394 case ICMD_INLINE_START:
395 case ICMD_INLINE_END:
398 case ICMD_NOP: /* ... ==> ... */
401 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
406 /* constant operations ************************************************/
408 case ICMD_ICONST: /* ... ==> ..., constant */
409 /* op1 = 0, val.i = constant */
411 gen_ICONST(cd, iptr->sx.val.i);
414 case ICMD_LCONST: /* ... ==> ..., constant */
415 /* op1 = 0, val.l = constant */
417 gen_LCONST(cd, iptr->sx.val.l);
420 case ICMD_FCONST: /* ... ==> ..., constant */
421 /* op1 = 0, val.f = constant */
425 vm_f2Cell(iptr->sx.val.f, fi);
430 case ICMD_DCONST: /* ... ==> ..., constant */
431 /* op1 = 0, val.d = constant */
433 gen_LCONST(cd, *(s8 *)&(iptr->sx.val.d));
436 case ICMD_ACONST: /* ... ==> ..., constant */
437 /* op1 = 0, val.a = constant */
439 if (INSTRUCTION_IS_UNRESOLVED(iptr))
440 gen_PATCHER_ACONST(cd, NULL, iptr->sx.val.c.ref);
442 gen_ACONST(cd, iptr->sx.val.anyptr);
446 /* load/store operations **********************************************/
448 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
449 /* op1 = local variable */
451 gen_ILOAD(cd, index2offset(iptr->s1.varindex));
454 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
455 /* op1 = local variable */
457 gen_LLOAD(cd, index2offset(iptr->s1.varindex));
460 case ICMD_ALOAD: /* ... ==> ..., content of local variable */
461 /* op1 = local variable */
463 gen_ALOAD(cd, index2offset(iptr->s1.varindex));
466 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
467 /* op1 = local variable */
469 gen_ILOAD(cd, index2offset(iptr->s1.varindex));
472 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
473 /* op1 = local variable */
475 gen_LLOAD(cd, index2offset(iptr->s1.varindex));
479 case ICMD_ISTORE: /* ..., value ==> ... */
480 /* op1 = local variable */
482 gen_ISTORE(cd, index2offset(iptr->dst.varindex));
485 case ICMD_LSTORE: /* ..., value ==> ... */
486 /* op1 = local variable */
488 gen_LSTORE(cd, index2offset(iptr->dst.varindex));
491 case ICMD_ASTORE: /* ..., value ==> ... */
492 /* op1 = local variable */
494 gen_ASTORE(cd, index2offset(iptr->dst.varindex));
498 case ICMD_FSTORE: /* ..., value ==> ... */
499 /* op1 = local variable */
501 gen_ISTORE(cd, index2offset(iptr->dst.varindex));
504 case ICMD_DSTORE: /* ..., value ==> ... */
505 /* op1 = local variable */
507 gen_LSTORE(cd, index2offset(iptr->dst.varindex));
511 /* pop/dup/swap operations ********************************************/
513 case ICMD_POP: /* ..., value ==> ... */
518 case ICMD_POP2: /* ..., value, value ==> ... */
523 case ICMD_DUP: /* ..., a ==> ..., a, a */
528 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
533 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
538 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
543 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
548 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
553 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
559 /* integer operations *************************************************/
561 case ICMD_INEG: /* ..., value ==> ..., - value */
566 case ICMD_LNEG: /* ..., value ==> ..., - value */
571 case ICMD_I2L: /* ..., value ==> ..., value */
576 case ICMD_L2I: /* ..., value ==> ..., value */
581 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
586 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
591 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
597 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
602 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
603 /* val.i = constant */
605 gen_ICONST(cd, iptr->sx.val.i);
609 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
614 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
615 /* val.l = constant */
617 gen_LCONST(cd, iptr->sx.val.l);
621 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
626 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
627 /* val.i = constant */
629 gen_ICONST(cd, iptr->sx.val.i);
633 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
638 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
639 /* val.l = constant */
641 gen_LCONST(cd, iptr->sx.val.l);
645 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
650 case ICMD_IMULCONST: /* ..., val1, val2 ==> ..., val1 * val2 */
652 gen_ICONST(cd, iptr->sx.val.i);
656 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
661 case ICMD_LMULCONST: /* ..., val1, val2 ==> ..., val1 * val2 */
663 gen_LCONST(cd, iptr->sx.val.l);
667 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
672 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
677 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
682 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
687 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
688 /* val.i = constant */
690 gen_IDIVPOW2(cd, iptr->sx.val.i);
693 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
694 /* val.i = constant */
696 gen_IREMPOW2(cd, iptr->sx.val.i);
699 case ICMD_LDIVPOW2: /* ..., value ==> ..., value << constant */
700 /* val.i = constant */
702 gen_LDIVPOW2(cd, iptr->sx.val.i);
705 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
706 /* val.l = constant */
708 gen_LREMPOW2(cd, iptr->sx.val.i);
711 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
716 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
717 /* val.i = constant */
719 gen_ICONST(cd, iptr->sx.val.i);
723 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
728 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
729 /* val.i = constant */
731 gen_ICONST(cd, iptr->sx.val.i);
735 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
740 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
741 /* val.i = constant */
743 gen_ICONST(cd, iptr->sx.val.i);
747 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
752 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
753 /* val.i = constant */
755 gen_ICONST(cd, iptr->sx.val.i);
759 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
764 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
765 /* val.i = constant */
767 gen_ICONST(cd, iptr->sx.val.i);
771 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
776 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
777 /* val.i = constant */
779 gen_ICONST(cd, iptr->sx.val.i);
783 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
788 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
789 /* val.i = constant */
791 gen_ICONST(cd, iptr->sx.val.i);
795 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
800 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
801 /* val.l = constant */
803 gen_LCONST(cd, iptr->sx.val.l);
807 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
812 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
813 /* val.i = constant */
815 gen_ICONST(cd, iptr->sx.val.i);
819 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
824 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
825 /* val.l = constant */
827 gen_LCONST(cd, iptr->sx.val.l);
831 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
836 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
837 /* val.i = constant */
839 gen_ICONST(cd, iptr->sx.val.i);
843 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
848 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
849 /* val.l = constant */
851 gen_LCONST(cd, iptr->sx.val.l);
856 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
862 case ICMD_IINC: /* ..., value ==> ..., value + constant */
863 /* op1 = variable, val.i = constant */
865 gen_IINC(cd, index2offset(iptr->s1.varindex), iptr->sx.val.i);
869 /* floating operations ************************************************/
871 case ICMD_FNEG: /* ..., value ==> ..., - value */
876 case ICMD_DNEG: /* ..., value ==> ..., - value */
881 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
886 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
891 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
896 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
901 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
906 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
911 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
916 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
921 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
926 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
931 case ICMD_I2F: /* ..., value ==> ..., (float) value */
936 case ICMD_L2F: /* ..., value ==> ..., (float) value */
941 case ICMD_I2D: /* ..., value ==> ..., (double) value */
946 case ICMD_L2D: /* ..., value ==> ..., (double) value */
951 case ICMD_F2I: /* ..., value ==> ..., (int) value */
956 case ICMD_D2I: /* ..., value ==> ..., (int) value */
961 case ICMD_F2L: /* ..., value ==> ..., (long) value */
966 case ICMD_D2L: /* ..., value ==> ..., (long) value */
971 case ICMD_F2D: /* ..., value ==> ..., (double) value */
976 case ICMD_D2F: /* ..., value ==> ..., (float) value */
981 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
986 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
991 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
996 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1002 /* memory operations **************************************************/
1004 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1006 gen_ARRAYLENGTH(cd);
1009 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1014 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1019 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1024 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1029 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1034 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1035 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1040 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1046 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1051 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1052 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1057 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1062 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1067 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1068 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1073 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1079 case ICMD_GETSTATIC: /* ... ==> ..., value */
1080 /* op1 = type, val.a = field address */
1082 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1084 uf = iptr->sx.s23.s3.uf;
1085 fieldtype = uf->fieldref->parseddesc.fd->type;
1088 fi = iptr->sx.s23.s3.fmiref->p.field;
1089 fieldtype = fi->type;
1092 switch (fieldtype) {
1095 gen_PATCHER_GETSTATIC_INT(cd, 0, uf);
1096 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1097 gen_PATCHER_GETSTATIC_CLINIT_INT(cd, 0, fi);
1099 gen_GETSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1103 gen_PATCHER_GETSTATIC_FLOAT(cd, 0, uf);
1104 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1105 gen_PATCHER_GETSTATIC_CLINIT_FLOAT(cd, 0, fi);
1107 gen_GETSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1112 gen_PATCHER_GETSTATIC_LONG(cd, 0, uf);
1113 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1114 gen_PATCHER_GETSTATIC_CLINIT_LONG(cd, 0, fi);
1116 gen_GETSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1120 gen_PATCHER_GETSTATIC_CELL(cd, 0, uf);
1121 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1122 gen_PATCHER_GETSTATIC_CLINIT_CELL(cd, 0, fi);
1124 gen_GETSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1129 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1130 /* op1 = type, val.a = field address */
1132 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1134 uf = iptr->sx.s23.s3.uf;
1135 fieldtype = uf->fieldref->parseddesc.fd->type;
1138 fi = iptr->sx.s23.s3.fmiref->p.field;
1139 fieldtype = fi->type;
1142 switch (fieldtype) {
1145 gen_PATCHER_PUTSTATIC_INT(cd, 0, uf);
1146 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1147 gen_PATCHER_PUTSTATIC_CLINIT_INT(cd, 0, fi);
1149 gen_PUTSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1153 gen_PATCHER_PUTSTATIC_FLOAT(cd, 0, uf);
1154 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1155 gen_PATCHER_PUTSTATIC_CLINIT_FLOAT(cd, 0, fi);
1157 gen_PUTSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1162 gen_PATCHER_PUTSTATIC_LONG(cd, 0, uf);
1163 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1164 gen_PATCHER_PUTSTATIC_CLINIT_LONG(cd, 0, fi);
1166 gen_PUTSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1170 gen_PATCHER_PUTSTATIC_CELL(cd, 0, uf);
1171 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1172 gen_PATCHER_PUTSTATIC_CLINIT_CELL(cd, 0, fi);
1174 gen_PUTSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1180 case ICMD_GETFIELD: /* ... ==> ..., value */
1181 /* op1 = type, val.a = field address */
1183 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1185 uf = iptr->sx.s23.s3.uf;
1186 fieldtype = uf->fieldref->parseddesc.fd->type;
1189 fi = iptr->sx.s23.s3.fmiref->p.field;
1190 fieldtype = fi->type;
1193 switch (fieldtype) {
1196 gen_PATCHER_GETFIELD_INT(cd, 0, uf);
1198 gen_GETFIELD_INT(cd, fi->offset, fi);
1202 gen_PATCHER_GETFIELD_FLOAT(cd, 0, uf);
1204 gen_GETFIELD_FLOAT(cd, fi->offset, fi);
1209 gen_PATCHER_GETFIELD_LONG(cd, 0, uf);
1211 gen_GETFIELD_LONG(cd, fi->offset, fi);
1215 gen_PATCHER_GETFIELD_CELL(cd, 0, uf);
1217 gen_GETFIELD_CELL(cd, fi->offset, fi);
1222 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1223 /* op1 = type, val.a = field address */
1225 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1227 uf = iptr->sx.s23.s3.uf;
1228 fieldtype = uf->fieldref->parseddesc.fd->type;
1231 fi = iptr->sx.s23.s3.fmiref->p.field;
1232 fieldtype = fi->type;
1235 switch (fieldtype) {
1238 gen_PATCHER_PUTFIELD_INT(cd, 0, uf);
1240 gen_PUTFIELD_INT(cd, fi->offset, fi);
1244 gen_PATCHER_PUTFIELD_FLOAT(cd, 0, uf);
1246 gen_PUTFIELD_FLOAT(cd, fi->offset, fi);
1251 gen_PATCHER_PUTFIELD_LONG(cd, 0, uf);
1253 gen_PUTFIELD_LONG(cd, fi->offset, fi);
1257 gen_PATCHER_PUTFIELD_CELL(cd, 0, uf);
1259 gen_PUTFIELD_CELL(cd, fi->offset, fi);
1265 /* branch operations **************************************************/
1267 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1272 case ICMD_GOTO: /* ... ==> ... */
1273 /* op1 = target JavaVM pc */
1277 case ICMD_JSR: /* ... ==> ... */
1278 /* op1 = target JavaVM pc */
1281 codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex));
1284 case ICMD_RET: /* ... ==> ... */
1285 /* op1 = local variable */
1287 gen_RET(cd, index2offset(iptr->s1.varindex));
1290 case ICMD_IFNULL: /* ..., value ==> ... */
1291 /* op1 = target JavaVM pc */
1296 case ICMD_IFNONNULL: /* ..., value ==> ... */
1297 /* op1 = target JavaVM pc */
1299 gen_branch(IFNONNULL);
1302 case ICMD_IFEQ: /* ..., value ==> ... */
1303 /* op1 = target JavaVM pc, val.i = constant */
1305 if (iptr->sx.val.i == 0) {
1308 gen_ICONST(cd, iptr->sx.val.i);
1309 gen_branch(IF_ICMPEQ);
1313 case ICMD_IFLT: /* ..., value ==> ... */
1314 /* op1 = target JavaVM pc, val.i = constant */
1316 if (iptr->sx.val.i == 0) {
1319 gen_ICONST(cd, iptr->sx.val.i);
1320 gen_branch(IF_ICMPLT);
1324 case ICMD_IFLE: /* ..., value ==> ... */
1325 /* op1 = target JavaVM pc, val.i = constant */
1327 if (iptr->sx.val.i == 0) {
1330 gen_ICONST(cd, iptr->sx.val.i);
1331 gen_branch(IF_ICMPLE);
1335 case ICMD_IFNE: /* ..., value ==> ... */
1336 /* op1 = target JavaVM pc, val.i = constant */
1338 if (iptr->sx.val.i == 0) {
1341 gen_ICONST(cd, iptr->sx.val.i);
1342 gen_branch(IF_ICMPNE);
1346 case ICMD_IFGT: /* ..., value ==> ... */
1347 /* op1 = target JavaVM pc, val.i = constant */
1349 if (iptr->sx.val.i == 0) {
1352 gen_ICONST(cd, iptr->sx.val.i);
1353 gen_branch(IF_ICMPGT);
1357 case ICMD_IFGE: /* ..., value ==> ... */
1358 /* op1 = target JavaVM pc, val.i = constant */
1360 if (iptr->sx.val.i == 0) {
1363 gen_ICONST(cd, iptr->sx.val.i);
1364 gen_branch(IF_ICMPGE);
1368 case ICMD_IF_LEQ: /* ..., value ==> ... */
1369 /* op1 = target JavaVM pc, val.l = constant */
1371 gen_LCONST(cd, iptr->sx.val.l);
1372 gen_branch(IF_LCMPEQ);
1375 case ICMD_IF_LLT: /* ..., value ==> ... */
1376 /* op1 = target JavaVM pc, val.l = constant */
1378 gen_LCONST(cd, iptr->sx.val.l);
1379 gen_branch(IF_LCMPLT);
1382 case ICMD_IF_LLE: /* ..., value ==> ... */
1383 /* op1 = target JavaVM pc, val.l = constant */
1385 gen_LCONST(cd, iptr->sx.val.l);
1386 gen_branch(IF_LCMPLE);
1389 case ICMD_IF_LNE: /* ..., value ==> ... */
1390 /* op1 = target JavaVM pc, val.l = constant */
1392 gen_LCONST(cd, iptr->sx.val.l);
1393 gen_branch(IF_LCMPNE);
1396 case ICMD_IF_LGT: /* ..., value ==> ... */
1397 /* op1 = target JavaVM pc, val.l = constant */
1399 gen_LCONST(cd, iptr->sx.val.l);
1400 gen_branch(IF_LCMPGT);
1403 case ICMD_IF_LGE: /* ..., value ==> ... */
1404 /* op1 = target JavaVM pc, val.l = constant */
1406 gen_LCONST(cd, iptr->sx.val.l);
1407 gen_branch(IF_LCMPGE);
1410 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1411 /* op1 = target JavaVM pc */
1413 gen_branch(IF_ICMPEQ);
1416 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1417 /* op1 = target JavaVM pc */
1419 gen_branch(IF_LCMPEQ);
1422 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
1423 /* op1 = target JavaVM pc */
1425 gen_branch(IF_ACMPEQ);
1428 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
1429 /* op1 = target JavaVM pc */
1431 gen_branch(IF_ICMPNE);
1434 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
1435 /* op1 = target JavaVM pc */
1437 gen_branch(IF_LCMPNE);
1440 case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
1441 /* op1 = target JavaVM pc */
1443 gen_branch(IF_ACMPNE);
1446 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
1447 /* op1 = target JavaVM pc */
1449 gen_branch(IF_ICMPLT);
1452 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
1453 /* op1 = target JavaVM pc */
1455 gen_branch(IF_LCMPLT);
1458 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
1459 /* op1 = target JavaVM pc */
1461 gen_branch(IF_ICMPGT);
1464 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
1465 /* op1 = target JavaVM pc */
1467 gen_branch(IF_LCMPGT);
1470 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
1471 /* op1 = target JavaVM pc */
1473 gen_branch(IF_ICMPLE);
1476 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
1477 /* op1 = target JavaVM pc */
1479 gen_branch(IF_LCMPLE);
1482 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
1483 /* op1 = target JavaVM pc */
1485 gen_branch(IF_ICMPGE);
1488 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
1489 /* op1 = target JavaVM pc */
1491 gen_branch(IF_LCMPGE);
1495 case ICMD_ARETURN: /* ..., retvalue ==> ... */
1496 case ICMD_IRETURN: /* ..., retvalue ==> ... */
1497 case ICMD_FRETURN: /* ..., retvalue ==> ... */
1499 #if defined(ENABLE_THREADS)
1500 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1501 if (m->flags & ACC_STATIC) {
1502 gen_ACONST(cd, (java_objectheader *) m->class);
1506 gen_MONITOREXIT(cd);
1509 if (opt_verbosecall)
1510 gen_TRACERETURN(cd, m);
1512 gen_IRETURN(cd, index2offset(cd->maxlocals));
1515 case ICMD_LRETURN: /* ..., retvalue ==> ... */
1516 case ICMD_DRETURN: /* ..., retvalue ==> ... */
1518 #if defined(ENABLE_THREADS)
1519 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1520 if (m->flags & ACC_STATIC) {
1521 gen_ACONST(cd, (java_objectheader *) m->class);
1525 gen_MONITOREXIT(cd);
1528 if (opt_verbosecall)
1529 gen_TRACELRETURN(cd, m);
1531 gen_LRETURN(cd, index2offset(cd->maxlocals));
1534 case ICMD_RETURN: /* ... ==> ... */
1536 #if defined(ENABLE_THREADS)
1537 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1538 if (m->flags & ACC_STATIC) {
1539 gen_ACONST(cd, (java_objectheader *) m->class);
1543 gen_MONITOREXIT(cd);
1546 if (opt_verbosecall)
1547 gen_TRACERETURN(cd, m);
1549 gen_RETURN(cd, index2offset(cd->maxlocals));
1553 case ICMD_TABLESWITCH: /* ..., index ==> ... */
1556 branch_target_t *table;
1558 table = iptr->dst.table;
1560 l = iptr->sx.s23.s2.tablelow;
1561 i = iptr->sx.s23.s3.tablehigh;
1565 /* arguments: low, range, datasegment address, table
1566 offset in datasegment, default target */
1568 gen_TABLESWITCH(cd, l, i, NULL, 0, NULL);
1570 /* actually -3 cells offset */
1572 cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1574 cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1576 codegen_addreference(cd, BLOCK_OF(table[0].insindex));
1578 /* build jump table top down and use address of lowest entry */
1583 dseg_addtarget(cd, BLOCK_OF(table->insindex));
1588 /* length of dataseg after last dseg_addtarget is used by load */
1589 ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1593 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
1596 lookup_target_t *lookup;
1598 lookup = iptr->dst.lookup;
1600 i = iptr->sx.s23.s2.lookupcount;
1602 /* arguments: count, datasegment address, table offset in */
1603 /* datasegment, default target */
1604 gen_LOOKUPSWITCH(cd, i, NULL, 0, NULL);
1606 /* actually -3 cells offset */
1608 cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1610 cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1612 /* build jump table top down and use address of lowest entry */
1615 dseg_addtarget(cd, BLOCK_OF(lookup->target.insindex));
1616 dseg_addaddress(cd, lookup->value);
1620 codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex));
1623 /* length of dataseg after last dseg_addtarget is used by load */
1624 ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1628 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
1629 /* op1 = arg count val.a = builtintable entry */
1630 bte = iptr->sx.s23.s3.bte;
1632 for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
1633 builtin_gen *bg = &builtin_gen_table[i];
1634 if (bg->builtin == bte->fp) {
1636 goto gen_builtin_end;
1645 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
1646 /* op1 = arg count, val.a = method pointer */
1648 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1649 um = iptr->sx.s23.s3.um;
1650 md = um->methodref->parseddesc.md;
1651 gen_PATCHER_INVOKESTATIC(cd, 0, md->paramslots, um);
1654 lm = iptr->sx.s23.s3.fmiref->p.method;
1655 md = lm->parseddesc;
1656 gen_INVOKESTATIC(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1660 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1662 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1663 um = iptr->sx.s23.s3.um;
1664 md = um->methodref->parseddesc.md;
1665 gen_PATCHER_INVOKESPECIAL(cd, 0, md->paramslots, um);
1668 lm = iptr->sx.s23.s3.fmiref->p.method;
1669 md = lm->parseddesc;
1670 gen_INVOKESPECIAL(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1674 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
1676 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1677 um = iptr->sx.s23.s3.um;
1678 md = um->methodref->parseddesc.md;
1679 gen_PATCHER_INVOKEVIRTUAL(cd, 0, md->paramslots, um);
1682 lm = iptr->sx.s23.s3.fmiref->p.method;
1683 md = lm->parseddesc;
1685 s1 = OFFSET(vftbl_t, table[0]) +
1686 sizeof(methodptr) * lm->vftblindex;
1688 gen_INVOKEVIRTUAL(cd, s1, md->paramslots, lm);
1692 case ICMD_INVOKEINTERFACE:/* op1 = arg count, val.a = method pointer */
1694 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1695 um = iptr->sx.s23.s3.um;
1696 md = um->methodref->parseddesc.md;
1697 gen_PATCHER_INVOKEINTERFACE(cd, 0, 0, md->paramslots, um);
1700 lm = iptr->sx.s23.s3.fmiref->p.method;
1701 md = lm->parseddesc;
1703 s1 = OFFSET(vftbl_t, interfacetable[0]) -
1704 sizeof(methodptr*) * lm->class->index;
1706 s2 = sizeof(methodptr) * (lm - lm->class->methods);
1708 gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
1713 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
1714 /* op1: 0 == array, 1 == class */
1715 /* val.a: (classinfo *) superclass */
1717 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1718 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1719 gen_PATCHER_CHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1721 gen_CHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1724 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1725 gen_PATCHER_ARRAYCHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1727 gen_ARRAYCHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1731 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
1732 /* op1: 0 == array, 1 == class */
1733 /* val.a: (classinfo *) superclass */
1735 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1736 gen_PATCHER_INSTANCEOF(cd, NULL, iptr->sx.s23.s3.c.ref);
1738 gen_INSTANCEOF(cd, iptr->sx.s23.s3.c.cls, iptr->sx.s23.s3.c.ref);
1741 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
1742 /* op1 = dimension, val.a = class */
1744 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1745 gen_PATCHER_MULTIANEWARRAY(cd, NULL, iptr->s1.argcount, iptr->sx.s23.s3.c.ref);
1747 gen_MULTIANEWARRAY(cd, iptr->sx.s23.s3.c.cls, iptr->s1.argcount, NULL);
1751 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
1755 } /* for instruction */
1759 } /* if (bptr->flags != BBDELETED) */
1760 } /* for basic block */
1762 dseg_createlinenumbertable(cd);
1767 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
1770 /* branch resolving (walk through all basic blocks) */
1772 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
1775 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
1776 gen_resolveanybranch(((u1*) jd->code->entrypoint) + brefs->branchpos,
1777 ((u1 *)jd->code->entrypoint) + bptr->mpc);
1781 /* everything's ok */
1787 /* createcompilerstub **********************************************************
1789 Creates a stub routine which calls the compiler.
1795 +-------------+ <-- stub
1805 codeptr points either to TRANSLATE or to the translated threaded code
1807 all methods are called indirectly through methodptr
1809 *******************************************************************************/
1811 #define COMPILERSTUB_DATASIZE 1
1812 #define COMPILERSTUB_CODESIZE 4
1814 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
1817 u1 *intrp_createcompilerstub(methodinfo *m)
1825 s = CNEW(Inst, COMPILERSTUB_SIZE);
1827 /* set data pointer and code pointer */
1830 s = s + COMPILERSTUB_DATASIZE;
1832 /* Store the codeinfo pointer in the same place as in the
1833 methodheader for compiled methods. */
1835 code = code_codeinfo_new(m);
1836 d[0] = (Inst *) code;
1838 /* mark start of dump memory area */
1840 dumpsize = dump_size();
1842 cd = DNEW(codegendata);
1843 cd->mcodeptr = (u1 *) s;
1844 cd->lastinstwithoutdispatch = ~0;
1845 cd->superstarts = NULL;
1847 genarg_ainst(cd, s + 2);
1849 if (m->flags & ACC_NATIVE) {
1850 genarg_i(cd, m->parseddesc->paramslots);
1852 genarg_i(cd, m->maxlocals);
1856 gen_TRANSLATE(cd, m);
1860 vm_block_insert(cd->mcodeptr);
1863 #if defined(ENABLE_STATISTICS)
1865 count_cstub_len += COMPILERSTUB_SIZE;
1868 /* release dump area */
1870 dump_release(dumpsize);
1876 #if defined(WITH_FFI)
1877 static ffi_type *cacaotype2ffitype(s4 cacaotype)
1879 switch (cacaotype) {
1881 #if SIZEOF_VOID_P == 8
1882 return &ffi_type_sint64;
1884 return &ffi_type_sint32;
1887 return &ffi_type_sint64;
1889 return &ffi_type_float;
1891 return &ffi_type_double;
1893 return &ffi_type_pointer;
1895 return &ffi_type_void;
1915 #if defined(WITH_FFI)
1916 static ffi_cif *createnativecif(methodinfo *m, methoddesc *nmd)
1918 methoddesc *md = m->parseddesc;
1919 ffi_cif *pcif = NEW(ffi_cif);
1920 ffi_type **types = MNEW(ffi_type *, nmd->paramcount);
1921 ffi_type **ptypes = types;
1924 /* pass env pointer */
1926 *ptypes++ = &ffi_type_pointer;
1928 /* for static methods, pass class pointer */
1930 if (m->flags & ACC_STATIC)
1931 *ptypes++ = &ffi_type_pointer;
1933 /* pass parameter to native function */
1935 for (i = 0; i < md->paramcount; i++)
1936 *ptypes++ = cacaotype2ffitype(md->paramtypes[i].type);
1938 assert(ptypes - types == nmd->paramcount);
1940 if (ffi_prep_cif(pcif, FFI_DEFAULT_ABI, nmd->paramcount, cacaotype2ffitype(md->returntype.type), types) != FFI_OK)
1948 u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
1954 #if defined(WITH_FFI)
1960 /* get required compiler data */
1966 /* create method header */
1968 /* Store the codeinfo pointer in the same place as in the
1969 methodheader for compiled methods. */
1971 code = code_codeinfo_new(m);
1973 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
1974 (void) dseg_adds4(cd, nmd->paramslots * SIZEOF_VOID_P); /* FrameSize */
1975 (void) dseg_adds4(cd, 0); /* IsSync */
1976 (void) dseg_adds4(cd, 0); /* IsLeaf */
1977 (void) dseg_adds4(cd, 0); /* IntSave */
1978 (void) dseg_adds4(cd, 0); /* FltSave */
1979 dseg_addlinenumbertablesize(cd);
1980 (void) dseg_adds4(cd, 0); /* ExTableSize */
1982 #if defined(WITH_FFI)
1983 /* prepare ffi cif structure */
1985 cif = createnativecif(m, nmd);
1992 if (opt_verbosecall)
1993 gen_TRACECALL(cd, m);
1996 gen_PATCHER_NATIVECALL(cd, m, f, (u1 *)cif);
1998 if (opt_verbosecall)
1999 gen_TRACENATIVECALL(cd, m, f, (u1 *)cif);
2001 gen_NATIVECALL(cd, m, f, (u1 *)cif);
2009 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2012 return jd->code->entrypoint;
2016 /* call jni function */
2017 Cell *nativecall(functionptr f, methodinfo *m, Cell *sp, Inst *ra, Cell *fp, u1 *addrcif)
2019 #if defined(WITH_FFCALL)
2033 switch (md->returntype.type) {
2035 endsp = sp - 1 + md->paramslots;
2036 av_start_long(alist, f, endsp);
2039 endsp = sp - 2 + md->paramslots;
2040 av_start_longlong(alist, f, endsp);
2043 endsp = sp - 1 + md->paramslots;
2044 av_start_float(alist, f, endsp);
2047 endsp = sp - 2 + md->paramslots;
2048 av_start_double(alist, f, endsp);
2051 endsp = sp - 1 + md->paramslots;
2052 av_start_ptr(alist, f, void *, endsp);
2055 endsp = sp + md->paramslots;
2056 av_start_void(alist, f);
2062 av_ptr(alist, _Jv_JNIEnv *, _Jv_env);
2064 if (m->flags & ACC_STATIC)
2065 av_ptr(alist, classinfo *, m->class);
2067 for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2068 switch (md->paramtypes[i].type) {
2075 av_longlong(alist, *(s8 *)p);
2079 av_float(alist, *((float *) p));
2083 av_double(alist, *(double *) p);
2087 av_ptr(alist, void *, *(void **) p);
2096 /* create stackframe info structure */
2098 codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2099 (u1 *) fp, (u1 *) ra);
2103 codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2108 #elif defined(WITH_FFI)
2109 methoddesc *md = m->parseddesc;
2111 void *values[md->paramcount + 2];
2112 void **pvalues = values;
2123 pcif = (ffi_cif *) addrcif;
2125 /* pass env pointer */
2127 penv = (_Jv_JNIEnv *) _Jv_env;
2130 /* for static methods, pass class pointer */
2132 if (m->flags & ACC_STATIC)
2133 *pvalues++ = &m->class;
2135 /* pass parameter to native function */
2137 for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2138 if (IS_2_WORD_TYPE(md->paramtypes[i].type))
2146 /* calculate position of return value */
2148 if (md->returntype.type == TYPE_VOID)
2149 endsp = sp + md->paramslots;
2151 endsp = sp - (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1) + md->paramslots;
2155 /* create stackframe info structure */
2157 codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2158 (u1 *) fp, (u1 *) ra);
2160 ffi_call(pcif, FFI_FN(f), endsp, values);
2162 codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2171 u1 *createcalljavafunction(methodinfo *m)
2181 /* mark dump memory */
2183 dumpsize = dump_size();
2185 /* allocate memory */
2189 tmpm = DNEW(methodinfo);
2190 cd = DNEW(codegendata);
2191 rd = DNEW(registerdata);
2198 /* Allocate codeinfo memory from the heap as we need to keep them. */
2200 jd->code = code_codeinfo_new(tmpm); /* XXX check allocation */
2202 /* setup code generation stuff */
2204 MSET(tmpm, 0, u1, sizeof(methodinfo));
2210 /* create method header */
2212 (void) dseg_addaddress(cd, NULL); /* CodeinfoPointer */
2213 (void) dseg_adds4(cd, md->paramslots * SIZEOF_VOID_P); /* FrameSize */
2214 (void) dseg_adds4(cd, 0); /* IsSync */
2215 (void) dseg_adds4(cd, 0); /* IsLeaf */
2216 (void) dseg_adds4(cd, 0); /* IntSave */
2217 (void) dseg_adds4(cd, 0); /* FltSave */
2218 dseg_addlinenumbertablesize(cd);
2219 (void) dseg_adds4(cd, 0); /* ExTableSize */
2225 gen_INVOKESTATIC(cd, (Inst **)m->stubroutine, md->paramslots, 0);
2233 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2235 entrypoint = jd->code->entrypoint;
2237 /* release memory */
2239 dump_release(dumpsize);
2246 * These are local overrides for various environment variables in Emacs.
2247 * Please do not remove this and leave it at the end of the file, where
2248 * Emacs will automagically detect them.
2249 * ---------------------------------------------------------------------
2252 * indent-tabs-mode: t
2256 * vim:noexpandtab:sw=4:ts=4: