1 /* src/vm/jit/intrp/codegen.c - code generator for Interpreter
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33 #elif defined(WITH_FFCALL)
36 # error neither WITH_FFI nor WITH_FFCALL defined
43 #include "vm/jit/intrp/codegen.h"
44 #include "vm/jit/intrp/intrp.h"
46 #include "mm/memory.h"
48 #include "native/native.h"
50 #include "vm/builtin.h"
51 #include "vm/exceptions.h"
52 #include "vm/global.h"
53 #include "vm/stringlocal.h"
56 #include "vm/jit/asmpart.h"
57 #include "vm/jit/codegen-common.h"
58 #include "vm/jit/dseg.h"
59 #include "vm/jit/jit.h"
60 #include "vm/jit/parse.h"
61 #include "vm/jit/patcher.h"
62 #include "vm/jit/stack.h"
63 #include "vm/jit/stacktrace.h"
65 #include "vmcore/class.h"
66 #include "vmcore/options.h"
69 #define gen_branch(_inst) { \
71 codegen_addreference(cd, BLOCK_OF(iptr->dst.insindex)); \
74 #define index2offset(_i) (-(_i) * SIZEOF_VOID_P)
76 /* functions used by cacao-gen.i */
78 void genarg_v(codegendata *cd1, Cell v)
80 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
81 *((Cell *) *mcodepp) = v;
85 void genarg_i(codegendata *cd1, s4 i)
87 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
88 *((Cell *) *mcodepp) = i;
92 void genarg_b(codegendata *cd1, s4 i)
97 void genarg_f(codegendata *cd1, float f)
105 void genarg_l(codegendata *cd1, s8 l)
107 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
108 vm_l2twoCell(l, ((Cell *) *mcodepp)[1], ((Cell *) *mcodepp)[0]);
112 void genarg_aRef(codegendata *cd1, java_objectheader *a)
114 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
115 *((java_objectheader **) *mcodepp) = a;
119 void genarg_aArray(codegendata *cd1, java_arrayheader *a)
121 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
122 *((java_arrayheader **) *mcodepp) = a;
126 void genarg_aaTarget(codegendata *cd1, Inst **a)
128 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
129 *((Inst ***) *mcodepp) = a;
133 void genarg_aClass(codegendata *cd1, classinfo *a)
135 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
136 *((classinfo **) *mcodepp) = a;
140 void genarg_acr(codegendata *cd1, constant_classref *a)
142 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
143 *((constant_classref **) *mcodepp) = a;
147 void genarg_addr(codegendata *cd1, u1 *a)
149 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
150 *((u1 **) *mcodepp) = a;
154 void genarg_af(codegendata *cd1, functionptr a)
156 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
157 *((functionptr *) *mcodepp) = a;
161 void genarg_afi(codegendata *cd1, fieldinfo *a)
163 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
164 *((fieldinfo **) *mcodepp) = a;
168 void genarg_am(codegendata *cd1, methodinfo *a)
170 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
171 *((methodinfo **) *mcodepp) = a;
175 void genarg_acell(codegendata *cd1, Cell *a)
177 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
178 *((Cell **) *mcodepp) = a;
182 void genarg_ainst(codegendata *cd1, Inst *a)
184 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
185 *((Inst **) *mcodepp) = a;
189 void genarg_auf(codegendata *cd1, unresolved_field *a)
191 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
192 *((unresolved_field **) *mcodepp) = a;
196 void genarg_aum(codegendata *cd1, unresolved_method *a)
198 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
199 *((unresolved_method **) *mcodepp) = a;
203 void genarg_avftbl(codegendata *cd1, vftbl_t *a)
205 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
206 *((vftbl_t **) *mcodepp) = a;
211 /* include the interpreter generation functions *******************************/
213 /* Do not use "java-gen.i", it does not work with builddir. */
214 #include <java-gen.i>
217 typedef void (*genfunctionptr) (codegendata *);
219 typedef struct builtin_gen builtin_gen;
226 struct builtin_gen builtin_gen_table[] = {
227 {BUILTIN_new, gen_NEW, },
228 {BUILTIN_newarray, gen_NEWARRAY, },
229 {BUILTIN_newarray_boolean, gen_NEWARRAY_BOOLEAN,},
230 {BUILTIN_newarray_byte, gen_NEWARRAY_BYTE, },
231 {BUILTIN_newarray_char, gen_NEWARRAY_CHAR, },
232 {BUILTIN_newarray_short, gen_NEWARRAY_SHORT, },
233 {BUILTIN_newarray_int, gen_NEWARRAY_INT, },
234 {BUILTIN_newarray_long, gen_NEWARRAY_LONG, },
235 {BUILTIN_newarray_float, gen_NEWARRAY_FLOAT, },
236 {BUILTIN_newarray_double, gen_NEWARRAY_DOUBLE, },
237 {BUILTIN_arrayinstanceof, gen_ARRAYINSTANCEOF, },
239 #if defined(ENABLE_THREADS)
240 {LOCK_monitor_enter, gen_MONITORENTER, },
241 {LOCK_monitor_exit, gen_MONITOREXIT, },
244 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
245 {BUILTIN_f2l, gen_F2L, },
248 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
249 {BUILTIN_d2l, gen_D2L, },
252 #if !(SUPPORT_FLOAT && SUPPORT_F2I)
253 {BUILTIN_f2i, gen_F2I, },
256 #if !(SUPPORT_DOUBLE && SUPPORT_D2I)
257 {BUILTIN_d2i, gen_D2I, },
260 #if !SUPPORT_DIVISION
261 {BUILTIN_idiv, gen_IDIV, },
262 {BUILTIN_irem, gen_IREM, },
265 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
266 {BUILTIN_ldiv, gen_LDIV, },
267 {BUILTIN_lrem, gen_LREM, },
270 {BUILTIN_frem, gen_FREM, },
271 {BUILTIN_drem, gen_DREM, },
275 /* codegen *********************************************************************
277 Generates machine code.
279 *******************************************************************************/
281 #define I(value) iptr[0].sx.val.i = (value); break;
283 bool intrp_codegen(jitdata *jd)
288 s4 i, len, s1, s2, d;
292 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
293 unresolved_method *um;
294 builtintable_entry *bte;
297 unresolved_field *uf;
300 /* get required compiler data */
306 /* prevent compiler warnings */
313 /* determine stackframe size (in units of ptrint slots) */
315 cd->stackframesize = m->maxlocals;
317 #if defined(ENABLE_THREADS)
318 if (checksync && code_is_synchronized(code))
319 cd->stackframesize += 1;
322 /* create method header */
324 (void) dseg_add_unique_address(cd, jd->code);
325 (void) dseg_add_unique_s4(cd, cd->stackframesize * SIZEOF_VOID_P);
327 code->synchronizedoffset = rd->memuse * 8;
329 /* REMOVEME: We still need it for exception handling in assembler. */
331 if (code_is_leafmethod(code))
332 (void) dseg_add_unique_s4(cd, 1);
334 (void) dseg_add_unique_s4(cd, 0);
336 (void) dseg_add_unique_s4(cd, 0);
337 (void) dseg_add_unique_s4(cd, 0);
339 dseg_addlinenumbertablesize(cd);
342 /* initialize mcode variables */
344 cd->mcodeptr = cd->mcodebase;
345 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
350 #if defined(ENABLE_THREADS)
351 if (checksync && code_is_synchronized(code)) {
352 if (m->flags & ACC_STATIC) {
353 gen_ACONST(cd, (java_objectheader *) m->clazz);
358 gen_ASTORE(cd, index2offset(m->maxlocals));
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 */
395 case ICMD_INLINE_START:
396 case ICMD_INLINE_END:
399 case ICMD_NOP: /* ... ==> ... */
402 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
407 /* constant operations ************************************************/
409 case ICMD_ICONST: /* ... ==> ..., constant */
410 /* op1 = 0, val.i = constant */
412 /* optimize ICONST (2^x) .. IREM --> IREMPOW2 (const) */
414 if (len >= 2 && iptr[1].opc == ICMD_IREM) {
415 switch (iptr[0].sx.val.i) {
416 case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
417 case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
418 case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
419 case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
420 case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
421 case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
422 case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
423 case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
424 iptr[0].opc = ICMD_IREMPOW2;
426 iptr[1].opc = ICMD_NOP;
431 /* optimize ICONST (2^x) .. IDIV --> IDIVPOW2 (const) */
433 if (len >= 2 && iptr[1].opc == ICMD_IDIV) {
434 switch (iptr[0].sx.val.i) {
435 case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
436 case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
437 case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
438 case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
439 case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
440 case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
441 case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
442 case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
443 default: goto dont_opt_IDIVPOW2;
445 iptr[0].opc = ICMD_IDIVPOW2;
446 iptr[1].opc = ICMD_NOP;
451 /* optimize ICONST .. IF_ICMPxx --> IFxx (const) */
454 switch (iptr[1].opc) {
455 case ICMD_IF_ICMPEQ: iptr[0].opc = ICMD_IFEQ; break;
456 case ICMD_IF_ICMPNE: iptr[0].opc = ICMD_IFNE; break;
457 case ICMD_IF_ICMPLT: iptr[0].opc = ICMD_IFLT; break;
458 case ICMD_IF_ICMPLE: iptr[0].opc = ICMD_IFLE; break;
459 case ICMD_IF_ICMPGT: iptr[0].opc = ICMD_IFGT; break;
460 case ICMD_IF_ICMPGE: iptr[0].opc = ICMD_IFGE; break;
461 default: goto dont_opt_IFxx;
463 iptr[0].dst.insindex = iptr[1].dst.insindex;
464 iptr[1].opc = ICMD_NOP;
469 gen_ICONST(cd, iptr->sx.val.i);
472 case ICMD_LCONST: /* ... ==> ..., constant */
473 /* op1 = 0, val.l = constant */
475 /* optimize LCONST (2^x) .. LREM --> LREMPOW2 (const) */
477 if (len >= 2 && iptr[1].opc == ICMD_LREM) {
478 switch (iptr[0].sx.val.l) {
479 case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
480 case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
481 case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
482 case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
483 case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
484 case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
485 case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
486 case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
487 iptr[0].opc = ICMD_LREMPOW2;
489 iptr[1].opc = ICMD_NOP;
494 /* optimize LCONST (2^x) .. LDIV --> LDIVPOW2 (const) */
496 if (len >= 2 && iptr[1].opc == ICMD_LDIV) {
497 switch (iptr[0].sx.val.l) {
498 case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
499 case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
500 case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
501 case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
502 case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
503 case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
504 case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
505 case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
506 default: goto dont_opt_LDIVPOW2;
508 iptr[0].opc = ICMD_LDIVPOW2;
509 iptr[1].opc = ICMD_NOP;
514 /* optimize LCONST .. LCMP .. IFxx (0) --> IF_Lxx */
516 if (len >= 3 && iptr[1].opc == ICMD_LCMP && iptr[2].sx.val.i == 0) {
517 switch (iptr[2].opc) {
518 case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LEQ; break;
519 case ICMD_IFNE: iptr[0].opc = ICMD_IF_LNE; break;
520 case ICMD_IFLT: iptr[0].opc = ICMD_IF_LLT; break;
521 case ICMD_IFLE: iptr[0].opc = ICMD_IF_LLE; break;
522 case ICMD_IFGT: iptr[0].opc = ICMD_IF_LGT; break;
523 case ICMD_IFGE: iptr[0].opc = ICMD_IF_LGE; break;
524 default: goto dont_opt_IF_Lxx;
526 iptr[0].dst.insindex = iptr[2].dst.insindex;
527 iptr[1].opc = ICMD_NOP;
528 iptr[2].opc = ICMD_NOP;
533 gen_LCONST(cd, iptr->sx.val.l);
536 case ICMD_FCONST: /* ... ==> ..., constant */
537 /* op1 = 0, val.f = constant */
541 vm_f2Cell(iptr->sx.val.f, fi);
546 case ICMD_DCONST: /* ... ==> ..., constant */
547 /* op1 = 0, val.d = constant */
549 gen_LCONST(cd, *(s8 *)&(iptr->sx.val.d));
552 case ICMD_ACONST: /* ... ==> ..., constant */
553 /* op1 = 0, val.a = constant */
555 if (INSTRUCTION_IS_UNRESOLVED(iptr))
556 gen_PATCHER_ACONST(cd, NULL, iptr->sx.val.c.ref);
558 gen_ACONST(cd, iptr->sx.val.anyptr);
562 /* load/store operations **********************************************/
564 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
565 /* op1 = local variable */
567 gen_ILOAD(cd, index2offset(iptr->s1.varindex));
570 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
571 /* op1 = local variable */
573 gen_LLOAD(cd, index2offset(iptr->s1.varindex));
576 case ICMD_ALOAD: /* ... ==> ..., content of local variable */
577 /* op1 = local variable */
579 gen_ALOAD(cd, index2offset(iptr->s1.varindex));
582 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
583 /* op1 = local variable */
585 gen_ILOAD(cd, index2offset(iptr->s1.varindex));
588 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
589 /* op1 = local variable */
591 gen_LLOAD(cd, index2offset(iptr->s1.varindex));
595 case ICMD_ISTORE: /* ..., value ==> ... */
596 /* op1 = local variable */
598 gen_ISTORE(cd, index2offset(iptr->dst.varindex));
601 case ICMD_LSTORE: /* ..., value ==> ... */
602 /* op1 = local variable */
604 gen_LSTORE(cd, index2offset(iptr->dst.varindex));
607 case ICMD_ASTORE: /* ..., value ==> ... */
608 /* op1 = local variable */
610 gen_ASTORE(cd, index2offset(iptr->dst.varindex));
614 case ICMD_FSTORE: /* ..., value ==> ... */
615 /* op1 = local variable */
617 gen_ISTORE(cd, index2offset(iptr->dst.varindex));
620 case ICMD_DSTORE: /* ..., value ==> ... */
621 /* op1 = local variable */
623 gen_LSTORE(cd, index2offset(iptr->dst.varindex));
627 /* pop/dup/swap operations ********************************************/
629 case ICMD_POP: /* ..., value ==> ... */
634 case ICMD_POP2: /* ..., value, value ==> ... */
639 case ICMD_DUP: /* ..., a ==> ..., a, a */
644 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
649 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
654 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
659 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
664 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
669 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
675 /* integer operations *************************************************/
677 case ICMD_INEG: /* ..., value ==> ..., - value */
682 case ICMD_LNEG: /* ..., value ==> ..., - value */
687 case ICMD_I2L: /* ..., value ==> ..., value */
692 case ICMD_L2I: /* ..., value ==> ..., value */
697 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
702 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
707 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
713 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
718 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
723 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
728 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
733 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
738 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
743 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
748 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
753 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
758 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
763 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
764 /* val.i = constant */
766 gen_IDIVPOW2(cd, iptr->sx.val.i);
769 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
770 /* val.i = constant */
772 gen_IREMPOW2(cd, iptr->sx.val.i);
775 case ICMD_LDIVPOW2: /* ..., value ==> ..., value << constant */
776 /* val.i = constant */
778 gen_LDIVPOW2(cd, iptr->sx.val.i);
781 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
782 /* val.l = constant */
784 gen_LREMPOW2(cd, iptr->sx.val.i);
787 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
792 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
797 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
802 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
807 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
812 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
817 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
822 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
827 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
832 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
837 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
842 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
848 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
850 /* optimize LCMP .. IFxx (0) --> IF_LCMPxx */
852 if (len >= 2 && iptr[1].sx.val.i == 0) {
853 switch (iptr[1].opc) {
854 case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LCMPEQ; break;
855 case ICMD_IFNE: iptr[0].opc = ICMD_IF_LCMPNE; break;
856 case ICMD_IFLT: iptr[0].opc = ICMD_IF_LCMPLT; break;
857 case ICMD_IFLE: iptr[0].opc = ICMD_IF_LCMPLE; break;
858 case ICMD_IFGT: iptr[0].opc = ICMD_IF_LCMPGT; break;
859 case ICMD_IFGE: iptr[0].opc = ICMD_IF_LCMPGE; break;
860 default: goto dont_opt_IF_LCMPxx;
862 iptr[0].dst.insindex = iptr[1].dst.insindex;
863 iptr[1].opc = ICMD_NOP;
872 case ICMD_IINC: /* ..., value ==> ..., value + constant */
873 /* op1 = variable, val.i = constant */
875 gen_IINC(cd, index2offset(iptr->s1.varindex), iptr->sx.val.i);
879 /* floating operations ************************************************/
881 case ICMD_FNEG: /* ..., value ==> ..., - value */
886 case ICMD_DNEG: /* ..., value ==> ..., - value */
891 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
896 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
901 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
906 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
911 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
916 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
921 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
926 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
931 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
936 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
941 case ICMD_I2F: /* ..., value ==> ..., (float) value */
946 case ICMD_L2F: /* ..., value ==> ..., (float) value */
951 case ICMD_I2D: /* ..., value ==> ..., (double) value */
956 case ICMD_L2D: /* ..., value ==> ..., (double) value */
961 case ICMD_F2I: /* ..., value ==> ..., (int) value */
966 case ICMD_D2I: /* ..., value ==> ..., (int) value */
971 case ICMD_F2L: /* ..., value ==> ..., (long) value */
976 case ICMD_D2L: /* ..., value ==> ..., (long) value */
981 case ICMD_F2D: /* ..., value ==> ..., (double) value */
986 case ICMD_D2F: /* ..., value ==> ..., (float) value */
991 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
996 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1001 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1006 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1012 /* memory operations **************************************************/
1014 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1016 gen_ARRAYLENGTH(cd);
1019 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1024 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1029 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1034 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1039 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1044 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1045 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1050 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1056 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1061 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1062 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1067 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1072 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1077 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1078 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1083 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1089 case ICMD_GETSTATIC: /* ... ==> ..., value */
1090 /* op1 = type, val.a = field address */
1092 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1094 uf = iptr->sx.s23.s3.uf;
1095 fieldtype = uf->fieldref->parseddesc.fd->type;
1098 fi = iptr->sx.s23.s3.fmiref->p.field;
1100 fieldtype = fi->type;
1103 switch (fieldtype) {
1106 gen_PATCHER_GETSTATIC_INT(cd, 0, uf);
1107 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1108 gen_PATCHER_GETSTATIC_CLINIT_INT(cd, 0, fi);
1110 gen_GETSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1114 gen_PATCHER_GETSTATIC_FLOAT(cd, 0, uf);
1115 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1116 gen_PATCHER_GETSTATIC_CLINIT_FLOAT(cd, 0, fi);
1118 gen_GETSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1123 gen_PATCHER_GETSTATIC_LONG(cd, 0, uf);
1124 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1125 gen_PATCHER_GETSTATIC_CLINIT_LONG(cd, 0, fi);
1127 gen_GETSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1131 gen_PATCHER_GETSTATIC_CELL(cd, 0, uf);
1132 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1133 gen_PATCHER_GETSTATIC_CLINIT_CELL(cd, 0, fi);
1135 gen_GETSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1140 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1141 /* op1 = type, val.a = field address */
1143 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1145 uf = iptr->sx.s23.s3.uf;
1146 fieldtype = uf->fieldref->parseddesc.fd->type;
1149 fi = iptr->sx.s23.s3.fmiref->p.field;
1151 fieldtype = fi->type;
1154 switch (fieldtype) {
1157 gen_PATCHER_PUTSTATIC_INT(cd, 0, uf);
1158 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1159 gen_PATCHER_PUTSTATIC_CLINIT_INT(cd, 0, fi);
1161 gen_PUTSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1165 gen_PATCHER_PUTSTATIC_FLOAT(cd, 0, uf);
1166 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1167 gen_PATCHER_PUTSTATIC_CLINIT_FLOAT(cd, 0, fi);
1169 gen_PUTSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1174 gen_PATCHER_PUTSTATIC_LONG(cd, 0, uf);
1175 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1176 gen_PATCHER_PUTSTATIC_CLINIT_LONG(cd, 0, fi);
1178 gen_PUTSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1182 gen_PATCHER_PUTSTATIC_CELL(cd, 0, uf);
1183 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1184 gen_PATCHER_PUTSTATIC_CLINIT_CELL(cd, 0, fi);
1186 gen_PUTSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1192 case ICMD_GETFIELD: /* ... ==> ..., value */
1193 /* op1 = type, val.a = field address */
1195 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1197 uf = iptr->sx.s23.s3.uf;
1198 fieldtype = uf->fieldref->parseddesc.fd->type;
1201 fi = iptr->sx.s23.s3.fmiref->p.field;
1203 fieldtype = fi->type;
1206 switch (fieldtype) {
1209 gen_PATCHER_GETFIELD_INT(cd, 0, uf);
1211 gen_GETFIELD_INT(cd, fi->offset, fi);
1215 gen_PATCHER_GETFIELD_FLOAT(cd, 0, uf);
1217 gen_GETFIELD_FLOAT(cd, fi->offset, fi);
1222 gen_PATCHER_GETFIELD_LONG(cd, 0, uf);
1224 gen_GETFIELD_LONG(cd, fi->offset, fi);
1228 gen_PATCHER_GETFIELD_CELL(cd, 0, uf);
1230 gen_GETFIELD_CELL(cd, fi->offset, fi);
1235 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1236 /* op1 = type, val.a = field address */
1238 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1240 uf = iptr->sx.s23.s3.uf;
1241 fieldtype = uf->fieldref->parseddesc.fd->type;
1244 fi = iptr->sx.s23.s3.fmiref->p.field;
1246 fieldtype = fi->type;
1249 switch (fieldtype) {
1252 gen_PATCHER_PUTFIELD_INT(cd, 0, uf);
1254 gen_PUTFIELD_INT(cd, fi->offset, fi);
1258 gen_PATCHER_PUTFIELD_FLOAT(cd, 0, uf);
1260 gen_PUTFIELD_FLOAT(cd, fi->offset, fi);
1265 gen_PATCHER_PUTFIELD_LONG(cd, 0, uf);
1267 gen_PUTFIELD_LONG(cd, fi->offset, fi);
1271 gen_PATCHER_PUTFIELD_CELL(cd, 0, uf);
1273 gen_PUTFIELD_CELL(cd, fi->offset, fi);
1279 /* branch operations **************************************************/
1281 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1286 case ICMD_GOTO: /* ... ==> ... */
1287 /* op1 = target JavaVM pc */
1291 case ICMD_JSR: /* ... ==> ... */
1292 /* op1 = target JavaVM pc */
1295 codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex));
1298 case ICMD_RET: /* ... ==> ... */
1299 /* op1 = local variable */
1301 gen_RET(cd, index2offset(iptr->s1.varindex));
1304 case ICMD_IFNULL: /* ..., value ==> ... */
1305 /* op1 = target JavaVM pc */
1310 case ICMD_IFNONNULL: /* ..., value ==> ... */
1311 /* op1 = target JavaVM pc */
1313 gen_branch(IFNONNULL);
1316 case ICMD_IFEQ: /* ..., value ==> ... */
1317 /* op1 = target JavaVM pc, val.i = constant */
1319 if (iptr->sx.val.i == 0) {
1322 gen_ICONST(cd, iptr->sx.val.i);
1323 gen_branch(IF_ICMPEQ);
1327 case ICMD_IFLT: /* ..., value ==> ... */
1328 /* op1 = target JavaVM pc, val.i = constant */
1330 if (iptr->sx.val.i == 0) {
1333 gen_ICONST(cd, iptr->sx.val.i);
1334 gen_branch(IF_ICMPLT);
1338 case ICMD_IFLE: /* ..., value ==> ... */
1339 /* op1 = target JavaVM pc, val.i = constant */
1341 if (iptr->sx.val.i == 0) {
1344 gen_ICONST(cd, iptr->sx.val.i);
1345 gen_branch(IF_ICMPLE);
1349 case ICMD_IFNE: /* ..., value ==> ... */
1350 /* op1 = target JavaVM pc, val.i = constant */
1352 if (iptr->sx.val.i == 0) {
1355 gen_ICONST(cd, iptr->sx.val.i);
1356 gen_branch(IF_ICMPNE);
1360 case ICMD_IFGT: /* ..., value ==> ... */
1361 /* op1 = target JavaVM pc, val.i = constant */
1363 if (iptr->sx.val.i == 0) {
1366 gen_ICONST(cd, iptr->sx.val.i);
1367 gen_branch(IF_ICMPGT);
1371 case ICMD_IFGE: /* ..., value ==> ... */
1372 /* op1 = target JavaVM pc, val.i = constant */
1374 if (iptr->sx.val.i == 0) {
1377 gen_ICONST(cd, iptr->sx.val.i);
1378 gen_branch(IF_ICMPGE);
1383 case ICMD_IF_LEQ: /* ..., value ==> ... */
1384 /* op1 = target JavaVM pc, val.l = constant */
1386 gen_LCONST(cd, iptr->sx.val.l);
1387 gen_branch(IF_LCMPEQ);
1390 case ICMD_IF_LLT: /* ..., value ==> ... */
1391 /* op1 = target JavaVM pc, val.l = constant */
1393 gen_LCONST(cd, iptr->sx.val.l);
1394 gen_branch(IF_LCMPLT);
1397 case ICMD_IF_LLE: /* ..., value ==> ... */
1398 /* op1 = target JavaVM pc, val.l = constant */
1400 gen_LCONST(cd, iptr->sx.val.l);
1401 gen_branch(IF_LCMPLE);
1404 case ICMD_IF_LNE: /* ..., value ==> ... */
1405 /* op1 = target JavaVM pc, val.l = constant */
1407 gen_LCONST(cd, iptr->sx.val.l);
1408 gen_branch(IF_LCMPNE);
1411 case ICMD_IF_LGT: /* ..., value ==> ... */
1412 /* op1 = target JavaVM pc, val.l = constant */
1414 gen_LCONST(cd, iptr->sx.val.l);
1415 gen_branch(IF_LCMPGT);
1418 case ICMD_IF_LGE: /* ..., value ==> ... */
1419 /* op1 = target JavaVM pc, val.l = constant */
1421 gen_LCONST(cd, iptr->sx.val.l);
1422 gen_branch(IF_LCMPGE);
1425 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1426 /* op1 = target JavaVM pc */
1428 gen_branch(IF_LCMPEQ);
1431 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
1432 /* op1 = target JavaVM pc */
1434 gen_branch(IF_LCMPNE);
1437 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
1438 /* op1 = target JavaVM pc */
1440 gen_branch(IF_LCMPLT);
1443 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
1444 /* op1 = target JavaVM pc */
1446 gen_branch(IF_LCMPGT);
1449 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
1450 /* op1 = target JavaVM pc */
1452 gen_branch(IF_LCMPLE);
1455 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
1456 /* op1 = target JavaVM pc */
1458 gen_branch(IF_LCMPGE);
1462 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1463 /* op1 = target JavaVM pc */
1465 gen_branch(IF_ICMPEQ);
1468 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
1469 /* op1 = target JavaVM pc */
1471 gen_branch(IF_ACMPEQ);
1474 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
1475 /* op1 = target JavaVM pc */
1477 gen_branch(IF_ICMPNE);
1480 case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
1481 /* op1 = target JavaVM pc */
1483 gen_branch(IF_ACMPNE);
1486 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
1487 /* op1 = target JavaVM pc */
1489 gen_branch(IF_ICMPLT);
1492 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
1493 /* op1 = target JavaVM pc */
1495 gen_branch(IF_ICMPGT);
1498 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
1499 /* op1 = target JavaVM pc */
1501 gen_branch(IF_ICMPLE);
1504 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
1505 /* op1 = target JavaVM pc */
1507 gen_branch(IF_ICMPGE);
1511 case ICMD_ARETURN: /* ..., retvalue ==> ... */
1512 case ICMD_IRETURN: /* ..., retvalue ==> ... */
1513 case ICMD_FRETURN: /* ..., retvalue ==> ... */
1515 #if defined(ENABLE_THREADS)
1516 if (checksync && code_is_synchronized(code)) {
1517 if (m->flags & ACC_STATIC) {
1518 gen_ACONST(cd, (java_objectheader *) m->clazz);
1520 gen_ALOAD(cd, index2offset(m->maxlocals));
1522 gen_MONITOREXIT(cd);
1525 if (opt_verbosecall)
1526 gen_TRACERETURN(cd, m);
1528 gen_IRETURN(cd, index2offset(cd->stackframesize));
1531 case ICMD_LRETURN: /* ..., retvalue ==> ... */
1532 case ICMD_DRETURN: /* ..., retvalue ==> ... */
1534 #if defined(ENABLE_THREADS)
1535 if (checksync && code_is_synchronized(code)) {
1536 if (m->flags & ACC_STATIC) {
1537 gen_ACONST(cd, (java_objectheader *) m->clazz);
1539 gen_ALOAD(cd, index2offset(m->maxlocals));
1541 gen_MONITOREXIT(cd);
1544 if (opt_verbosecall)
1545 gen_TRACELRETURN(cd, m);
1547 gen_LRETURN(cd, index2offset(cd->stackframesize));
1550 case ICMD_RETURN: /* ... ==> ... */
1552 #if defined(ENABLE_THREADS)
1553 if (checksync && code_is_synchronized(code)) {
1554 if (m->flags & ACC_STATIC) {
1555 gen_ACONST(cd, (java_objectheader *) m->clazz);
1557 gen_ALOAD(cd, index2offset(m->maxlocals));
1559 gen_MONITOREXIT(cd);
1562 if (opt_verbosecall)
1563 gen_TRACERETURN(cd, m);
1565 gen_RETURN(cd, index2offset(cd->stackframesize));
1569 case ICMD_TABLESWITCH: /* ..., index ==> ... */
1572 branch_target_t *table;
1574 table = iptr->dst.table;
1576 l = iptr->sx.s23.s2.tablelow;
1577 i = iptr->sx.s23.s3.tablehigh;
1581 /* arguments: low, range, datasegment address, table
1582 offset in datasegment, default target */
1584 gen_TABLESWITCH(cd, l, i, NULL, 0, NULL);
1586 /* actually -3 cells offset */
1588 cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1590 cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1592 codegen_addreference(cd, BLOCK_OF(table[0].insindex));
1594 /* build jump table top down and use address of lowest entry */
1599 dseg_add_target(cd, BLOCK_OF(table->insindex));
1604 /* length of dataseg after last dseg_add_target is used by load */
1605 ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1609 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
1612 lookup_target_t *lookup;
1614 lookup = iptr->dst.lookup;
1616 i = iptr->sx.s23.s2.lookupcount;
1618 /* arguments: count, datasegment address, table offset in */
1619 /* datasegment, default target */
1620 gen_LOOKUPSWITCH(cd, i, NULL, 0, NULL);
1622 /* actually -3 cells offset */
1624 cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1626 cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1628 /* build jump table top down and use address of lowest entry */
1631 dseg_add_target(cd, BLOCK_OF(lookup->target.insindex));
1632 dseg_add_unique_address(cd, lookup->value);
1636 codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex));
1639 /* length of dataseg after last dseg_add_target is used by load */
1640 ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1644 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
1645 /* op1 = arg count val.a = builtintable entry */
1646 bte = iptr->sx.s23.s3.bte;
1648 for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
1649 builtin_gen *bg = &builtin_gen_table[i];
1650 if (bg->builtin == bte->fp) {
1652 goto gen_builtin_end;
1661 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
1662 /* op1 = arg count, val.a = method pointer */
1664 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1665 um = iptr->sx.s23.s3.um;
1666 md = um->methodref->parseddesc.md;
1667 gen_PATCHER_INVOKESTATIC(cd, 0, md->paramslots, um);
1670 lm = iptr->sx.s23.s3.fmiref->p.method;
1671 md = lm->parseddesc;
1672 gen_INVOKESTATIC(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1676 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1678 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1679 um = iptr->sx.s23.s3.um;
1680 md = um->methodref->parseddesc.md;
1681 gen_PATCHER_INVOKESPECIAL(cd, 0, md->paramslots, um);
1684 lm = iptr->sx.s23.s3.fmiref->p.method;
1685 md = lm->parseddesc;
1686 gen_INVOKESPECIAL(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1690 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
1692 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1693 um = iptr->sx.s23.s3.um;
1694 md = um->methodref->parseddesc.md;
1695 gen_PATCHER_INVOKEVIRTUAL(cd, 0, md->paramslots, um);
1698 lm = iptr->sx.s23.s3.fmiref->p.method;
1699 md = lm->parseddesc;
1701 s1 = OFFSET(vftbl_t, table[0]) +
1702 sizeof(methodptr) * lm->vftblindex;
1704 gen_INVOKEVIRTUAL(cd, s1, md->paramslots, lm);
1708 case ICMD_INVOKEINTERFACE:/* op1 = arg count, val.a = method pointer */
1710 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1711 um = iptr->sx.s23.s3.um;
1712 md = um->methodref->parseddesc.md;
1713 gen_PATCHER_INVOKEINTERFACE(cd, 0, 0, md->paramslots, um);
1716 lm = iptr->sx.s23.s3.fmiref->p.method;
1717 md = lm->parseddesc;
1719 s1 = OFFSET(vftbl_t, interfacetable[0]) -
1720 sizeof(methodptr*) * lm->clazz->index;
1722 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
1724 gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
1729 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
1730 /* op1: 0 == array, 1 == class */
1731 /* val.a: (classinfo *) superclass */
1733 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1734 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1735 gen_PATCHER_CHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1737 gen_CHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1740 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1741 gen_PATCHER_ARRAYCHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1743 gen_ARRAYCHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1747 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
1748 /* op1: 0 == array, 1 == class */
1749 /* val.a: (classinfo *) superclass */
1751 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1752 gen_PATCHER_INSTANCEOF(cd, NULL, iptr->sx.s23.s3.c.ref);
1754 gen_INSTANCEOF(cd, iptr->sx.s23.s3.c.cls, iptr->sx.s23.s3.c.ref);
1757 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
1758 /* op1 = dimension, val.a = class */
1760 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1761 gen_PATCHER_MULTIANEWARRAY(cd, NULL, iptr->s1.argcount, iptr->sx.s23.s3.c.ref);
1763 gen_MULTIANEWARRAY(cd, iptr->sx.s23.s3.c.cls, iptr->s1.argcount, NULL);
1767 exceptions_throw_internalerror("Unknown ICMD %d during code generation",
1772 } /* for instruction */
1776 } /* if (bptr->flags != BBDELETED) */
1777 } /* for basic block */
1779 dseg_createlinenumbertable(cd);
1784 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
1787 /* branch resolving (walk through all basic blocks) */
1789 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
1792 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
1793 gen_resolveanybranch(((u1*) jd->code->entrypoint) + brefs->branchpos,
1794 ((u1 *)jd->code->entrypoint) + bptr->mpc);
1798 /* everything's ok */
1804 /* createcompilerstub **********************************************************
1806 Creates a stub routine which calls the compiler.
1812 +-------------+ <-- stub
1815 | framesize | (in ptrint units, does not include return address)
1822 codeptr points either to TRANSLATE or to the translated threaded code
1824 all methods are called indirectly through methodptr
1826 *******************************************************************************/
1828 #define COMPILERSTUB_DATASIZE 2
1829 #define COMPILERSTUB_CODESIZE 4
1831 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
1834 u1 *intrp_createcompilerstub(methodinfo *m)
1842 s = CNEW(Inst, COMPILERSTUB_SIZE);
1844 /* set data pointer and code pointer */
1847 s = s + COMPILERSTUB_DATASIZE;
1849 /* The codeinfo pointer is actually a pointer to the
1850 methodinfo. This fakes a codeinfo structure. */
1853 d[1] = (Inst *) &d[0]; /* fake code->m */
1855 /* mark start of dump memory area */
1859 cd = DNEW(codegendata);
1860 cd->mcodeptr = (u1 *) s;
1861 cd->lastinstwithoutdispatch = ~0;
1862 cd->superstarts = NULL;
1864 genarg_ainst(cd, s + 2);
1866 if (m->flags & ACC_NATIVE) {
1867 stackframesize = m->parseddesc->paramslots;
1870 stackframesize = m->maxlocals;
1872 #if defined(ENABLE_THREADS)
1873 if (checksync && code_is_synchronized(code))
1874 stackframesize += 1;
1878 genarg_i(cd, stackframesize);
1881 gen_TRANSLATE(cd, m);
1885 vm_block_insert(cd->mcodeptr);
1888 #if defined(ENABLE_STATISTICS)
1890 count_cstub_len += COMPILERSTUB_SIZE;
1893 /* release dump area */
1901 #if defined(WITH_FFI)
1902 static ffi_type *cacaotype2ffitype(s4 cacaotype)
1904 switch (cacaotype) {
1906 #if SIZEOF_VOID_P == 8
1907 return &ffi_type_sint64;
1909 return &ffi_type_sint32;
1912 return &ffi_type_sint64;
1914 return &ffi_type_float;
1916 return &ffi_type_double;
1918 return &ffi_type_pointer;
1920 return &ffi_type_void;
1940 #if defined(WITH_FFI)
1941 static ffi_cif *createnativecif(methodinfo *m, methoddesc *nmd)
1943 methoddesc *md = m->parseddesc;
1944 ffi_cif *pcif = NEW(ffi_cif);
1945 ffi_type **types = MNEW(ffi_type *, nmd->paramcount);
1946 ffi_type **ptypes = types;
1949 /* pass env pointer */
1951 *ptypes++ = &ffi_type_pointer;
1953 /* for static methods, pass class pointer */
1955 if (m->flags & ACC_STATIC)
1956 *ptypes++ = &ffi_type_pointer;
1958 /* pass parameter to native function */
1960 for (i = 0; i < md->paramcount; i++)
1961 *ptypes++ = cacaotype2ffitype(md->paramtypes[i].type);
1963 assert(ptypes - types == nmd->paramcount);
1965 if (ffi_prep_cif(pcif, FFI_DEFAULT_ABI, nmd->paramcount, cacaotype2ffitype(md->returntype.type), types) != FFI_OK)
1973 u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
1979 #if defined(WITH_FFI)
1986 /* get required compiler data */
1993 /* determine stackframe size (in units of ptrint) */
1995 stackframesize = nmd->paramslots;
1997 /* create method header */
1999 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2000 (void) dseg_add_unique_s4(cd, stackframesize * SIZEOF_VOID_P); /*FrameSize*/
2001 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2002 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2003 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2004 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2005 dseg_addlinenumbertablesize(cd);
2006 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2008 #if defined(WITH_FFI)
2009 /* prepare ffi cif structure */
2011 cif = createnativecif(m, nmd);
2018 if (opt_verbosecall)
2019 gen_TRACECALL(cd, m);
2022 gen_PATCHER_NATIVECALL(cd, m, f, (u1 *)cif);
2024 if (opt_verbosecall)
2025 gen_TRACENATIVECALL(cd, m, f, (u1 *)cif);
2027 gen_NATIVECALL(cd, m, f, (u1 *)cif);
2035 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2038 return jd->code->entrypoint;
2042 /* call jni function */
2043 Cell *nativecall(functionptr f, methodinfo *m, Cell *sp, Inst *ra, Cell *fp, u1 *addrcif)
2045 #if defined(WITH_FFCALL)
2059 switch (md->returntype.type) {
2061 endsp = sp - 1 + md->paramslots;
2062 av_start_long(alist, f, endsp);
2065 endsp = sp - 2 + md->paramslots;
2066 av_start_longlong(alist, f, endsp);
2069 endsp = sp - 1 + md->paramslots;
2070 av_start_float(alist, f, endsp);
2073 endsp = sp - 2 + md->paramslots;
2074 av_start_double(alist, f, endsp);
2077 endsp = sp - 1 + md->paramslots;
2078 av_start_ptr(alist, f, void *, endsp);
2081 endsp = sp + md->paramslots;
2082 av_start_void(alist, f);
2088 av_ptr(alist, _Jv_JNIEnv *, VM_get_jnienv());
2090 if (m->flags & ACC_STATIC)
2091 av_ptr(alist, classinfo *, m->clazz);
2093 for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2094 switch (md->paramtypes[i].type) {
2101 av_longlong(alist, *(s8 *)p);
2105 av_float(alist, *((float *) p));
2109 av_double(alist, *(double *) p);
2113 av_ptr(alist, void *, *(void **) p);
2122 /* create stackframe info structure */
2124 codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2125 (u1 *) fp, (u1 *) ra);
2129 *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2134 #elif defined(WITH_FFI)
2135 methoddesc *md = m->parseddesc;
2137 void *values[md->paramcount + 2];
2138 void **pvalues = values;
2149 pcif = (ffi_cif *) addrcif;
2151 /* pass env pointer */
2153 penv = (_Jv_JNIEnv *) VM_get_jnienv();
2156 /* for static methods, pass class pointer */
2158 if (m->flags & ACC_STATIC)
2159 *pvalues++ = &m->clazz;
2161 /* pass parameter to native function */
2163 for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2164 if (IS_2_WORD_TYPE(md->paramtypes[i].type))
2172 /* calculate position of return value */
2174 if (md->returntype.type == TYPE_VOID)
2175 endsp = sp + md->paramslots;
2177 endsp = sp - (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1) + md->paramslots;
2181 /* create stackframe info structure */
2183 codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2184 (u1 *) fp, (u1 *) ra);
2186 ffi_call(pcif, FFI_FN(f), endsp, values);
2188 *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2197 u1 *createcalljavafunction(methodinfo *m)
2207 /* mark dump memory */
2211 /* allocate memory */
2215 tmpm = DNEW(methodinfo);
2216 cd = DNEW(codegendata);
2217 rd = DNEW(registerdata);
2224 /* Allocate codeinfo memory from the heap as we need to keep them. */
2226 jd->code = code_codeinfo_new(tmpm); /* XXX check allocation */
2228 /* setup code generation stuff */
2230 MSET(tmpm, 0, u1, sizeof(methodinfo));
2236 /* create method header */
2238 (void) dseg_add_unique_address(cd, NULL); /* CodeinfoPointer */
2239 (void) dseg_add_unique_s4(cd, md->paramslots * SIZEOF_VOID_P);/* FrameSize*/
2240 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2241 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2242 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2243 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2244 dseg_addlinenumbertablesize(cd);
2245 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2251 gen_INVOKESTATIC(cd, (Inst **)m->stubroutine, md->paramslots, 0);
2259 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2261 entrypoint = jd->code->entrypoint;
2263 /* release memory */
2272 * These are local overrides for various environment variables in Emacs.
2273 * Please do not remove this and leave it at the end of the file, where
2274 * Emacs will automagically detect them.
2275 * ---------------------------------------------------------------------
2278 * indent-tabs-mode: t
2282 * vim:noexpandtab:sw=4:ts=4: