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
31 $Id: codegen.c 5980 2006-11-15 12:25:13Z twisti $
43 #elif defined(WITH_FFCALL)
46 # error neither WITH_FFI nor WITH_FFCALL defined
53 #include "vm/jit/intrp/codegen.h"
54 #include "vm/jit/intrp/intrp.h"
56 #include "native/native.h"
57 #include "vm/builtin.h"
59 #include "vm/exceptions.h"
60 #include "vm/global.h"
61 #include "vm/options.h"
62 #include "vm/stringlocal.h"
64 #include "vm/jit/asmpart.h"
65 #include "vm/jit/codegen-common.h"
66 #include "vm/jit/dseg.h"
67 #include "vm/jit/jit.h"
68 #include "vm/jit/parse.h"
69 #include "vm/jit/patcher.h"
70 #include "vm/jit/stack.h"
73 #define gen_branch(_inst) { \
75 codegen_addreference(cd, BLOCK_OF(iptr->dst.insindex)); \
78 #define index2offset(_i) (-(_i) * SIZEOF_VOID_P)
80 /* functions used by cacao-gen.i */
82 void genarg_v(codegendata *cd1, Cell v)
84 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
85 *((Cell *) *mcodepp) = v;
89 void genarg_i(codegendata *cd1, s4 i)
91 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
92 *((Cell *) *mcodepp) = i;
96 void genarg_b(codegendata *cd1, s4 i)
101 void genarg_f(codegendata *cd1, float f)
109 void genarg_l(codegendata *cd1, s8 l)
111 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
112 vm_l2twoCell(l, ((Cell *) *mcodepp)[1], ((Cell *) *mcodepp)[0]);
116 void genarg_aRef(codegendata *cd1, java_objectheader *a)
118 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
119 *((java_objectheader **) *mcodepp) = a;
123 void genarg_aArray(codegendata *cd1, java_arrayheader *a)
125 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
126 *((java_arrayheader **) *mcodepp) = a;
130 void genarg_aaTarget(codegendata *cd1, Inst **a)
132 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
133 *((Inst ***) *mcodepp) = a;
137 void genarg_aClass(codegendata *cd1, classinfo *a)
139 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
140 *((classinfo **) *mcodepp) = a;
144 void genarg_acr(codegendata *cd1, constant_classref *a)
146 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
147 *((constant_classref **) *mcodepp) = a;
151 void genarg_addr(codegendata *cd1, u1 *a)
153 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
154 *((u1 **) *mcodepp) = a;
158 void genarg_af(codegendata *cd1, functionptr a)
160 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
161 *((functionptr *) *mcodepp) = a;
165 void genarg_afi(codegendata *cd1, fieldinfo *a)
167 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
168 *((fieldinfo **) *mcodepp) = a;
172 void genarg_am(codegendata *cd1, methodinfo *a)
174 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
175 *((methodinfo **) *mcodepp) = a;
179 void genarg_acell(codegendata *cd1, Cell *a)
181 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
182 *((Cell **) *mcodepp) = a;
186 void genarg_ainst(codegendata *cd1, Inst *a)
188 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
189 *((Inst **) *mcodepp) = a;
193 void genarg_auf(codegendata *cd1, unresolved_field *a)
195 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
196 *((unresolved_field **) *mcodepp) = a;
200 void genarg_aum(codegendata *cd1, unresolved_method *a)
202 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
203 *((unresolved_method **) *mcodepp) = a;
207 void genarg_avftbl(codegendata *cd1, vftbl_t *a)
209 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
210 *((vftbl_t **) *mcodepp) = a;
215 /* include the interpreter generation functions *******************************/
217 /* Do not use "java-gen.i", it does not work with builddir. */
218 #include <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 #define I(value) iptr[0].sx.val.i = (value); break;
287 bool intrp_codegen(jitdata *jd)
292 s4 i, len, s1, s2, d;
297 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
298 unresolved_method *um;
299 builtintable_entry *bte;
302 unresolved_field *uf;
305 /* get required compiler data */
311 /* prevent compiler warnings */
318 /* determine stackframe size (in units of ptrint slots) */
320 cd->stackframesize = m->maxlocals;
322 #if defined(ENABLE_THREADS)
323 if (checksync && (m->flags & ACC_SYNCHRONIZED))
324 cd->stackframesize += 1;
327 /* create method header */
329 (void) dseg_addaddress(cd, jd->code); /* CodeinfoPointer */
330 (void) dseg_adds4(cd, cd->stackframesize * SIZEOF_VOID_P); /* FrameSize */
332 #if defined(ENABLE_THREADS)
333 if (checksync && (m->flags & ACC_SYNCHRONIZED))
334 (void) dseg_adds4(cd, 1); /* IsSync */
337 (void) dseg_adds4(cd, 0); /* IsSync */
339 (void) dseg_adds4(cd, 0); /* IsLeaf */
340 (void) dseg_adds4(cd, 0); /* IntSave */
341 (void) dseg_adds4(cd, 0); /* FltSave */
343 dseg_addlinenumbertablesize(cd);
345 (void) dseg_adds4(cd, jd->exceptiontablelength); /* ExTableSize */
347 /* create exception table */
349 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
350 dseg_addtarget(cd, ex->start);
351 dseg_addtarget(cd, ex->end);
352 dseg_addtarget(cd, ex->handler);
353 (void) dseg_addaddress(cd, ex->catchtype.any);
357 /* initialize mcode variables */
359 cd->mcodeptr = cd->mcodebase;
360 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
365 #if defined(ENABLE_THREADS)
366 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
367 if (m->flags & ACC_STATIC) {
368 gen_ACONST(cd, (java_objectheader *) m->class);
373 gen_ASTORE(cd, index2offset(m->maxlocals));
376 gen_MONITORENTER(cd);
381 gen_TRACECALL(cd, m);
385 /* walk through all basic blocks */
387 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
389 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
391 if (bptr->flags != BBDELETED) {
393 /* walk through all instructions */
399 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
400 if (iptr->line != currentline) {
401 dseg_addlinenumber(cd, iptr->line);
402 currentline = iptr->line;
405 MCODECHECK(64); /* an instruction usually needs < 64 words */
410 case ICMD_INLINE_START:
411 case ICMD_INLINE_END:
414 case ICMD_NOP: /* ... ==> ... */
417 case ICMD_CHECKNULL_POP: /* ..., objectref ==> ... */
423 /* constant operations ************************************************/
425 case ICMD_ICONST: /* ... ==> ..., constant */
426 /* op1 = 0, val.i = constant */
428 /* optimize ICONST (2^x) .. IREM --> IREMPOW2 (const) */
430 if (len >= 2 && iptr[1].opc == ICMD_IREM) {
431 switch (iptr[0].sx.val.i) {
432 case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
433 case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
434 case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
435 case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
436 case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
437 case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
438 case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
439 case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
440 iptr[0].opc = ICMD_IREMPOW2;
442 iptr[1].opc = ICMD_NOP;
447 /* optimize ICONST (2^x) .. IDIV --> IDIVPOW2 (const) */
449 if (len >= 2 && iptr[1].opc == ICMD_IDIV) {
450 switch (iptr[0].sx.val.i) {
451 case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
452 case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
453 case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
454 case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
455 case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
456 case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
457 case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
458 case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
459 default: goto dont_opt_IDIVPOW2;
461 iptr[0].opc = ICMD_IDIVPOW2;
462 iptr[1].opc = ICMD_NOP;
467 /* optimize ICONST .. IF_ICMPxx --> IFxx (const) */
470 switch (iptr[1].opc) {
471 case ICMD_IF_ICMPEQ: iptr[0].opc = ICMD_IFEQ; break;
472 case ICMD_IF_ICMPNE: iptr[0].opc = ICMD_IFNE; break;
473 case ICMD_IF_ICMPLT: iptr[0].opc = ICMD_IFLT; break;
474 case ICMD_IF_ICMPLE: iptr[0].opc = ICMD_IFLE; break;
475 case ICMD_IF_ICMPGT: iptr[0].opc = ICMD_IFGT; break;
476 case ICMD_IF_ICMPGE: iptr[0].opc = ICMD_IFGE; break;
477 default: goto dont_opt_IFxx;
479 iptr[0].dst.insindex = iptr[1].dst.insindex;
480 iptr[1].opc = ICMD_NOP;
485 gen_ICONST(cd, iptr->sx.val.i);
488 case ICMD_LCONST: /* ... ==> ..., constant */
489 /* op1 = 0, val.l = constant */
491 /* optimize LCONST (2^x) .. LREM --> LREMPOW2 (const) */
493 if (len >= 2 && iptr[1].opc == ICMD_LREM) {
494 switch (iptr[0].sx.val.l) {
495 case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
496 case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
497 case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
498 case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
499 case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
500 case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
501 case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
502 case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
503 iptr[0].opc = ICMD_LREMPOW2;
505 iptr[1].opc = ICMD_NOP;
510 /* optimize LCONST (2^x) .. LDIV --> LDIVPOW2 (const) */
512 if (len >= 2 && iptr[1].opc == ICMD_LDIV) {
513 switch (iptr[0].sx.val.l) {
514 case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
515 case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
516 case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
517 case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
518 case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
519 case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
520 case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
521 case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
522 default: goto dont_opt_LDIVPOW2;
524 iptr[0].opc = ICMD_LDIVPOW2;
525 iptr[1].opc = ICMD_NOP;
530 /* optimize LCONST .. LCMP .. IFxx (0) --> IF_Lxx */
532 if (len >= 3 && iptr[1].opc == ICMD_LCMP && iptr[2].sx.val.i == 0) {
533 switch (iptr[2].opc) {
534 case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LEQ; break;
535 case ICMD_IFNE: iptr[0].opc = ICMD_IF_LNE; break;
536 case ICMD_IFLT: iptr[0].opc = ICMD_IF_LLT; break;
537 case ICMD_IFLE: iptr[0].opc = ICMD_IF_LLE; break;
538 case ICMD_IFGT: iptr[0].opc = ICMD_IF_LGT; break;
539 case ICMD_IFGE: iptr[0].opc = ICMD_IF_LGE; break;
540 default: goto dont_opt_IF_Lxx;
542 iptr[0].dst.insindex = iptr[2].dst.insindex;
543 iptr[1].opc = ICMD_NOP;
544 iptr[2].opc = ICMD_NOP;
549 gen_LCONST(cd, iptr->sx.val.l);
552 case ICMD_FCONST: /* ... ==> ..., constant */
553 /* op1 = 0, val.f = constant */
557 vm_f2Cell(iptr->sx.val.f, fi);
562 case ICMD_DCONST: /* ... ==> ..., constant */
563 /* op1 = 0, val.d = constant */
565 gen_LCONST(cd, *(s8 *)&(iptr->sx.val.d));
568 case ICMD_ACONST: /* ... ==> ..., constant */
569 /* op1 = 0, val.a = constant */
571 if (INSTRUCTION_IS_UNRESOLVED(iptr))
572 gen_PATCHER_ACONST(cd, NULL, iptr->sx.val.c.ref);
574 gen_ACONST(cd, iptr->sx.val.anyptr);
578 /* load/store operations **********************************************/
580 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
581 /* op1 = local variable */
583 gen_ILOAD(cd, index2offset(iptr->s1.varindex));
586 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
587 /* op1 = local variable */
589 gen_LLOAD(cd, index2offset(iptr->s1.varindex));
592 case ICMD_ALOAD: /* ... ==> ..., content of local variable */
593 /* op1 = local variable */
595 gen_ALOAD(cd, index2offset(iptr->s1.varindex));
598 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
599 /* op1 = local variable */
601 gen_ILOAD(cd, index2offset(iptr->s1.varindex));
604 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
605 /* op1 = local variable */
607 gen_LLOAD(cd, index2offset(iptr->s1.varindex));
611 case ICMD_ISTORE: /* ..., value ==> ... */
612 /* op1 = local variable */
614 gen_ISTORE(cd, index2offset(iptr->dst.varindex));
617 case ICMD_LSTORE: /* ..., value ==> ... */
618 /* op1 = local variable */
620 gen_LSTORE(cd, index2offset(iptr->dst.varindex));
623 case ICMD_ASTORE: /* ..., value ==> ... */
624 /* op1 = local variable */
626 gen_ASTORE(cd, index2offset(iptr->dst.varindex));
630 case ICMD_FSTORE: /* ..., value ==> ... */
631 /* op1 = local variable */
633 gen_ISTORE(cd, index2offset(iptr->dst.varindex));
636 case ICMD_DSTORE: /* ..., value ==> ... */
637 /* op1 = local variable */
639 gen_LSTORE(cd, index2offset(iptr->dst.varindex));
643 /* pop/dup/swap operations ********************************************/
645 case ICMD_POP: /* ..., value ==> ... */
650 case ICMD_POP2: /* ..., value, value ==> ... */
655 case ICMD_DUP: /* ..., a ==> ..., a, a */
660 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
665 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
670 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
675 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
680 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
685 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
691 /* integer operations *************************************************/
693 case ICMD_INEG: /* ..., value ==> ..., - value */
698 case ICMD_LNEG: /* ..., value ==> ..., - value */
703 case ICMD_I2L: /* ..., value ==> ..., value */
708 case ICMD_L2I: /* ..., value ==> ..., value */
713 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
718 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
723 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
729 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
734 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
739 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
744 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
749 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
754 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
759 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
764 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
769 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
774 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
779 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
780 /* val.i = constant */
782 gen_IDIVPOW2(cd, iptr->sx.val.i);
785 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
786 /* val.i = constant */
788 gen_IREMPOW2(cd, iptr->sx.val.i);
791 case ICMD_LDIVPOW2: /* ..., value ==> ..., value << constant */
792 /* val.i = constant */
794 gen_LDIVPOW2(cd, iptr->sx.val.i);
797 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
798 /* val.l = constant */
800 gen_LREMPOW2(cd, iptr->sx.val.i);
803 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
808 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
813 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
818 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
823 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
828 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
833 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
838 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
843 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
848 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
853 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
858 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
864 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
866 /* optimize LCMP .. IFxx (0) --> IF_LCMPxx */
868 if (len >= 2 && iptr[1].sx.val.i == 0) {
869 switch (iptr[1].opc) {
870 case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LCMPEQ; break;
871 case ICMD_IFNE: iptr[0].opc = ICMD_IF_LCMPNE; break;
872 case ICMD_IFLT: iptr[0].opc = ICMD_IF_LCMPLT; break;
873 case ICMD_IFLE: iptr[0].opc = ICMD_IF_LCMPLE; break;
874 case ICMD_IFGT: iptr[0].opc = ICMD_IF_LCMPGT; break;
875 case ICMD_IFGE: iptr[0].opc = ICMD_IF_LCMPGE; break;
876 default: goto dont_opt_IF_LCMPxx;
878 iptr[0].dst.insindex = iptr[1].dst.insindex;
879 iptr[1].opc = ICMD_NOP;
888 case ICMD_IINC: /* ..., value ==> ..., value + constant */
889 /* op1 = variable, val.i = constant */
891 gen_IINC(cd, index2offset(iptr->s1.varindex), iptr->sx.val.i);
895 /* floating operations ************************************************/
897 case ICMD_FNEG: /* ..., value ==> ..., - value */
902 case ICMD_DNEG: /* ..., value ==> ..., - value */
907 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
912 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
917 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
922 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
927 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
932 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
937 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
942 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
947 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
952 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
957 case ICMD_I2F: /* ..., value ==> ..., (float) value */
962 case ICMD_L2F: /* ..., value ==> ..., (float) value */
967 case ICMD_I2D: /* ..., value ==> ..., (double) value */
972 case ICMD_L2D: /* ..., value ==> ..., (double) value */
977 case ICMD_F2I: /* ..., value ==> ..., (int) value */
982 case ICMD_D2I: /* ..., value ==> ..., (int) value */
987 case ICMD_F2L: /* ..., value ==> ..., (long) value */
992 case ICMD_D2L: /* ..., value ==> ..., (long) value */
997 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1002 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1007 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1012 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1017 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1022 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1028 /* memory operations **************************************************/
1030 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1032 gen_ARRAYLENGTH(cd);
1035 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1040 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1045 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1050 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1055 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1060 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1061 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1066 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1072 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1077 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1078 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1083 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1088 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1093 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1094 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1099 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1105 case ICMD_GETSTATIC: /* ... ==> ..., value */
1106 /* op1 = type, val.a = field address */
1108 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1110 uf = iptr->sx.s23.s3.uf;
1111 fieldtype = uf->fieldref->parseddesc.fd->type;
1114 fi = iptr->sx.s23.s3.fmiref->p.field;
1116 fieldtype = fi->type;
1119 switch (fieldtype) {
1122 gen_PATCHER_GETSTATIC_INT(cd, 0, uf);
1123 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1124 gen_PATCHER_GETSTATIC_CLINIT_INT(cd, 0, fi);
1126 gen_GETSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1130 gen_PATCHER_GETSTATIC_FLOAT(cd, 0, uf);
1131 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1132 gen_PATCHER_GETSTATIC_CLINIT_FLOAT(cd, 0, fi);
1134 gen_GETSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1139 gen_PATCHER_GETSTATIC_LONG(cd, 0, uf);
1140 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1141 gen_PATCHER_GETSTATIC_CLINIT_LONG(cd, 0, fi);
1143 gen_GETSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1147 gen_PATCHER_GETSTATIC_CELL(cd, 0, uf);
1148 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1149 gen_PATCHER_GETSTATIC_CLINIT_CELL(cd, 0, fi);
1151 gen_GETSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1156 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1157 /* op1 = type, val.a = field address */
1159 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1161 uf = iptr->sx.s23.s3.uf;
1162 fieldtype = uf->fieldref->parseddesc.fd->type;
1165 fi = iptr->sx.s23.s3.fmiref->p.field;
1167 fieldtype = fi->type;
1170 switch (fieldtype) {
1173 gen_PATCHER_PUTSTATIC_INT(cd, 0, uf);
1174 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1175 gen_PATCHER_PUTSTATIC_CLINIT_INT(cd, 0, fi);
1177 gen_PUTSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1181 gen_PATCHER_PUTSTATIC_FLOAT(cd, 0, uf);
1182 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1183 gen_PATCHER_PUTSTATIC_CLINIT_FLOAT(cd, 0, fi);
1185 gen_PUTSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1190 gen_PATCHER_PUTSTATIC_LONG(cd, 0, uf);
1191 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1192 gen_PATCHER_PUTSTATIC_CLINIT_LONG(cd, 0, fi);
1194 gen_PUTSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1198 gen_PATCHER_PUTSTATIC_CELL(cd, 0, uf);
1199 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1200 gen_PATCHER_PUTSTATIC_CLINIT_CELL(cd, 0, fi);
1202 gen_PUTSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1208 case ICMD_GETFIELD: /* ... ==> ..., value */
1209 /* op1 = type, val.a = field address */
1211 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1213 uf = iptr->sx.s23.s3.uf;
1214 fieldtype = uf->fieldref->parseddesc.fd->type;
1217 fi = iptr->sx.s23.s3.fmiref->p.field;
1219 fieldtype = fi->type;
1222 switch (fieldtype) {
1225 gen_PATCHER_GETFIELD_INT(cd, 0, uf);
1227 gen_GETFIELD_INT(cd, fi->offset, fi);
1231 gen_PATCHER_GETFIELD_FLOAT(cd, 0, uf);
1233 gen_GETFIELD_FLOAT(cd, fi->offset, fi);
1238 gen_PATCHER_GETFIELD_LONG(cd, 0, uf);
1240 gen_GETFIELD_LONG(cd, fi->offset, fi);
1244 gen_PATCHER_GETFIELD_CELL(cd, 0, uf);
1246 gen_GETFIELD_CELL(cd, fi->offset, fi);
1251 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1252 /* op1 = type, val.a = field address */
1254 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1256 uf = iptr->sx.s23.s3.uf;
1257 fieldtype = uf->fieldref->parseddesc.fd->type;
1260 fi = iptr->sx.s23.s3.fmiref->p.field;
1262 fieldtype = fi->type;
1265 switch (fieldtype) {
1268 gen_PATCHER_PUTFIELD_INT(cd, 0, uf);
1270 gen_PUTFIELD_INT(cd, fi->offset, fi);
1274 gen_PATCHER_PUTFIELD_FLOAT(cd, 0, uf);
1276 gen_PUTFIELD_FLOAT(cd, fi->offset, fi);
1281 gen_PATCHER_PUTFIELD_LONG(cd, 0, uf);
1283 gen_PUTFIELD_LONG(cd, fi->offset, fi);
1287 gen_PATCHER_PUTFIELD_CELL(cd, 0, uf);
1289 gen_PUTFIELD_CELL(cd, fi->offset, fi);
1295 /* branch operations **************************************************/
1297 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1302 case ICMD_GOTO: /* ... ==> ... */
1303 /* op1 = target JavaVM pc */
1307 case ICMD_JSR: /* ... ==> ... */
1308 /* op1 = target JavaVM pc */
1311 codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex));
1314 case ICMD_RET: /* ... ==> ... */
1315 /* op1 = local variable */
1317 gen_RET(cd, index2offset(iptr->s1.varindex));
1320 case ICMD_IFNULL: /* ..., value ==> ... */
1321 /* op1 = target JavaVM pc */
1326 case ICMD_IFNONNULL: /* ..., value ==> ... */
1327 /* op1 = target JavaVM pc */
1329 gen_branch(IFNONNULL);
1332 case ICMD_IFEQ: /* ..., value ==> ... */
1333 /* op1 = target JavaVM pc, val.i = constant */
1335 if (iptr->sx.val.i == 0) {
1338 gen_ICONST(cd, iptr->sx.val.i);
1339 gen_branch(IF_ICMPEQ);
1343 case ICMD_IFLT: /* ..., value ==> ... */
1344 /* op1 = target JavaVM pc, val.i = constant */
1346 if (iptr->sx.val.i == 0) {
1349 gen_ICONST(cd, iptr->sx.val.i);
1350 gen_branch(IF_ICMPLT);
1354 case ICMD_IFLE: /* ..., value ==> ... */
1355 /* op1 = target JavaVM pc, val.i = constant */
1357 if (iptr->sx.val.i == 0) {
1360 gen_ICONST(cd, iptr->sx.val.i);
1361 gen_branch(IF_ICMPLE);
1365 case ICMD_IFNE: /* ..., value ==> ... */
1366 /* op1 = target JavaVM pc, val.i = constant */
1368 if (iptr->sx.val.i == 0) {
1371 gen_ICONST(cd, iptr->sx.val.i);
1372 gen_branch(IF_ICMPNE);
1376 case ICMD_IFGT: /* ..., value ==> ... */
1377 /* op1 = target JavaVM pc, val.i = constant */
1379 if (iptr->sx.val.i == 0) {
1382 gen_ICONST(cd, iptr->sx.val.i);
1383 gen_branch(IF_ICMPGT);
1387 case ICMD_IFGE: /* ..., value ==> ... */
1388 /* op1 = target JavaVM pc, val.i = constant */
1390 if (iptr->sx.val.i == 0) {
1393 gen_ICONST(cd, iptr->sx.val.i);
1394 gen_branch(IF_ICMPGE);
1399 case ICMD_IF_LEQ: /* ..., value ==> ... */
1400 /* op1 = target JavaVM pc, val.l = constant */
1402 gen_LCONST(cd, iptr->sx.val.l);
1403 gen_branch(IF_LCMPEQ);
1406 case ICMD_IF_LLT: /* ..., value ==> ... */
1407 /* op1 = target JavaVM pc, val.l = constant */
1409 gen_LCONST(cd, iptr->sx.val.l);
1410 gen_branch(IF_LCMPLT);
1413 case ICMD_IF_LLE: /* ..., value ==> ... */
1414 /* op1 = target JavaVM pc, val.l = constant */
1416 gen_LCONST(cd, iptr->sx.val.l);
1417 gen_branch(IF_LCMPLE);
1420 case ICMD_IF_LNE: /* ..., value ==> ... */
1421 /* op1 = target JavaVM pc, val.l = constant */
1423 gen_LCONST(cd, iptr->sx.val.l);
1424 gen_branch(IF_LCMPNE);
1427 case ICMD_IF_LGT: /* ..., value ==> ... */
1428 /* op1 = target JavaVM pc, val.l = constant */
1430 gen_LCONST(cd, iptr->sx.val.l);
1431 gen_branch(IF_LCMPGT);
1434 case ICMD_IF_LGE: /* ..., value ==> ... */
1435 /* op1 = target JavaVM pc, val.l = constant */
1437 gen_LCONST(cd, iptr->sx.val.l);
1438 gen_branch(IF_LCMPGE);
1441 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1442 /* op1 = target JavaVM pc */
1444 gen_branch(IF_LCMPEQ);
1447 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
1448 /* op1 = target JavaVM pc */
1450 gen_branch(IF_LCMPNE);
1453 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
1454 /* op1 = target JavaVM pc */
1456 gen_branch(IF_LCMPLT);
1459 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
1460 /* op1 = target JavaVM pc */
1462 gen_branch(IF_LCMPGT);
1465 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
1466 /* op1 = target JavaVM pc */
1468 gen_branch(IF_LCMPLE);
1471 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
1472 /* op1 = target JavaVM pc */
1474 gen_branch(IF_LCMPGE);
1478 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1479 /* op1 = target JavaVM pc */
1481 gen_branch(IF_ICMPEQ);
1484 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
1485 /* op1 = target JavaVM pc */
1487 gen_branch(IF_ACMPEQ);
1490 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
1491 /* op1 = target JavaVM pc */
1493 gen_branch(IF_ICMPNE);
1496 case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
1497 /* op1 = target JavaVM pc */
1499 gen_branch(IF_ACMPNE);
1502 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
1503 /* op1 = target JavaVM pc */
1505 gen_branch(IF_ICMPLT);
1508 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
1509 /* op1 = target JavaVM pc */
1511 gen_branch(IF_ICMPGT);
1514 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
1515 /* op1 = target JavaVM pc */
1517 gen_branch(IF_ICMPLE);
1520 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
1521 /* op1 = target JavaVM pc */
1523 gen_branch(IF_ICMPGE);
1527 case ICMD_ARETURN: /* ..., retvalue ==> ... */
1528 case ICMD_IRETURN: /* ..., retvalue ==> ... */
1529 case ICMD_FRETURN: /* ..., retvalue ==> ... */
1531 #if defined(ENABLE_THREADS)
1532 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1533 if (m->flags & ACC_STATIC) {
1534 gen_ACONST(cd, (java_objectheader *) m->class);
1536 gen_ALOAD(cd, index2offset(m->maxlocals));
1538 gen_MONITOREXIT(cd);
1541 if (opt_verbosecall)
1542 gen_TRACERETURN(cd, m);
1544 gen_IRETURN(cd, index2offset(cd->stackframesize));
1547 case ICMD_LRETURN: /* ..., retvalue ==> ... */
1548 case ICMD_DRETURN: /* ..., retvalue ==> ... */
1550 #if defined(ENABLE_THREADS)
1551 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1552 if (m->flags & ACC_STATIC) {
1553 gen_ACONST(cd, (java_objectheader *) m->class);
1555 gen_ALOAD(cd, index2offset(m->maxlocals));
1557 gen_MONITOREXIT(cd);
1560 if (opt_verbosecall)
1561 gen_TRACELRETURN(cd, m);
1563 gen_LRETURN(cd, index2offset(cd->stackframesize));
1566 case ICMD_RETURN: /* ... ==> ... */
1568 #if defined(ENABLE_THREADS)
1569 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1570 if (m->flags & ACC_STATIC) {
1571 gen_ACONST(cd, (java_objectheader *) m->class);
1573 gen_ALOAD(cd, index2offset(m->maxlocals));
1575 gen_MONITOREXIT(cd);
1578 if (opt_verbosecall)
1579 gen_TRACERETURN(cd, m);
1581 gen_RETURN(cd, index2offset(cd->stackframesize));
1585 case ICMD_TABLESWITCH: /* ..., index ==> ... */
1588 branch_target_t *table;
1590 table = iptr->dst.table;
1592 l = iptr->sx.s23.s2.tablelow;
1593 i = iptr->sx.s23.s3.tablehigh;
1597 /* arguments: low, range, datasegment address, table
1598 offset in datasegment, default target */
1600 gen_TABLESWITCH(cd, l, i, NULL, 0, NULL);
1602 /* actually -3 cells offset */
1604 cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1606 cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1608 codegen_addreference(cd, BLOCK_OF(table[0].insindex));
1610 /* build jump table top down and use address of lowest entry */
1615 dseg_addtarget(cd, BLOCK_OF(table->insindex));
1620 /* length of dataseg after last dseg_addtarget is used by load */
1621 ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1625 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
1628 lookup_target_t *lookup;
1630 lookup = iptr->dst.lookup;
1632 i = iptr->sx.s23.s2.lookupcount;
1634 /* arguments: count, datasegment address, table offset in */
1635 /* datasegment, default target */
1636 gen_LOOKUPSWITCH(cd, i, NULL, 0, NULL);
1638 /* actually -3 cells offset */
1640 cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1642 cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1644 /* build jump table top down and use address of lowest entry */
1647 dseg_addtarget(cd, BLOCK_OF(lookup->target.insindex));
1648 dseg_addaddress(cd, lookup->value);
1652 codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex));
1655 /* length of dataseg after last dseg_addtarget is used by load */
1656 ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1660 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
1661 /* op1 = arg count val.a = builtintable entry */
1662 bte = iptr->sx.s23.s3.bte;
1664 for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
1665 builtin_gen *bg = &builtin_gen_table[i];
1666 if (bg->builtin == bte->fp) {
1668 goto gen_builtin_end;
1677 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
1678 /* op1 = arg count, val.a = method pointer */
1680 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1681 um = iptr->sx.s23.s3.um;
1682 md = um->methodref->parseddesc.md;
1683 gen_PATCHER_INVOKESTATIC(cd, 0, md->paramslots, um);
1686 lm = iptr->sx.s23.s3.fmiref->p.method;
1687 md = lm->parseddesc;
1688 gen_INVOKESTATIC(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1692 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1694 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1695 um = iptr->sx.s23.s3.um;
1696 md = um->methodref->parseddesc.md;
1697 gen_PATCHER_INVOKESPECIAL(cd, 0, md->paramslots, um);
1700 lm = iptr->sx.s23.s3.fmiref->p.method;
1701 md = lm->parseddesc;
1702 gen_INVOKESPECIAL(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1706 case ICMD_INVOKEVIRTUAL:/* 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_INVOKEVIRTUAL(cd, 0, md->paramslots, um);
1714 lm = iptr->sx.s23.s3.fmiref->p.method;
1715 md = lm->parseddesc;
1717 s1 = OFFSET(vftbl_t, table[0]) +
1718 sizeof(methodptr) * lm->vftblindex;
1720 gen_INVOKEVIRTUAL(cd, s1, md->paramslots, lm);
1724 case ICMD_INVOKEINTERFACE:/* op1 = arg count, val.a = method pointer */
1726 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1727 um = iptr->sx.s23.s3.um;
1728 md = um->methodref->parseddesc.md;
1729 gen_PATCHER_INVOKEINTERFACE(cd, 0, 0, md->paramslots, um);
1732 lm = iptr->sx.s23.s3.fmiref->p.method;
1733 md = lm->parseddesc;
1735 s1 = OFFSET(vftbl_t, interfacetable[0]) -
1736 sizeof(methodptr*) * lm->class->index;
1738 s2 = sizeof(methodptr) * (lm - lm->class->methods);
1740 gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
1745 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
1746 /* op1: 0 == array, 1 == class */
1747 /* val.a: (classinfo *) superclass */
1749 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1750 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1751 gen_PATCHER_CHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1753 gen_CHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1756 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1757 gen_PATCHER_ARRAYCHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1759 gen_ARRAYCHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1763 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
1764 /* op1: 0 == array, 1 == class */
1765 /* val.a: (classinfo *) superclass */
1767 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1768 gen_PATCHER_INSTANCEOF(cd, NULL, iptr->sx.s23.s3.c.ref);
1770 gen_INSTANCEOF(cd, iptr->sx.s23.s3.c.cls, iptr->sx.s23.s3.c.ref);
1773 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
1774 /* op1 = dimension, val.a = class */
1776 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1777 gen_PATCHER_MULTIANEWARRAY(cd, NULL, iptr->s1.argcount, iptr->sx.s23.s3.c.ref);
1779 gen_MULTIANEWARRAY(cd, iptr->sx.s23.s3.c.cls, iptr->s1.argcount, NULL);
1783 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
1787 } /* for instruction */
1791 } /* if (bptr->flags != BBDELETED) */
1792 } /* for basic block */
1794 dseg_createlinenumbertable(cd);
1799 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
1802 /* branch resolving (walk through all basic blocks) */
1804 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
1807 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
1808 gen_resolveanybranch(((u1*) jd->code->entrypoint) + brefs->branchpos,
1809 ((u1 *)jd->code->entrypoint) + bptr->mpc);
1813 /* everything's ok */
1819 /* createcompilerstub **********************************************************
1821 Creates a stub routine which calls the compiler.
1827 +-------------+ <-- stub
1830 | framesize | (in ptrint units, does not include return address)
1837 codeptr points either to TRANSLATE or to the translated threaded code
1839 all methods are called indirectly through methodptr
1841 *******************************************************************************/
1843 #define COMPILERSTUB_DATASIZE 1
1844 #define COMPILERSTUB_CODESIZE 4
1846 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
1849 u1 *intrp_createcompilerstub(methodinfo *m)
1858 s = CNEW(Inst, COMPILERSTUB_SIZE);
1860 /* set data pointer and code pointer */
1863 s = s + COMPILERSTUB_DATASIZE;
1865 /* Store the codeinfo pointer in the same place as in the
1866 methodheader for compiled methods. */
1868 code = code_codeinfo_new(m);
1869 d[0] = (Inst *) code;
1871 /* mark start of dump memory area */
1873 dumpsize = dump_size();
1875 cd = DNEW(codegendata);
1876 cd->mcodeptr = (u1 *) s;
1877 cd->lastinstwithoutdispatch = ~0;
1878 cd->superstarts = NULL;
1880 genarg_ainst(cd, s + 2);
1882 if (m->flags & ACC_NATIVE) {
1883 stackframesize = m->parseddesc->paramslots;
1886 stackframesize = m->maxlocals;
1888 #if defined(ENABLE_THREADS)
1889 if (checksync && (m->flags & ACC_SYNCHRONIZED))
1890 stackframesize += 1;
1894 genarg_i(cd, stackframesize);
1897 gen_TRANSLATE(cd, m);
1901 vm_block_insert(cd->mcodeptr);
1904 #if defined(ENABLE_STATISTICS)
1906 count_cstub_len += COMPILERSTUB_SIZE;
1909 /* release dump area */
1911 dump_release(dumpsize);
1917 #if defined(WITH_FFI)
1918 static ffi_type *cacaotype2ffitype(s4 cacaotype)
1920 switch (cacaotype) {
1922 #if SIZEOF_VOID_P == 8
1923 return &ffi_type_sint64;
1925 return &ffi_type_sint32;
1928 return &ffi_type_sint64;
1930 return &ffi_type_float;
1932 return &ffi_type_double;
1934 return &ffi_type_pointer;
1936 return &ffi_type_void;
1956 #if defined(WITH_FFI)
1957 static ffi_cif *createnativecif(methodinfo *m, methoddesc *nmd)
1959 methoddesc *md = m->parseddesc;
1960 ffi_cif *pcif = NEW(ffi_cif);
1961 ffi_type **types = MNEW(ffi_type *, nmd->paramcount);
1962 ffi_type **ptypes = types;
1965 /* pass env pointer */
1967 *ptypes++ = &ffi_type_pointer;
1969 /* for static methods, pass class pointer */
1971 if (m->flags & ACC_STATIC)
1972 *ptypes++ = &ffi_type_pointer;
1974 /* pass parameter to native function */
1976 for (i = 0; i < md->paramcount; i++)
1977 *ptypes++ = cacaotype2ffitype(md->paramtypes[i].type);
1979 assert(ptypes - types == nmd->paramcount);
1981 if (ffi_prep_cif(pcif, FFI_DEFAULT_ABI, nmd->paramcount, cacaotype2ffitype(md->returntype.type), types) != FFI_OK)
1989 u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
1995 #if defined(WITH_FFI)
2002 /* get required compiler data */
2008 /* determine stackframe size (in units of ptrint) */
2010 stackframesize = nmd->paramslots;
2012 /* create method header */
2014 /* Store the codeinfo pointer in the same place as in the
2015 methodheader for compiled methods. */
2017 code = code_codeinfo_new(m);
2019 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
2020 (void) dseg_adds4(cd, stackframesize * SIZEOF_VOID_P); /* FrameSize */
2021 (void) dseg_adds4(cd, 0); /* IsSync */
2022 (void) dseg_adds4(cd, 0); /* IsLeaf */
2023 (void) dseg_adds4(cd, 0); /* IntSave */
2024 (void) dseg_adds4(cd, 0); /* FltSave */
2025 dseg_addlinenumbertablesize(cd);
2026 (void) dseg_adds4(cd, 0); /* ExTableSize */
2028 #if defined(WITH_FFI)
2029 /* prepare ffi cif structure */
2031 cif = createnativecif(m, nmd);
2038 if (opt_verbosecall)
2039 gen_TRACECALL(cd, m);
2042 gen_PATCHER_NATIVECALL(cd, m, f, (u1 *)cif);
2044 if (opt_verbosecall)
2045 gen_TRACENATIVECALL(cd, m, f, (u1 *)cif);
2047 gen_NATIVECALL(cd, m, f, (u1 *)cif);
2055 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2058 return jd->code->entrypoint;
2062 /* call jni function */
2063 Cell *nativecall(functionptr f, methodinfo *m, Cell *sp, Inst *ra, Cell *fp, u1 *addrcif)
2065 #if defined(WITH_FFCALL)
2079 switch (md->returntype.type) {
2081 endsp = sp - 1 + md->paramslots;
2082 av_start_long(alist, f, endsp);
2085 endsp = sp - 2 + md->paramslots;
2086 av_start_longlong(alist, f, endsp);
2089 endsp = sp - 1 + md->paramslots;
2090 av_start_float(alist, f, endsp);
2093 endsp = sp - 2 + md->paramslots;
2094 av_start_double(alist, f, endsp);
2097 endsp = sp - 1 + md->paramslots;
2098 av_start_ptr(alist, f, void *, endsp);
2101 endsp = sp + md->paramslots;
2102 av_start_void(alist, f);
2108 av_ptr(alist, _Jv_JNIEnv *, _Jv_env);
2110 if (m->flags & ACC_STATIC)
2111 av_ptr(alist, classinfo *, m->class);
2113 for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2114 switch (md->paramtypes[i].type) {
2121 av_longlong(alist, *(s8 *)p);
2125 av_float(alist, *((float *) p));
2129 av_double(alist, *(double *) p);
2133 av_ptr(alist, void *, *(void **) p);
2142 /* create stackframe info structure */
2144 codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2145 (u1 *) fp, (u1 *) ra);
2149 *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2154 #elif defined(WITH_FFI)
2155 methoddesc *md = m->parseddesc;
2157 void *values[md->paramcount + 2];
2158 void **pvalues = values;
2169 pcif = (ffi_cif *) addrcif;
2171 /* pass env pointer */
2173 penv = (_Jv_JNIEnv *) _Jv_env;
2176 /* for static methods, pass class pointer */
2178 if (m->flags & ACC_STATIC)
2179 *pvalues++ = &m->class;
2181 /* pass parameter to native function */
2183 for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2184 if (IS_2_WORD_TYPE(md->paramtypes[i].type))
2192 /* calculate position of return value */
2194 if (md->returntype.type == TYPE_VOID)
2195 endsp = sp + md->paramslots;
2197 endsp = sp - (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1) + md->paramslots;
2201 /* create stackframe info structure */
2203 codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2204 (u1 *) fp, (u1 *) ra);
2206 ffi_call(pcif, FFI_FN(f), endsp, values);
2208 *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2217 u1 *createcalljavafunction(methodinfo *m)
2227 /* mark dump memory */
2229 dumpsize = dump_size();
2231 /* allocate memory */
2235 tmpm = DNEW(methodinfo);
2236 cd = DNEW(codegendata);
2237 rd = DNEW(registerdata);
2244 /* Allocate codeinfo memory from the heap as we need to keep them. */
2246 jd->code = code_codeinfo_new(tmpm); /* XXX check allocation */
2248 /* setup code generation stuff */
2250 MSET(tmpm, 0, u1, sizeof(methodinfo));
2256 /* create method header */
2258 (void) dseg_addaddress(cd, NULL); /* CodeinfoPointer */
2259 (void) dseg_adds4(cd, md->paramslots * SIZEOF_VOID_P); /* FrameSize */
2260 (void) dseg_adds4(cd, 0); /* IsSync */
2261 (void) dseg_adds4(cd, 0); /* IsLeaf */
2262 (void) dseg_adds4(cd, 0); /* IntSave */
2263 (void) dseg_adds4(cd, 0); /* FltSave */
2264 dseg_addlinenumbertablesize(cd);
2265 (void) dseg_adds4(cd, 0); /* ExTableSize */
2271 gen_INVOKESTATIC(cd, (Inst **)m->stubroutine, md->paramslots, 0);
2279 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2281 entrypoint = jd->code->entrypoint;
2283 /* release memory */
2285 dump_release(dumpsize);
2292 * These are local overrides for various environment variables in Emacs.
2293 * Please do not remove this and leave it at the end of the file, where
2294 * Emacs will automagically detect them.
2295 * ---------------------------------------------------------------------
2298 * indent-tabs-mode: t
2302 * vim:noexpandtab:sw=4:ts=4: