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.hpp"
50 #include "vm/jit/builtin.hpp"
51 #include "vm/class.hpp"
52 #include "vm/exceptions.hpp"
53 #include "vm/global.h"
54 #include "vm/options.h"
57 #include "vm/jit/asmpart.h"
58 #include "vm/jit/codegen-common.hpp"
59 #include "vm/jit/dseg.h"
60 #include "vm/jit/jit.hpp"
61 #include "vm/jit/parse.h"
62 #include "vm/jit/patcher.h"
63 #include "vm/jit/stack.h"
64 #include "vm/jit/stacktrace.hpp"
67 #define gen_branch(_inst) { \
69 codegen_addreference(cd, BLOCK_OF(iptr->dst.insindex)); \
72 #define index2offset(_i) (-(_i) * SIZEOF_VOID_P)
74 /* functions used by cacao-gen.i */
76 void genarg_v(codegendata *cd1, Cell v)
78 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
79 *((Cell *) *mcodepp) = v;
83 void genarg_i(codegendata *cd1, s4 i)
85 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
86 *((Cell *) *mcodepp) = i;
90 void genarg_b(codegendata *cd1, s4 i)
95 void genarg_f(codegendata *cd1, float f)
103 void genarg_l(codegendata *cd1, s8 l)
105 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
106 vm_l2twoCell(l, ((Cell *) *mcodepp)[1], ((Cell *) *mcodepp)[0]);
110 void genarg_aRef(codegendata *cd1, java_objectheader *a)
112 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
113 *((java_objectheader **) *mcodepp) = a;
117 void genarg_aArray(codegendata *cd1, java_arrayheader *a)
119 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
120 *((java_arrayheader **) *mcodepp) = a;
124 void genarg_aaTarget(codegendata *cd1, Inst **a)
126 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
127 *((Inst ***) *mcodepp) = a;
131 void genarg_aClass(codegendata *cd1, classinfo *a)
133 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
134 *((classinfo **) *mcodepp) = a;
138 void genarg_acr(codegendata *cd1, constant_classref *a)
140 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
141 *((constant_classref **) *mcodepp) = a;
145 void genarg_addr(codegendata *cd1, u1 *a)
147 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
148 *((u1 **) *mcodepp) = a;
152 void genarg_af(codegendata *cd1, functionptr a)
154 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
155 *((functionptr *) *mcodepp) = a;
159 void genarg_afi(codegendata *cd1, fieldinfo *a)
161 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
162 *((fieldinfo **) *mcodepp) = a;
166 void genarg_am(codegendata *cd1, methodinfo *a)
168 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
169 *((methodinfo **) *mcodepp) = a;
173 void genarg_acell(codegendata *cd1, Cell *a)
175 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
176 *((Cell **) *mcodepp) = a;
180 void genarg_ainst(codegendata *cd1, Inst *a)
182 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
183 *((Inst **) *mcodepp) = a;
187 void genarg_auf(codegendata *cd1, unresolved_field *a)
189 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
190 *((unresolved_field **) *mcodepp) = a;
194 void genarg_aum(codegendata *cd1, unresolved_method *a)
196 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
197 *((unresolved_method **) *mcodepp) = a;
201 void genarg_avftbl(codegendata *cd1, vftbl_t *a)
203 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
204 *((vftbl_t **) *mcodepp) = a;
209 /* include the interpreter generation functions *******************************/
211 /* Do not use "java-gen.i", it does not work with builddir. */
212 #include <java-gen.i>
215 typedef void (*genfunctionptr) (codegendata *);
217 typedef struct builtin_gen builtin_gen;
224 struct builtin_gen builtin_gen_table[] = {
225 {BUILTIN_new, gen_NEW, },
226 {BUILTIN_newarray, gen_NEWARRAY, },
227 {BUILTIN_newarray_boolean, gen_NEWARRAY_BOOLEAN,},
228 {BUILTIN_newarray_byte, gen_NEWARRAY_BYTE, },
229 {BUILTIN_newarray_char, gen_NEWARRAY_CHAR, },
230 {BUILTIN_newarray_short, gen_NEWARRAY_SHORT, },
231 {BUILTIN_newarray_int, gen_NEWARRAY_INT, },
232 {BUILTIN_newarray_long, gen_NEWARRAY_LONG, },
233 {BUILTIN_newarray_float, gen_NEWARRAY_FLOAT, },
234 {BUILTIN_newarray_double, gen_NEWARRAY_DOUBLE, },
235 {BUILTIN_arrayinstanceof, gen_ARRAYINSTANCEOF, },
237 #if defined(ENABLE_THREADS)
238 {LOCK_monitor_enter, gen_MONITORENTER, },
239 {LOCK_monitor_exit, gen_MONITOREXIT, },
242 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
243 {BUILTIN_f2l, gen_F2L, },
246 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
247 {BUILTIN_d2l, gen_D2L, },
250 #if !(SUPPORT_FLOAT && SUPPORT_F2I)
251 {BUILTIN_f2i, gen_F2I, },
254 #if !(SUPPORT_DOUBLE && SUPPORT_D2I)
255 {BUILTIN_d2i, gen_D2I, },
258 #if !SUPPORT_DIVISION
259 {BUILTIN_idiv, gen_IDIV, },
260 {BUILTIN_irem, gen_IREM, },
263 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
264 {BUILTIN_ldiv, gen_LDIV, },
265 {BUILTIN_lrem, gen_LREM, },
268 {BUILTIN_frem, gen_FREM, },
269 {BUILTIN_drem, gen_DREM, },
273 /* codegen *********************************************************************
275 Generates machine code.
277 *******************************************************************************/
279 #define I(value) iptr[0].sx.val.i = (value); break;
281 bool intrp_codegen(jitdata *jd)
286 s4 i, len, s1, s2, d;
290 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
291 unresolved_method *um;
292 builtintable_entry *bte;
295 unresolved_field *uf;
298 /* get required compiler data */
304 /* prevent compiler warnings */
311 /* determine stackframe size (in units of ptrint slots) */
313 cd->stackframesize = m->maxlocals;
315 #if defined(ENABLE_THREADS)
316 if (checksync && code_is_synchronized(code))
317 cd->stackframesize += 1;
320 /* create method header */
322 (void) dseg_add_unique_address(cd, jd->code);
323 (void) dseg_add_unique_s4(cd, cd->stackframesize * SIZEOF_VOID_P);
325 code->synchronizedoffset = rd->memuse * 8;
327 /* REMOVEME: We still need it for exception handling in assembler. */
329 if (code_is_leafmethod(code))
330 (void) dseg_add_unique_s4(cd, 1);
332 (void) dseg_add_unique_s4(cd, 0);
334 (void) dseg_add_unique_s4(cd, 0);
335 (void) dseg_add_unique_s4(cd, 0);
337 dseg_addlinenumbertablesize(cd);
340 /* initialize mcode variables */
342 cd->mcodeptr = cd->mcodebase;
343 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
348 #if defined(ENABLE_THREADS)
349 if (checksync && code_is_synchronized(code)) {
350 if (m->flags & ACC_STATIC) {
351 gen_ACONST(cd, (java_objectheader *) m->clazz);
356 gen_ASTORE(cd, index2offset(m->maxlocals));
359 gen_MONITORENTER(cd);
364 gen_TRACECALL(cd, m);
368 /* walk through all basic blocks */
370 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
372 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
374 if (bptr->flags != BBDELETED) {
376 /* walk through all instructions */
382 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
383 if (iptr->line != currentline) {
384 dseg_addlinenumber(cd, iptr->line);
385 currentline = iptr->line;
388 MCODECHECK(64); /* an instruction usually needs < 64 words */
393 case ICMD_INLINE_START:
394 case ICMD_INLINE_END:
397 case ICMD_NOP: /* ... ==> ... */
400 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
405 /* constant operations ************************************************/
407 case ICMD_ICONST: /* ... ==> ..., constant */
408 /* op1 = 0, val.i = constant */
410 /* optimize ICONST (2^x) .. IREM --> IREMPOW2 (const) */
412 if (len >= 2 && iptr[1].opc == ICMD_IREM) {
413 switch (iptr[0].sx.val.i) {
414 case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
415 case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
416 case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
417 case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
418 case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
419 case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
420 case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
421 case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
422 iptr[0].opc = ICMD_IREMPOW2;
424 iptr[1].opc = ICMD_NOP;
429 /* optimize ICONST (2^x) .. IDIV --> IDIVPOW2 (const) */
431 if (len >= 2 && iptr[1].opc == ICMD_IDIV) {
432 switch (iptr[0].sx.val.i) {
433 case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
434 case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
435 case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
436 case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
437 case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
438 case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
439 case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
440 case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
441 default: goto dont_opt_IDIVPOW2;
443 iptr[0].opc = ICMD_IDIVPOW2;
444 iptr[1].opc = ICMD_NOP;
449 /* optimize ICONST .. IF_ICMPxx --> IFxx (const) */
452 switch (iptr[1].opc) {
453 case ICMD_IF_ICMPEQ: iptr[0].opc = ICMD_IFEQ; break;
454 case ICMD_IF_ICMPNE: iptr[0].opc = ICMD_IFNE; break;
455 case ICMD_IF_ICMPLT: iptr[0].opc = ICMD_IFLT; break;
456 case ICMD_IF_ICMPLE: iptr[0].opc = ICMD_IFLE; break;
457 case ICMD_IF_ICMPGT: iptr[0].opc = ICMD_IFGT; break;
458 case ICMD_IF_ICMPGE: iptr[0].opc = ICMD_IFGE; break;
459 default: goto dont_opt_IFxx;
461 iptr[0].dst.insindex = iptr[1].dst.insindex;
462 iptr[1].opc = ICMD_NOP;
467 gen_ICONST(cd, iptr->sx.val.i);
470 case ICMD_LCONST: /* ... ==> ..., constant */
471 /* op1 = 0, val.l = constant */
473 /* optimize LCONST (2^x) .. LREM --> LREMPOW2 (const) */
475 if (len >= 2 && iptr[1].opc == ICMD_LREM) {
476 switch (iptr[0].sx.val.l) {
477 case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
478 case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
479 case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
480 case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
481 case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
482 case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
483 case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
484 case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
485 iptr[0].opc = ICMD_LREMPOW2;
487 iptr[1].opc = ICMD_NOP;
492 /* optimize LCONST (2^x) .. LDIV --> LDIVPOW2 (const) */
494 if (len >= 2 && iptr[1].opc == ICMD_LDIV) {
495 switch (iptr[0].sx.val.l) {
496 case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
497 case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
498 case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
499 case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
500 case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
501 case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
502 case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
503 case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
504 default: goto dont_opt_LDIVPOW2;
506 iptr[0].opc = ICMD_LDIVPOW2;
507 iptr[1].opc = ICMD_NOP;
512 /* optimize LCONST .. LCMP .. IFxx (0) --> IF_Lxx */
514 if (len >= 3 && iptr[1].opc == ICMD_LCMP && iptr[2].sx.val.i == 0) {
515 switch (iptr[2].opc) {
516 case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LEQ; break;
517 case ICMD_IFNE: iptr[0].opc = ICMD_IF_LNE; break;
518 case ICMD_IFLT: iptr[0].opc = ICMD_IF_LLT; break;
519 case ICMD_IFLE: iptr[0].opc = ICMD_IF_LLE; break;
520 case ICMD_IFGT: iptr[0].opc = ICMD_IF_LGT; break;
521 case ICMD_IFGE: iptr[0].opc = ICMD_IF_LGE; break;
522 default: goto dont_opt_IF_Lxx;
524 iptr[0].dst.insindex = iptr[2].dst.insindex;
525 iptr[1].opc = ICMD_NOP;
526 iptr[2].opc = ICMD_NOP;
531 gen_LCONST(cd, iptr->sx.val.l);
534 case ICMD_FCONST: /* ... ==> ..., constant */
535 /* op1 = 0, val.f = constant */
539 vm_f2Cell(iptr->sx.val.f, fi);
544 case ICMD_DCONST: /* ... ==> ..., constant */
545 /* op1 = 0, val.d = constant */
547 gen_LCONST(cd, *(s8 *)&(iptr->sx.val.d));
550 case ICMD_ACONST: /* ... ==> ..., constant */
551 /* op1 = 0, val.a = constant */
553 if (INSTRUCTION_IS_UNRESOLVED(iptr))
554 gen_PATCHER_ACONST(cd, NULL, iptr->sx.val.c.ref);
556 gen_ACONST(cd, iptr->sx.val.anyptr);
560 /* load/store operations **********************************************/
562 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
563 /* op1 = local variable */
565 gen_ILOAD(cd, index2offset(iptr->s1.varindex));
568 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
569 /* op1 = local variable */
571 gen_LLOAD(cd, index2offset(iptr->s1.varindex));
574 case ICMD_ALOAD: /* ... ==> ..., content of local variable */
575 /* op1 = local variable */
577 gen_ALOAD(cd, index2offset(iptr->s1.varindex));
580 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
581 /* op1 = local variable */
583 gen_ILOAD(cd, index2offset(iptr->s1.varindex));
586 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
587 /* op1 = local variable */
589 gen_LLOAD(cd, index2offset(iptr->s1.varindex));
593 case ICMD_ISTORE: /* ..., value ==> ... */
594 /* op1 = local variable */
596 gen_ISTORE(cd, index2offset(iptr->dst.varindex));
599 case ICMD_LSTORE: /* ..., value ==> ... */
600 /* op1 = local variable */
602 gen_LSTORE(cd, index2offset(iptr->dst.varindex));
605 case ICMD_ASTORE: /* ..., value ==> ... */
606 /* op1 = local variable */
608 gen_ASTORE(cd, index2offset(iptr->dst.varindex));
612 case ICMD_FSTORE: /* ..., value ==> ... */
613 /* op1 = local variable */
615 gen_ISTORE(cd, index2offset(iptr->dst.varindex));
618 case ICMD_DSTORE: /* ..., value ==> ... */
619 /* op1 = local variable */
621 gen_LSTORE(cd, index2offset(iptr->dst.varindex));
625 /* pop/dup/swap operations ********************************************/
627 case ICMD_POP: /* ..., value ==> ... */
632 case ICMD_POP2: /* ..., value, value ==> ... */
637 case ICMD_DUP: /* ..., a ==> ..., a, a */
642 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
647 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
652 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
657 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
662 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
667 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
673 /* integer operations *************************************************/
675 case ICMD_INEG: /* ..., value ==> ..., - value */
680 case ICMD_LNEG: /* ..., value ==> ..., - value */
685 case ICMD_I2L: /* ..., value ==> ..., value */
690 case ICMD_L2I: /* ..., value ==> ..., value */
695 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
700 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
705 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
711 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
716 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
721 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
726 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
731 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
736 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
741 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
746 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
751 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
756 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
761 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
762 /* val.i = constant */
764 gen_IDIVPOW2(cd, iptr->sx.val.i);
767 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
768 /* val.i = constant */
770 gen_IREMPOW2(cd, iptr->sx.val.i);
773 case ICMD_LDIVPOW2: /* ..., value ==> ..., value << constant */
774 /* val.i = constant */
776 gen_LDIVPOW2(cd, iptr->sx.val.i);
779 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
780 /* val.l = constant */
782 gen_LREMPOW2(cd, iptr->sx.val.i);
785 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
790 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
795 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
800 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
805 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
810 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
815 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
820 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
825 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
830 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
835 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
840 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
846 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
848 /* optimize LCMP .. IFxx (0) --> IF_LCMPxx */
850 if (len >= 2 && iptr[1].sx.val.i == 0) {
851 switch (iptr[1].opc) {
852 case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LCMPEQ; break;
853 case ICMD_IFNE: iptr[0].opc = ICMD_IF_LCMPNE; break;
854 case ICMD_IFLT: iptr[0].opc = ICMD_IF_LCMPLT; break;
855 case ICMD_IFLE: iptr[0].opc = ICMD_IF_LCMPLE; break;
856 case ICMD_IFGT: iptr[0].opc = ICMD_IF_LCMPGT; break;
857 case ICMD_IFGE: iptr[0].opc = ICMD_IF_LCMPGE; break;
858 default: goto dont_opt_IF_LCMPxx;
860 iptr[0].dst.insindex = iptr[1].dst.insindex;
861 iptr[1].opc = ICMD_NOP;
870 case ICMD_IINC: /* ..., value ==> ..., value + constant */
871 /* op1 = variable, val.i = constant */
873 gen_IINC(cd, index2offset(iptr->s1.varindex), iptr->sx.val.i);
877 /* floating operations ************************************************/
879 case ICMD_FNEG: /* ..., value ==> ..., - value */
884 case ICMD_DNEG: /* ..., value ==> ..., - value */
889 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
894 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
899 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
904 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
909 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
914 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
919 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
924 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
929 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
934 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
939 case ICMD_I2F: /* ..., value ==> ..., (float) value */
944 case ICMD_L2F: /* ..., value ==> ..., (float) value */
949 case ICMD_I2D: /* ..., value ==> ..., (double) value */
954 case ICMD_L2D: /* ..., value ==> ..., (double) value */
959 case ICMD_F2I: /* ..., value ==> ..., (int) value */
964 case ICMD_D2I: /* ..., value ==> ..., (int) value */
969 case ICMD_F2L: /* ..., value ==> ..., (long) value */
974 case ICMD_D2L: /* ..., value ==> ..., (long) value */
979 case ICMD_F2D: /* ..., value ==> ..., (double) value */
984 case ICMD_D2F: /* ..., value ==> ..., (float) value */
989 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
994 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
999 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1004 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1010 /* memory operations **************************************************/
1012 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1014 gen_ARRAYLENGTH(cd);
1017 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1022 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1027 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1032 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1037 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1042 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1043 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1048 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1054 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1059 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1060 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1065 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1070 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1075 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1076 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1081 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1087 case ICMD_GETSTATIC: /* ... ==> ..., value */
1088 /* op1 = type, val.a = field address */
1090 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1092 uf = iptr->sx.s23.s3.uf;
1093 fieldtype = uf->fieldref->parseddesc.fd->type;
1096 fi = iptr->sx.s23.s3.fmiref->p.field;
1098 fieldtype = fi->type;
1101 switch (fieldtype) {
1104 gen_PATCHER_GETSTATIC_INT(cd, 0, uf);
1105 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1106 gen_PATCHER_GETSTATIC_CLINIT_INT(cd, 0, fi);
1108 gen_GETSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1112 gen_PATCHER_GETSTATIC_FLOAT(cd, 0, uf);
1113 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1114 gen_PATCHER_GETSTATIC_CLINIT_FLOAT(cd, 0, fi);
1116 gen_GETSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1121 gen_PATCHER_GETSTATIC_LONG(cd, 0, uf);
1122 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1123 gen_PATCHER_GETSTATIC_CLINIT_LONG(cd, 0, fi);
1125 gen_GETSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1129 gen_PATCHER_GETSTATIC_CELL(cd, 0, uf);
1130 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1131 gen_PATCHER_GETSTATIC_CLINIT_CELL(cd, 0, fi);
1133 gen_GETSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1138 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1139 /* op1 = type, val.a = field address */
1141 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1143 uf = iptr->sx.s23.s3.uf;
1144 fieldtype = uf->fieldref->parseddesc.fd->type;
1147 fi = iptr->sx.s23.s3.fmiref->p.field;
1149 fieldtype = fi->type;
1152 switch (fieldtype) {
1155 gen_PATCHER_PUTSTATIC_INT(cd, 0, uf);
1156 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1157 gen_PATCHER_PUTSTATIC_CLINIT_INT(cd, 0, fi);
1159 gen_PUTSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1163 gen_PATCHER_PUTSTATIC_FLOAT(cd, 0, uf);
1164 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1165 gen_PATCHER_PUTSTATIC_CLINIT_FLOAT(cd, 0, fi);
1167 gen_PUTSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1172 gen_PATCHER_PUTSTATIC_LONG(cd, 0, uf);
1173 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1174 gen_PATCHER_PUTSTATIC_CLINIT_LONG(cd, 0, fi);
1176 gen_PUTSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1180 gen_PATCHER_PUTSTATIC_CELL(cd, 0, uf);
1181 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1182 gen_PATCHER_PUTSTATIC_CLINIT_CELL(cd, 0, fi);
1184 gen_PUTSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1190 case ICMD_GETFIELD: /* ... ==> ..., value */
1191 /* op1 = type, val.a = field address */
1193 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1195 uf = iptr->sx.s23.s3.uf;
1196 fieldtype = uf->fieldref->parseddesc.fd->type;
1199 fi = iptr->sx.s23.s3.fmiref->p.field;
1201 fieldtype = fi->type;
1204 switch (fieldtype) {
1207 gen_PATCHER_GETFIELD_INT(cd, 0, uf);
1209 gen_GETFIELD_INT(cd, fi->offset, fi);
1213 gen_PATCHER_GETFIELD_FLOAT(cd, 0, uf);
1215 gen_GETFIELD_FLOAT(cd, fi->offset, fi);
1220 gen_PATCHER_GETFIELD_LONG(cd, 0, uf);
1222 gen_GETFIELD_LONG(cd, fi->offset, fi);
1226 gen_PATCHER_GETFIELD_CELL(cd, 0, uf);
1228 gen_GETFIELD_CELL(cd, fi->offset, fi);
1233 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1234 /* op1 = type, val.a = field address */
1236 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1238 uf = iptr->sx.s23.s3.uf;
1239 fieldtype = uf->fieldref->parseddesc.fd->type;
1242 fi = iptr->sx.s23.s3.fmiref->p.field;
1244 fieldtype = fi->type;
1247 switch (fieldtype) {
1250 gen_PATCHER_PUTFIELD_INT(cd, 0, uf);
1252 gen_PUTFIELD_INT(cd, fi->offset, fi);
1256 gen_PATCHER_PUTFIELD_FLOAT(cd, 0, uf);
1258 gen_PUTFIELD_FLOAT(cd, fi->offset, fi);
1263 gen_PATCHER_PUTFIELD_LONG(cd, 0, uf);
1265 gen_PUTFIELD_LONG(cd, fi->offset, fi);
1269 gen_PATCHER_PUTFIELD_CELL(cd, 0, uf);
1271 gen_PUTFIELD_CELL(cd, fi->offset, fi);
1277 /* branch operations **************************************************/
1279 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1284 case ICMD_GOTO: /* ... ==> ... */
1285 /* op1 = target JavaVM pc */
1289 case ICMD_JSR: /* ... ==> ... */
1290 /* op1 = target JavaVM pc */
1293 codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex));
1296 case ICMD_RET: /* ... ==> ... */
1297 /* op1 = local variable */
1299 gen_RET(cd, index2offset(iptr->s1.varindex));
1302 case ICMD_IFNULL: /* ..., value ==> ... */
1303 /* op1 = target JavaVM pc */
1308 case ICMD_IFNONNULL: /* ..., value ==> ... */
1309 /* op1 = target JavaVM pc */
1311 gen_branch(IFNONNULL);
1314 case ICMD_IFEQ: /* ..., value ==> ... */
1315 /* op1 = target JavaVM pc, val.i = constant */
1317 if (iptr->sx.val.i == 0) {
1320 gen_ICONST(cd, iptr->sx.val.i);
1321 gen_branch(IF_ICMPEQ);
1325 case ICMD_IFLT: /* ..., value ==> ... */
1326 /* op1 = target JavaVM pc, val.i = constant */
1328 if (iptr->sx.val.i == 0) {
1331 gen_ICONST(cd, iptr->sx.val.i);
1332 gen_branch(IF_ICMPLT);
1336 case ICMD_IFLE: /* ..., value ==> ... */
1337 /* op1 = target JavaVM pc, val.i = constant */
1339 if (iptr->sx.val.i == 0) {
1342 gen_ICONST(cd, iptr->sx.val.i);
1343 gen_branch(IF_ICMPLE);
1347 case ICMD_IFNE: /* ..., value ==> ... */
1348 /* op1 = target JavaVM pc, val.i = constant */
1350 if (iptr->sx.val.i == 0) {
1353 gen_ICONST(cd, iptr->sx.val.i);
1354 gen_branch(IF_ICMPNE);
1358 case ICMD_IFGT: /* ..., value ==> ... */
1359 /* op1 = target JavaVM pc, val.i = constant */
1361 if (iptr->sx.val.i == 0) {
1364 gen_ICONST(cd, iptr->sx.val.i);
1365 gen_branch(IF_ICMPGT);
1369 case ICMD_IFGE: /* ..., value ==> ... */
1370 /* op1 = target JavaVM pc, val.i = constant */
1372 if (iptr->sx.val.i == 0) {
1375 gen_ICONST(cd, iptr->sx.val.i);
1376 gen_branch(IF_ICMPGE);
1381 case ICMD_IF_LEQ: /* ..., value ==> ... */
1382 /* op1 = target JavaVM pc, val.l = constant */
1384 gen_LCONST(cd, iptr->sx.val.l);
1385 gen_branch(IF_LCMPEQ);
1388 case ICMD_IF_LLT: /* ..., value ==> ... */
1389 /* op1 = target JavaVM pc, val.l = constant */
1391 gen_LCONST(cd, iptr->sx.val.l);
1392 gen_branch(IF_LCMPLT);
1395 case ICMD_IF_LLE: /* ..., value ==> ... */
1396 /* op1 = target JavaVM pc, val.l = constant */
1398 gen_LCONST(cd, iptr->sx.val.l);
1399 gen_branch(IF_LCMPLE);
1402 case ICMD_IF_LNE: /* ..., value ==> ... */
1403 /* op1 = target JavaVM pc, val.l = constant */
1405 gen_LCONST(cd, iptr->sx.val.l);
1406 gen_branch(IF_LCMPNE);
1409 case ICMD_IF_LGT: /* ..., value ==> ... */
1410 /* op1 = target JavaVM pc, val.l = constant */
1412 gen_LCONST(cd, iptr->sx.val.l);
1413 gen_branch(IF_LCMPGT);
1416 case ICMD_IF_LGE: /* ..., value ==> ... */
1417 /* op1 = target JavaVM pc, val.l = constant */
1419 gen_LCONST(cd, iptr->sx.val.l);
1420 gen_branch(IF_LCMPGE);
1423 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1424 /* op1 = target JavaVM pc */
1426 gen_branch(IF_LCMPEQ);
1429 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
1430 /* op1 = target JavaVM pc */
1432 gen_branch(IF_LCMPNE);
1435 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
1436 /* op1 = target JavaVM pc */
1438 gen_branch(IF_LCMPLT);
1441 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
1442 /* op1 = target JavaVM pc */
1444 gen_branch(IF_LCMPGT);
1447 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
1448 /* op1 = target JavaVM pc */
1450 gen_branch(IF_LCMPLE);
1453 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
1454 /* op1 = target JavaVM pc */
1456 gen_branch(IF_LCMPGE);
1460 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1461 /* op1 = target JavaVM pc */
1463 gen_branch(IF_ICMPEQ);
1466 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
1467 /* op1 = target JavaVM pc */
1469 gen_branch(IF_ACMPEQ);
1472 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
1473 /* op1 = target JavaVM pc */
1475 gen_branch(IF_ICMPNE);
1478 case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
1479 /* op1 = target JavaVM pc */
1481 gen_branch(IF_ACMPNE);
1484 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
1485 /* op1 = target JavaVM pc */
1487 gen_branch(IF_ICMPLT);
1490 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
1491 /* op1 = target JavaVM pc */
1493 gen_branch(IF_ICMPGT);
1496 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
1497 /* op1 = target JavaVM pc */
1499 gen_branch(IF_ICMPLE);
1502 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
1503 /* op1 = target JavaVM pc */
1505 gen_branch(IF_ICMPGE);
1509 case ICMD_ARETURN: /* ..., retvalue ==> ... */
1510 case ICMD_IRETURN: /* ..., retvalue ==> ... */
1511 case ICMD_FRETURN: /* ..., retvalue ==> ... */
1513 #if defined(ENABLE_THREADS)
1514 if (checksync && code_is_synchronized(code)) {
1515 if (m->flags & ACC_STATIC) {
1516 gen_ACONST(cd, (java_objectheader *) m->clazz);
1518 gen_ALOAD(cd, index2offset(m->maxlocals));
1520 gen_MONITOREXIT(cd);
1523 if (opt_verbosecall)
1524 gen_TRACERETURN(cd, m);
1526 gen_IRETURN(cd, index2offset(cd->stackframesize));
1529 case ICMD_LRETURN: /* ..., retvalue ==> ... */
1530 case ICMD_DRETURN: /* ..., retvalue ==> ... */
1532 #if defined(ENABLE_THREADS)
1533 if (checksync && code_is_synchronized(code)) {
1534 if (m->flags & ACC_STATIC) {
1535 gen_ACONST(cd, (java_objectheader *) m->clazz);
1537 gen_ALOAD(cd, index2offset(m->maxlocals));
1539 gen_MONITOREXIT(cd);
1542 if (opt_verbosecall)
1543 gen_TRACELRETURN(cd, m);
1545 gen_LRETURN(cd, index2offset(cd->stackframesize));
1548 case ICMD_RETURN: /* ... ==> ... */
1550 #if defined(ENABLE_THREADS)
1551 if (checksync && code_is_synchronized(code)) {
1552 if (m->flags & ACC_STATIC) {
1553 gen_ACONST(cd, (java_objectheader *) m->clazz);
1555 gen_ALOAD(cd, index2offset(m->maxlocals));
1557 gen_MONITOREXIT(cd);
1560 if (opt_verbosecall)
1561 gen_TRACERETURN(cd, m);
1563 gen_RETURN(cd, index2offset(cd->stackframesize));
1567 case ICMD_TABLESWITCH: /* ..., index ==> ... */
1570 branch_target_t *table;
1572 table = iptr->dst.table;
1574 l = iptr->sx.s23.s2.tablelow;
1575 i = iptr->sx.s23.s3.tablehigh;
1579 /* arguments: low, range, datasegment address, table
1580 offset in datasegment, default target */
1582 gen_TABLESWITCH(cd, l, i, NULL, 0, NULL);
1584 /* actually -3 cells offset */
1586 cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1588 cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1590 codegen_addreference(cd, BLOCK_OF(table[0].insindex));
1592 /* build jump table top down and use address of lowest entry */
1597 dseg_add_target(cd, BLOCK_OF(table->insindex));
1602 /* length of dataseg after last dseg_add_target is used by load */
1603 ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1607 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
1610 lookup_target_t *lookup;
1612 lookup = iptr->dst.lookup;
1614 i = iptr->sx.s23.s2.lookupcount;
1616 /* arguments: count, datasegment address, table offset in */
1617 /* datasegment, default target */
1618 gen_LOOKUPSWITCH(cd, i, NULL, 0, NULL);
1620 /* actually -3 cells offset */
1622 cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1624 cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1626 /* build jump table top down and use address of lowest entry */
1629 dseg_add_target(cd, BLOCK_OF(lookup->target.insindex));
1630 dseg_add_unique_address(cd, lookup->value);
1634 codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex));
1637 /* length of dataseg after last dseg_add_target is used by load */
1638 ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1642 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
1643 /* op1 = arg count val.a = builtintable entry */
1644 bte = iptr->sx.s23.s3.bte;
1646 for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
1647 builtin_gen *bg = &builtin_gen_table[i];
1648 if (bg->builtin == bte->fp) {
1650 goto gen_builtin_end;
1659 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
1660 /* op1 = arg count, val.a = method pointer */
1662 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1663 um = iptr->sx.s23.s3.um;
1664 md = um->methodref->parseddesc.md;
1665 gen_PATCHER_INVOKESTATIC(cd, 0, md->paramslots, um);
1668 lm = iptr->sx.s23.s3.fmiref->p.method;
1669 md = lm->parseddesc;
1670 gen_INVOKESTATIC(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1674 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1676 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1677 um = iptr->sx.s23.s3.um;
1678 md = um->methodref->parseddesc.md;
1679 gen_PATCHER_INVOKESPECIAL(cd, 0, md->paramslots, um);
1682 lm = iptr->sx.s23.s3.fmiref->p.method;
1683 md = lm->parseddesc;
1684 gen_INVOKESPECIAL(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1688 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
1690 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1691 um = iptr->sx.s23.s3.um;
1692 md = um->methodref->parseddesc.md;
1693 gen_PATCHER_INVOKEVIRTUAL(cd, 0, md->paramslots, um);
1696 lm = iptr->sx.s23.s3.fmiref->p.method;
1697 md = lm->parseddesc;
1699 s1 = OFFSET(vftbl_t, table[0]) +
1700 sizeof(methodptr) * lm->vftblindex;
1702 gen_INVOKEVIRTUAL(cd, s1, md->paramslots, lm);
1706 case ICMD_INVOKEINTERFACE:/* op1 = arg count, val.a = method pointer */
1708 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1709 um = iptr->sx.s23.s3.um;
1710 md = um->methodref->parseddesc.md;
1711 gen_PATCHER_INVOKEINTERFACE(cd, 0, 0, md->paramslots, um);
1714 lm = iptr->sx.s23.s3.fmiref->p.method;
1715 md = lm->parseddesc;
1717 s1 = OFFSET(vftbl_t, interfacetable[0]) -
1718 sizeof(methodptr*) * lm->clazz->index;
1720 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
1722 gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
1727 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
1728 /* op1: 0 == array, 1 == class */
1729 /* val.a: (classinfo *) superclass */
1731 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1732 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1733 gen_PATCHER_CHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1735 gen_CHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1738 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1739 gen_PATCHER_ARRAYCHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1741 gen_ARRAYCHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1745 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
1746 /* op1: 0 == array, 1 == class */
1747 /* val.a: (classinfo *) superclass */
1749 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1750 gen_PATCHER_INSTANCEOF(cd, NULL, iptr->sx.s23.s3.c.ref);
1752 gen_INSTANCEOF(cd, iptr->sx.s23.s3.c.cls, iptr->sx.s23.s3.c.ref);
1755 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
1756 /* op1 = dimension, val.a = class */
1758 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1759 gen_PATCHER_MULTIANEWARRAY(cd, NULL, iptr->s1.argcount, iptr->sx.s23.s3.c.ref);
1761 gen_MULTIANEWARRAY(cd, iptr->sx.s23.s3.c.cls, iptr->s1.argcount, NULL);
1765 exceptions_throw_internalerror("Unknown ICMD %d during code generation",
1770 } /* for instruction */
1774 } /* if (bptr->flags != BBDELETED) */
1775 } /* for basic block */
1777 dseg_createlinenumbertable(cd);
1782 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
1785 /* branch resolving (walk through all basic blocks) */
1787 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
1790 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
1791 gen_resolveanybranch(((u1*) jd->code->entrypoint) + brefs->branchpos,
1792 ((u1 *)jd->code->entrypoint) + bptr->mpc);
1796 /* everything's ok */
1802 /* createcompilerstub **********************************************************
1804 Creates a stub routine which calls the compiler.
1810 +-------------+ <-- stub
1813 | framesize | (in ptrint units, does not include return address)
1820 codeptr points either to TRANSLATE or to the translated threaded code
1822 all methods are called indirectly through methodptr
1824 *******************************************************************************/
1826 #define COMPILERSTUB_DATASIZE 2
1827 #define COMPILERSTUB_CODESIZE 4
1829 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
1832 u1 *intrp_createcompilerstub(methodinfo *m)
1840 s = CNEW(Inst, COMPILERSTUB_SIZE);
1842 /* set data pointer and code pointer */
1845 s = s + COMPILERSTUB_DATASIZE;
1847 /* The codeinfo pointer is actually a pointer to the
1848 methodinfo. This fakes a codeinfo structure. */
1851 d[1] = (Inst *) &d[0]; /* fake code->m */
1853 /* mark start of dump memory area */
1857 cd = DNEW(codegendata);
1858 cd->mcodeptr = (u1 *) s;
1859 cd->lastinstwithoutdispatch = ~0;
1860 cd->superstarts = NULL;
1862 genarg_ainst(cd, s + 2);
1864 if (m->flags & ACC_NATIVE) {
1865 stackframesize = m->parseddesc->paramslots;
1868 stackframesize = m->maxlocals;
1870 #if defined(ENABLE_THREADS)
1871 if (checksync && code_is_synchronized(code))
1872 stackframesize += 1;
1876 genarg_i(cd, stackframesize);
1879 gen_TRANSLATE(cd, m);
1883 vm_block_insert(cd->mcodeptr);
1886 #if defined(ENABLE_STATISTICS)
1888 count_cstub_len += COMPILERSTUB_SIZE;
1891 /* release dump area */
1899 #if defined(WITH_FFI)
1900 static ffi_type *cacaotype2ffitype(s4 cacaotype)
1902 switch (cacaotype) {
1904 #if SIZEOF_VOID_P == 8
1905 return &ffi_type_sint64;
1907 return &ffi_type_sint32;
1910 return &ffi_type_sint64;
1912 return &ffi_type_float;
1914 return &ffi_type_double;
1916 return &ffi_type_pointer;
1918 return &ffi_type_void;
1938 #if defined(WITH_FFI)
1939 static ffi_cif *createnativecif(methodinfo *m, methoddesc *nmd)
1941 methoddesc *md = m->parseddesc;
1942 ffi_cif *pcif = NEW(ffi_cif);
1943 ffi_type **types = MNEW(ffi_type *, nmd->paramcount);
1944 ffi_type **ptypes = types;
1947 /* pass env pointer */
1949 *ptypes++ = &ffi_type_pointer;
1951 /* for static methods, pass class pointer */
1953 if (m->flags & ACC_STATIC)
1954 *ptypes++ = &ffi_type_pointer;
1956 /* pass parameter to native function */
1958 for (i = 0; i < md->paramcount; i++)
1959 *ptypes++ = cacaotype2ffitype(md->paramtypes[i].type);
1961 assert(ptypes - types == nmd->paramcount);
1963 if (ffi_prep_cif(pcif, FFI_DEFAULT_ABI, nmd->paramcount, cacaotype2ffitype(md->returntype.type), types) != FFI_OK)
1971 u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
1977 #if defined(WITH_FFI)
1984 /* get required compiler data */
1991 /* determine stackframe size (in units of ptrint) */
1993 stackframesize = nmd->paramslots;
1995 /* create method header */
1997 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
1998 (void) dseg_add_unique_s4(cd, stackframesize * SIZEOF_VOID_P); /*FrameSize*/
1999 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2000 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2001 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2002 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2003 dseg_addlinenumbertablesize(cd);
2004 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2006 #if defined(WITH_FFI)
2007 /* prepare ffi cif structure */
2009 cif = createnativecif(m, nmd);
2016 if (opt_verbosecall)
2017 gen_TRACECALL(cd, m);
2020 gen_PATCHER_NATIVECALL(cd, m, f, (u1 *)cif);
2022 if (opt_verbosecall)
2023 gen_TRACENATIVECALL(cd, m, f, (u1 *)cif);
2025 gen_NATIVECALL(cd, m, f, (u1 *)cif);
2033 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2036 return jd->code->entrypoint;
2040 /* call jni function */
2041 Cell *nativecall(functionptr f, methodinfo *m, Cell *sp, Inst *ra, Cell *fp, u1 *addrcif)
2043 #if defined(WITH_FFCALL)
2057 switch (md->returntype.type) {
2059 endsp = sp - 1 + md->paramslots;
2060 av_start_long(alist, f, endsp);
2063 endsp = sp - 2 + md->paramslots;
2064 av_start_longlong(alist, f, endsp);
2067 endsp = sp - 1 + md->paramslots;
2068 av_start_float(alist, f, endsp);
2071 endsp = sp - 2 + md->paramslots;
2072 av_start_double(alist, f, endsp);
2075 endsp = sp - 1 + md->paramslots;
2076 av_start_ptr(alist, f, void *, endsp);
2079 endsp = sp + md->paramslots;
2080 av_start_void(alist, f);
2086 av_ptr(alist, _Jv_JNIEnv *, VM_get_jnienv());
2088 if (m->flags & ACC_STATIC)
2089 av_ptr(alist, classinfo *, m->clazz);
2091 for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2092 switch (md->paramtypes[i].type) {
2099 av_longlong(alist, *(s8 *)p);
2103 av_float(alist, *((float *) p));
2107 av_double(alist, *(double *) p);
2111 av_ptr(alist, void *, *(void **) p);
2120 /* create stackframe info structure */
2122 codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2123 (u1 *) fp, (u1 *) ra);
2127 *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2132 #elif defined(WITH_FFI)
2133 methoddesc *md = m->parseddesc;
2135 void *values[md->paramcount + 2];
2136 void **pvalues = values;
2147 pcif = (ffi_cif *) addrcif;
2149 /* pass env pointer */
2151 penv = (_Jv_JNIEnv *) VM_get_jnienv();
2154 /* for static methods, pass class pointer */
2156 if (m->flags & ACC_STATIC)
2157 *pvalues++ = &m->clazz;
2159 /* pass parameter to native function */
2161 for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2162 if (IS_2_WORD_TYPE(md->paramtypes[i].type))
2170 /* calculate position of return value */
2172 if (md->returntype.type == TYPE_VOID)
2173 endsp = sp + md->paramslots;
2175 endsp = sp - (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1) + md->paramslots;
2179 /* create stackframe info structure */
2181 codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2182 (u1 *) fp, (u1 *) ra);
2184 ffi_call(pcif, FFI_FN(f), endsp, values);
2186 *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2195 u1 *createcalljavafunction(methodinfo *m)
2205 /* mark dump memory */
2209 /* allocate memory */
2213 tmpm = DNEW(methodinfo);
2214 cd = DNEW(codegendata);
2215 rd = DNEW(registerdata);
2222 /* Allocate codeinfo memory from the heap as we need to keep them. */
2224 jd->code = code_codeinfo_new(tmpm); /* XXX check allocation */
2226 /* setup code generation stuff */
2228 MSET(tmpm, 0, u1, sizeof(methodinfo));
2234 /* create method header */
2236 (void) dseg_add_unique_address(cd, NULL); /* CodeinfoPointer */
2237 (void) dseg_add_unique_s4(cd, md->paramslots * SIZEOF_VOID_P);/* FrameSize*/
2238 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2239 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2240 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2241 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2242 dseg_addlinenumbertablesize(cd);
2243 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2249 gen_INVOKESTATIC(cd, (Inst **)m->stubroutine, md->paramslots, 0);
2257 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2259 entrypoint = jd->code->entrypoint;
2261 /* release memory */
2270 * These are local overrides for various environment variables in Emacs.
2271 * Please do not remove this and leave it at the end of the file, where
2272 * Emacs will automagically detect them.
2273 * ---------------------------------------------------------------------
2276 * indent-tabs-mode: t
2280 * vim:noexpandtab:sw=4:ts=4: