1 /* src/vm/jit/intrp/codegen.c - code generator for Interpreter
3 Copyright (C) 1996-2005, 2006, 2007 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
35 #elif defined(WITH_FFCALL)
38 # error neither WITH_FFI nor WITH_FFCALL defined
45 #include "vm/jit/intrp/codegen.h"
46 #include "vm/jit/intrp/intrp.h"
48 #include "mm/memory.h"
50 #include "native/native.h"
52 #include "vm/builtin.h"
53 #include "vm/exceptions.h"
54 #include "vm/global.h"
55 #include "vm/stringlocal.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/codegen-common.h"
60 #include "vm/jit/dseg.h"
61 #include "vm/jit/jit.h"
62 #include "vm/jit/parse.h"
63 #include "vm/jit/patcher.h"
64 #include "vm/jit/stack.h"
65 #include "vm/jit/stacktrace.h"
67 #include "vmcore/class.h"
68 #include "vmcore/options.h"
71 #define gen_branch(_inst) { \
73 codegen_addreference(cd, BLOCK_OF(iptr->dst.insindex)); \
76 #define index2offset(_i) (-(_i) * SIZEOF_VOID_P)
78 /* functions used by cacao-gen.i */
80 void genarg_v(codegendata *cd1, Cell v)
82 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
83 *((Cell *) *mcodepp) = v;
87 void genarg_i(codegendata *cd1, s4 i)
89 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
90 *((Cell *) *mcodepp) = i;
94 void genarg_b(codegendata *cd1, s4 i)
99 void genarg_f(codegendata *cd1, float f)
107 void genarg_l(codegendata *cd1, s8 l)
109 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
110 vm_l2twoCell(l, ((Cell *) *mcodepp)[1], ((Cell *) *mcodepp)[0]);
114 void genarg_aRef(codegendata *cd1, java_objectheader *a)
116 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
117 *((java_objectheader **) *mcodepp) = a;
121 void genarg_aArray(codegendata *cd1, java_arrayheader *a)
123 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
124 *((java_arrayheader **) *mcodepp) = a;
128 void genarg_aaTarget(codegendata *cd1, Inst **a)
130 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
131 *((Inst ***) *mcodepp) = a;
135 void genarg_aClass(codegendata *cd1, classinfo *a)
137 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
138 *((classinfo **) *mcodepp) = a;
142 void genarg_acr(codegendata *cd1, constant_classref *a)
144 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
145 *((constant_classref **) *mcodepp) = a;
149 void genarg_addr(codegendata *cd1, u1 *a)
151 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
152 *((u1 **) *mcodepp) = a;
156 void genarg_af(codegendata *cd1, functionptr a)
158 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
159 *((functionptr *) *mcodepp) = a;
163 void genarg_afi(codegendata *cd1, fieldinfo *a)
165 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
166 *((fieldinfo **) *mcodepp) = a;
170 void genarg_am(codegendata *cd1, methodinfo *a)
172 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
173 *((methodinfo **) *mcodepp) = a;
177 void genarg_acell(codegendata *cd1, Cell *a)
179 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
180 *((Cell **) *mcodepp) = a;
184 void genarg_ainst(codegendata *cd1, Inst *a)
186 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
187 *((Inst **) *mcodepp) = a;
191 void genarg_auf(codegendata *cd1, unresolved_field *a)
193 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
194 *((unresolved_field **) *mcodepp) = a;
198 void genarg_aum(codegendata *cd1, unresolved_method *a)
200 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
201 *((unresolved_method **) *mcodepp) = a;
205 void genarg_avftbl(codegendata *cd1, vftbl_t *a)
207 Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
208 *((vftbl_t **) *mcodepp) = a;
213 /* include the interpreter generation functions *******************************/
215 /* Do not use "java-gen.i", it does not work with builddir. */
216 #include <java-gen.i>
219 typedef void (*genfunctionptr) (codegendata *);
221 typedef struct builtin_gen builtin_gen;
228 struct builtin_gen builtin_gen_table[] = {
229 {BUILTIN_new, gen_NEW, },
230 {BUILTIN_newarray, gen_NEWARRAY, },
231 {BUILTIN_newarray_boolean, gen_NEWARRAY_BOOLEAN,},
232 {BUILTIN_newarray_byte, gen_NEWARRAY_BYTE, },
233 {BUILTIN_newarray_char, gen_NEWARRAY_CHAR, },
234 {BUILTIN_newarray_short, gen_NEWARRAY_SHORT, },
235 {BUILTIN_newarray_int, gen_NEWARRAY_INT, },
236 {BUILTIN_newarray_long, gen_NEWARRAY_LONG, },
237 {BUILTIN_newarray_float, gen_NEWARRAY_FLOAT, },
238 {BUILTIN_newarray_double, gen_NEWARRAY_DOUBLE, },
239 {BUILTIN_arrayinstanceof, gen_ARRAYINSTANCEOF, },
241 #if defined(ENABLE_THREADS)
242 {LOCK_monitor_enter, gen_MONITORENTER, },
243 {LOCK_monitor_exit, gen_MONITOREXIT, },
246 #if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
247 {BUILTIN_f2l, gen_F2L, },
250 #if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
251 {BUILTIN_d2l, gen_D2L, },
254 #if !(SUPPORT_FLOAT && SUPPORT_F2I)
255 {BUILTIN_f2i, gen_F2I, },
258 #if !(SUPPORT_DOUBLE && SUPPORT_D2I)
259 {BUILTIN_d2i, gen_D2I, },
262 #if !SUPPORT_DIVISION
263 {BUILTIN_idiv, gen_IDIV, },
264 {BUILTIN_irem, gen_IREM, },
267 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
268 {BUILTIN_ldiv, gen_LDIV, },
269 {BUILTIN_lrem, gen_LREM, },
272 {BUILTIN_frem, gen_FREM, },
273 {BUILTIN_drem, gen_DREM, },
277 /* codegen *********************************************************************
279 Generates machine code.
281 *******************************************************************************/
283 #define I(value) iptr[0].sx.val.i = (value); break;
285 bool intrp_codegen(jitdata *jd)
290 s4 i, len, s1, s2, d;
295 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
296 unresolved_method *um;
297 builtintable_entry *bte;
300 unresolved_field *uf;
303 /* get required compiler data */
309 /* prevent compiler warnings */
316 /* determine stackframe size (in units of ptrint slots) */
318 cd->stackframesize = m->maxlocals;
320 #if defined(ENABLE_THREADS)
321 if (checksync && (m->flags & ACC_SYNCHRONIZED))
322 cd->stackframesize += 1;
325 /* create method header */
327 (void) dseg_add_unique_address(cd, jd->code);
328 (void) dseg_add_unique_s4(cd, cd->stackframesize * SIZEOF_VOID_P);
330 #if defined(ENABLE_THREADS)
331 if (checksync && (m->flags & ACC_SYNCHRONIZED))
332 (void) dseg_add_unique_s4(cd, 1);
335 (void) dseg_add_unique_s4(cd, 0);
337 (void) dseg_add_unique_s4(cd, 0);
338 (void) dseg_add_unique_s4(cd, 0);
339 (void) dseg_add_unique_s4(cd, 0);
341 dseg_addlinenumbertablesize(cd);
343 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength);
345 /* create exception table */
347 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
348 dseg_add_target(cd, ex->start);
349 dseg_add_target(cd, ex->end);
350 dseg_add_target(cd, ex->handler);
351 (void) dseg_add_unique_address(cd, ex->catchtype.any);
355 /* initialize mcode variables */
357 cd->mcodeptr = cd->mcodebase;
358 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
363 #if defined(ENABLE_THREADS)
364 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
365 if (m->flags & ACC_STATIC) {
366 gen_ACONST(cd, (java_objectheader *) m->class);
371 gen_ASTORE(cd, index2offset(m->maxlocals));
374 gen_MONITORENTER(cd);
379 gen_TRACECALL(cd, m);
383 /* walk through all basic blocks */
385 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
387 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
389 if (bptr->flags != BBDELETED) {
391 /* walk through all instructions */
397 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
398 if (iptr->line != currentline) {
399 dseg_addlinenumber(cd, iptr->line);
400 currentline = iptr->line;
403 MCODECHECK(64); /* an instruction usually needs < 64 words */
408 case ICMD_INLINE_START:
409 case ICMD_INLINE_END:
412 case ICMD_NOP: /* ... ==> ... */
415 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
420 /* constant operations ************************************************/
422 case ICMD_ICONST: /* ... ==> ..., constant */
423 /* op1 = 0, val.i = constant */
425 /* optimize ICONST (2^x) .. IREM --> IREMPOW2 (const) */
427 if (len >= 2 && iptr[1].opc == ICMD_IREM) {
428 switch (iptr[0].sx.val.i) {
429 case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
430 case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
431 case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
432 case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
433 case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
434 case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
435 case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
436 case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
437 iptr[0].opc = ICMD_IREMPOW2;
439 iptr[1].opc = ICMD_NOP;
444 /* optimize ICONST (2^x) .. IDIV --> IDIVPOW2 (const) */
446 if (len >= 2 && iptr[1].opc == ICMD_IDIV) {
447 switch (iptr[0].sx.val.i) {
448 case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
449 case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
450 case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
451 case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
452 case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
453 case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
454 case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
455 case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
456 default: goto dont_opt_IDIVPOW2;
458 iptr[0].opc = ICMD_IDIVPOW2;
459 iptr[1].opc = ICMD_NOP;
464 /* optimize ICONST .. IF_ICMPxx --> IFxx (const) */
467 switch (iptr[1].opc) {
468 case ICMD_IF_ICMPEQ: iptr[0].opc = ICMD_IFEQ; break;
469 case ICMD_IF_ICMPNE: iptr[0].opc = ICMD_IFNE; break;
470 case ICMD_IF_ICMPLT: iptr[0].opc = ICMD_IFLT; break;
471 case ICMD_IF_ICMPLE: iptr[0].opc = ICMD_IFLE; break;
472 case ICMD_IF_ICMPGT: iptr[0].opc = ICMD_IFGT; break;
473 case ICMD_IF_ICMPGE: iptr[0].opc = ICMD_IFGE; break;
474 default: goto dont_opt_IFxx;
476 iptr[0].dst.insindex = iptr[1].dst.insindex;
477 iptr[1].opc = ICMD_NOP;
482 gen_ICONST(cd, iptr->sx.val.i);
485 case ICMD_LCONST: /* ... ==> ..., constant */
486 /* op1 = 0, val.l = constant */
488 /* optimize LCONST (2^x) .. LREM --> LREMPOW2 (const) */
490 if (len >= 2 && iptr[1].opc == ICMD_LREM) {
491 switch (iptr[0].sx.val.l) {
492 case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
493 case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
494 case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
495 case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
496 case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
497 case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
498 case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
499 case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
500 iptr[0].opc = ICMD_LREMPOW2;
502 iptr[1].opc = ICMD_NOP;
507 /* optimize LCONST (2^x) .. LDIV --> LDIVPOW2 (const) */
509 if (len >= 2 && iptr[1].opc == ICMD_LDIV) {
510 switch (iptr[0].sx.val.l) {
511 case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
512 case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
513 case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
514 case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
515 case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
516 case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
517 case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
518 case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
519 default: goto dont_opt_LDIVPOW2;
521 iptr[0].opc = ICMD_LDIVPOW2;
522 iptr[1].opc = ICMD_NOP;
527 /* optimize LCONST .. LCMP .. IFxx (0) --> IF_Lxx */
529 if (len >= 3 && iptr[1].opc == ICMD_LCMP && iptr[2].sx.val.i == 0) {
530 switch (iptr[2].opc) {
531 case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LEQ; break;
532 case ICMD_IFNE: iptr[0].opc = ICMD_IF_LNE; break;
533 case ICMD_IFLT: iptr[0].opc = ICMD_IF_LLT; break;
534 case ICMD_IFLE: iptr[0].opc = ICMD_IF_LLE; break;
535 case ICMD_IFGT: iptr[0].opc = ICMD_IF_LGT; break;
536 case ICMD_IFGE: iptr[0].opc = ICMD_IF_LGE; break;
537 default: goto dont_opt_IF_Lxx;
539 iptr[0].dst.insindex = iptr[2].dst.insindex;
540 iptr[1].opc = ICMD_NOP;
541 iptr[2].opc = ICMD_NOP;
546 gen_LCONST(cd, iptr->sx.val.l);
549 case ICMD_FCONST: /* ... ==> ..., constant */
550 /* op1 = 0, val.f = constant */
554 vm_f2Cell(iptr->sx.val.f, fi);
559 case ICMD_DCONST: /* ... ==> ..., constant */
560 /* op1 = 0, val.d = constant */
562 gen_LCONST(cd, *(s8 *)&(iptr->sx.val.d));
565 case ICMD_ACONST: /* ... ==> ..., constant */
566 /* op1 = 0, val.a = constant */
568 if (INSTRUCTION_IS_UNRESOLVED(iptr))
569 gen_PATCHER_ACONST(cd, NULL, iptr->sx.val.c.ref);
571 gen_ACONST(cd, iptr->sx.val.anyptr);
575 /* load/store operations **********************************************/
577 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
578 /* op1 = local variable */
580 gen_ILOAD(cd, index2offset(iptr->s1.varindex));
583 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
584 /* op1 = local variable */
586 gen_LLOAD(cd, index2offset(iptr->s1.varindex));
589 case ICMD_ALOAD: /* ... ==> ..., content of local variable */
590 /* op1 = local variable */
592 gen_ALOAD(cd, index2offset(iptr->s1.varindex));
595 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
596 /* op1 = local variable */
598 gen_ILOAD(cd, index2offset(iptr->s1.varindex));
601 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
602 /* op1 = local variable */
604 gen_LLOAD(cd, index2offset(iptr->s1.varindex));
608 case ICMD_ISTORE: /* ..., value ==> ... */
609 /* op1 = local variable */
611 gen_ISTORE(cd, index2offset(iptr->dst.varindex));
614 case ICMD_LSTORE: /* ..., value ==> ... */
615 /* op1 = local variable */
617 gen_LSTORE(cd, index2offset(iptr->dst.varindex));
620 case ICMD_ASTORE: /* ..., value ==> ... */
621 /* op1 = local variable */
623 gen_ASTORE(cd, index2offset(iptr->dst.varindex));
627 case ICMD_FSTORE: /* ..., value ==> ... */
628 /* op1 = local variable */
630 gen_ISTORE(cd, index2offset(iptr->dst.varindex));
633 case ICMD_DSTORE: /* ..., value ==> ... */
634 /* op1 = local variable */
636 gen_LSTORE(cd, index2offset(iptr->dst.varindex));
640 /* pop/dup/swap operations ********************************************/
642 case ICMD_POP: /* ..., value ==> ... */
647 case ICMD_POP2: /* ..., value, value ==> ... */
652 case ICMD_DUP: /* ..., a ==> ..., a, a */
657 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
662 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
667 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
672 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
677 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
682 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
688 /* integer operations *************************************************/
690 case ICMD_INEG: /* ..., value ==> ..., - value */
695 case ICMD_LNEG: /* ..., value ==> ..., - value */
700 case ICMD_I2L: /* ..., value ==> ..., value */
705 case ICMD_L2I: /* ..., value ==> ..., value */
710 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
715 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
720 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
726 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
731 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
736 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
741 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
746 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
751 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
756 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
761 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
766 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
771 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
776 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
777 /* val.i = constant */
779 gen_IDIVPOW2(cd, iptr->sx.val.i);
782 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
783 /* val.i = constant */
785 gen_IREMPOW2(cd, iptr->sx.val.i);
788 case ICMD_LDIVPOW2: /* ..., value ==> ..., value << constant */
789 /* val.i = constant */
791 gen_LDIVPOW2(cd, iptr->sx.val.i);
794 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
795 /* val.l = constant */
797 gen_LREMPOW2(cd, iptr->sx.val.i);
800 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
805 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
810 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
815 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
820 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
825 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
830 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
835 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
840 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
845 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
850 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
855 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
861 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
863 /* optimize LCMP .. IFxx (0) --> IF_LCMPxx */
865 if (len >= 2 && iptr[1].sx.val.i == 0) {
866 switch (iptr[1].opc) {
867 case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LCMPEQ; break;
868 case ICMD_IFNE: iptr[0].opc = ICMD_IF_LCMPNE; break;
869 case ICMD_IFLT: iptr[0].opc = ICMD_IF_LCMPLT; break;
870 case ICMD_IFLE: iptr[0].opc = ICMD_IF_LCMPLE; break;
871 case ICMD_IFGT: iptr[0].opc = ICMD_IF_LCMPGT; break;
872 case ICMD_IFGE: iptr[0].opc = ICMD_IF_LCMPGE; break;
873 default: goto dont_opt_IF_LCMPxx;
875 iptr[0].dst.insindex = iptr[1].dst.insindex;
876 iptr[1].opc = ICMD_NOP;
885 case ICMD_IINC: /* ..., value ==> ..., value + constant */
886 /* op1 = variable, val.i = constant */
888 gen_IINC(cd, index2offset(iptr->s1.varindex), iptr->sx.val.i);
892 /* floating operations ************************************************/
894 case ICMD_FNEG: /* ..., value ==> ..., - value */
899 case ICMD_DNEG: /* ..., value ==> ..., - value */
904 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
909 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
914 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
919 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
924 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
929 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
934 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
939 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
944 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
949 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
954 case ICMD_I2F: /* ..., value ==> ..., (float) value */
959 case ICMD_L2F: /* ..., value ==> ..., (float) value */
964 case ICMD_I2D: /* ..., value ==> ..., (double) value */
969 case ICMD_L2D: /* ..., value ==> ..., (double) value */
974 case ICMD_F2I: /* ..., value ==> ..., (int) value */
979 case ICMD_D2I: /* ..., value ==> ..., (int) value */
984 case ICMD_F2L: /* ..., value ==> ..., (long) value */
989 case ICMD_D2L: /* ..., value ==> ..., (long) value */
994 case ICMD_F2D: /* ..., value ==> ..., (double) value */
999 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1004 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1009 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1014 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1019 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1025 /* memory operations **************************************************/
1027 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1029 gen_ARRAYLENGTH(cd);
1032 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1037 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1042 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1047 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1052 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1057 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1058 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1063 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1069 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1074 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1075 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1080 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1085 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1090 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1091 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1096 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1102 case ICMD_GETSTATIC: /* ... ==> ..., value */
1103 /* op1 = type, val.a = field address */
1105 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1107 uf = iptr->sx.s23.s3.uf;
1108 fieldtype = uf->fieldref->parseddesc.fd->type;
1111 fi = iptr->sx.s23.s3.fmiref->p.field;
1113 fieldtype = fi->type;
1116 switch (fieldtype) {
1119 gen_PATCHER_GETSTATIC_INT(cd, 0, uf);
1120 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1121 gen_PATCHER_GETSTATIC_CLINIT_INT(cd, 0, fi);
1123 gen_GETSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1127 gen_PATCHER_GETSTATIC_FLOAT(cd, 0, uf);
1128 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1129 gen_PATCHER_GETSTATIC_CLINIT_FLOAT(cd, 0, fi);
1131 gen_GETSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1136 gen_PATCHER_GETSTATIC_LONG(cd, 0, uf);
1137 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1138 gen_PATCHER_GETSTATIC_CLINIT_LONG(cd, 0, fi);
1140 gen_GETSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1144 gen_PATCHER_GETSTATIC_CELL(cd, 0, uf);
1145 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1146 gen_PATCHER_GETSTATIC_CLINIT_CELL(cd, 0, fi);
1148 gen_GETSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1153 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1154 /* op1 = type, val.a = field address */
1156 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1158 uf = iptr->sx.s23.s3.uf;
1159 fieldtype = uf->fieldref->parseddesc.fd->type;
1162 fi = iptr->sx.s23.s3.fmiref->p.field;
1164 fieldtype = fi->type;
1167 switch (fieldtype) {
1170 gen_PATCHER_PUTSTATIC_INT(cd, 0, uf);
1171 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1172 gen_PATCHER_PUTSTATIC_CLINIT_INT(cd, 0, fi);
1174 gen_PUTSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
1178 gen_PATCHER_PUTSTATIC_FLOAT(cd, 0, uf);
1179 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1180 gen_PATCHER_PUTSTATIC_CLINIT_FLOAT(cd, 0, fi);
1182 gen_PUTSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
1187 gen_PATCHER_PUTSTATIC_LONG(cd, 0, uf);
1188 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1189 gen_PATCHER_PUTSTATIC_CLINIT_LONG(cd, 0, fi);
1191 gen_PUTSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
1195 gen_PATCHER_PUTSTATIC_CELL(cd, 0, uf);
1196 else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1197 gen_PATCHER_PUTSTATIC_CLINIT_CELL(cd, 0, fi);
1199 gen_PUTSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
1205 case ICMD_GETFIELD: /* ... ==> ..., value */
1206 /* op1 = type, val.a = field address */
1208 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1210 uf = iptr->sx.s23.s3.uf;
1211 fieldtype = uf->fieldref->parseddesc.fd->type;
1214 fi = iptr->sx.s23.s3.fmiref->p.field;
1216 fieldtype = fi->type;
1219 switch (fieldtype) {
1222 gen_PATCHER_GETFIELD_INT(cd, 0, uf);
1224 gen_GETFIELD_INT(cd, fi->offset, fi);
1228 gen_PATCHER_GETFIELD_FLOAT(cd, 0, uf);
1230 gen_GETFIELD_FLOAT(cd, fi->offset, fi);
1235 gen_PATCHER_GETFIELD_LONG(cd, 0, uf);
1237 gen_GETFIELD_LONG(cd, fi->offset, fi);
1241 gen_PATCHER_GETFIELD_CELL(cd, 0, uf);
1243 gen_GETFIELD_CELL(cd, fi->offset, fi);
1248 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1249 /* op1 = type, val.a = field address */
1251 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1253 uf = iptr->sx.s23.s3.uf;
1254 fieldtype = uf->fieldref->parseddesc.fd->type;
1257 fi = iptr->sx.s23.s3.fmiref->p.field;
1259 fieldtype = fi->type;
1262 switch (fieldtype) {
1265 gen_PATCHER_PUTFIELD_INT(cd, 0, uf);
1267 gen_PUTFIELD_INT(cd, fi->offset, fi);
1271 gen_PATCHER_PUTFIELD_FLOAT(cd, 0, uf);
1273 gen_PUTFIELD_FLOAT(cd, fi->offset, fi);
1278 gen_PATCHER_PUTFIELD_LONG(cd, 0, uf);
1280 gen_PUTFIELD_LONG(cd, fi->offset, fi);
1284 gen_PATCHER_PUTFIELD_CELL(cd, 0, uf);
1286 gen_PUTFIELD_CELL(cd, fi->offset, fi);
1292 /* branch operations **************************************************/
1294 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1299 case ICMD_GOTO: /* ... ==> ... */
1300 /* op1 = target JavaVM pc */
1304 case ICMD_JSR: /* ... ==> ... */
1305 /* op1 = target JavaVM pc */
1308 codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex));
1311 case ICMD_RET: /* ... ==> ... */
1312 /* op1 = local variable */
1314 gen_RET(cd, index2offset(iptr->s1.varindex));
1317 case ICMD_IFNULL: /* ..., value ==> ... */
1318 /* op1 = target JavaVM pc */
1323 case ICMD_IFNONNULL: /* ..., value ==> ... */
1324 /* op1 = target JavaVM pc */
1326 gen_branch(IFNONNULL);
1329 case ICMD_IFEQ: /* ..., value ==> ... */
1330 /* op1 = target JavaVM pc, val.i = constant */
1332 if (iptr->sx.val.i == 0) {
1335 gen_ICONST(cd, iptr->sx.val.i);
1336 gen_branch(IF_ICMPEQ);
1340 case ICMD_IFLT: /* ..., value ==> ... */
1341 /* op1 = target JavaVM pc, val.i = constant */
1343 if (iptr->sx.val.i == 0) {
1346 gen_ICONST(cd, iptr->sx.val.i);
1347 gen_branch(IF_ICMPLT);
1351 case ICMD_IFLE: /* ..., value ==> ... */
1352 /* op1 = target JavaVM pc, val.i = constant */
1354 if (iptr->sx.val.i == 0) {
1357 gen_ICONST(cd, iptr->sx.val.i);
1358 gen_branch(IF_ICMPLE);
1362 case ICMD_IFNE: /* ..., value ==> ... */
1363 /* op1 = target JavaVM pc, val.i = constant */
1365 if (iptr->sx.val.i == 0) {
1368 gen_ICONST(cd, iptr->sx.val.i);
1369 gen_branch(IF_ICMPNE);
1373 case ICMD_IFGT: /* ..., value ==> ... */
1374 /* op1 = target JavaVM pc, val.i = constant */
1376 if (iptr->sx.val.i == 0) {
1379 gen_ICONST(cd, iptr->sx.val.i);
1380 gen_branch(IF_ICMPGT);
1384 case ICMD_IFGE: /* ..., value ==> ... */
1385 /* op1 = target JavaVM pc, val.i = constant */
1387 if (iptr->sx.val.i == 0) {
1390 gen_ICONST(cd, iptr->sx.val.i);
1391 gen_branch(IF_ICMPGE);
1396 case ICMD_IF_LEQ: /* ..., value ==> ... */
1397 /* op1 = target JavaVM pc, val.l = constant */
1399 gen_LCONST(cd, iptr->sx.val.l);
1400 gen_branch(IF_LCMPEQ);
1403 case ICMD_IF_LLT: /* ..., value ==> ... */
1404 /* op1 = target JavaVM pc, val.l = constant */
1406 gen_LCONST(cd, iptr->sx.val.l);
1407 gen_branch(IF_LCMPLT);
1410 case ICMD_IF_LLE: /* ..., value ==> ... */
1411 /* op1 = target JavaVM pc, val.l = constant */
1413 gen_LCONST(cd, iptr->sx.val.l);
1414 gen_branch(IF_LCMPLE);
1417 case ICMD_IF_LNE: /* ..., value ==> ... */
1418 /* op1 = target JavaVM pc, val.l = constant */
1420 gen_LCONST(cd, iptr->sx.val.l);
1421 gen_branch(IF_LCMPNE);
1424 case ICMD_IF_LGT: /* ..., value ==> ... */
1425 /* op1 = target JavaVM pc, val.l = constant */
1427 gen_LCONST(cd, iptr->sx.val.l);
1428 gen_branch(IF_LCMPGT);
1431 case ICMD_IF_LGE: /* ..., value ==> ... */
1432 /* op1 = target JavaVM pc, val.l = constant */
1434 gen_LCONST(cd, iptr->sx.val.l);
1435 gen_branch(IF_LCMPGE);
1438 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
1439 /* op1 = target JavaVM pc */
1441 gen_branch(IF_LCMPEQ);
1444 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
1445 /* op1 = target JavaVM pc */
1447 gen_branch(IF_LCMPNE);
1450 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
1451 /* op1 = target JavaVM pc */
1453 gen_branch(IF_LCMPLT);
1456 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
1457 /* op1 = target JavaVM pc */
1459 gen_branch(IF_LCMPGT);
1462 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
1463 /* op1 = target JavaVM pc */
1465 gen_branch(IF_LCMPLE);
1468 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
1469 /* op1 = target JavaVM pc */
1471 gen_branch(IF_LCMPGE);
1475 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1476 /* op1 = target JavaVM pc */
1478 gen_branch(IF_ICMPEQ);
1481 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
1482 /* op1 = target JavaVM pc */
1484 gen_branch(IF_ACMPEQ);
1487 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
1488 /* op1 = target JavaVM pc */
1490 gen_branch(IF_ICMPNE);
1493 case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
1494 /* op1 = target JavaVM pc */
1496 gen_branch(IF_ACMPNE);
1499 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
1500 /* op1 = target JavaVM pc */
1502 gen_branch(IF_ICMPLT);
1505 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
1506 /* op1 = target JavaVM pc */
1508 gen_branch(IF_ICMPGT);
1511 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
1512 /* op1 = target JavaVM pc */
1514 gen_branch(IF_ICMPLE);
1517 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
1518 /* op1 = target JavaVM pc */
1520 gen_branch(IF_ICMPGE);
1524 case ICMD_ARETURN: /* ..., retvalue ==> ... */
1525 case ICMD_IRETURN: /* ..., retvalue ==> ... */
1526 case ICMD_FRETURN: /* ..., retvalue ==> ... */
1528 #if defined(ENABLE_THREADS)
1529 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1530 if (m->flags & ACC_STATIC) {
1531 gen_ACONST(cd, (java_objectheader *) m->class);
1533 gen_ALOAD(cd, index2offset(m->maxlocals));
1535 gen_MONITOREXIT(cd);
1538 if (opt_verbosecall)
1539 gen_TRACERETURN(cd, m);
1541 gen_IRETURN(cd, index2offset(cd->stackframesize));
1544 case ICMD_LRETURN: /* ..., retvalue ==> ... */
1545 case ICMD_DRETURN: /* ..., retvalue ==> ... */
1547 #if defined(ENABLE_THREADS)
1548 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1549 if (m->flags & ACC_STATIC) {
1550 gen_ACONST(cd, (java_objectheader *) m->class);
1552 gen_ALOAD(cd, index2offset(m->maxlocals));
1554 gen_MONITOREXIT(cd);
1557 if (opt_verbosecall)
1558 gen_TRACELRETURN(cd, m);
1560 gen_LRETURN(cd, index2offset(cd->stackframesize));
1563 case ICMD_RETURN: /* ... ==> ... */
1565 #if defined(ENABLE_THREADS)
1566 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1567 if (m->flags & ACC_STATIC) {
1568 gen_ACONST(cd, (java_objectheader *) m->class);
1570 gen_ALOAD(cd, index2offset(m->maxlocals));
1572 gen_MONITOREXIT(cd);
1575 if (opt_verbosecall)
1576 gen_TRACERETURN(cd, m);
1578 gen_RETURN(cd, index2offset(cd->stackframesize));
1582 case ICMD_TABLESWITCH: /* ..., index ==> ... */
1585 branch_target_t *table;
1587 table = iptr->dst.table;
1589 l = iptr->sx.s23.s2.tablelow;
1590 i = iptr->sx.s23.s3.tablehigh;
1594 /* arguments: low, range, datasegment address, table
1595 offset in datasegment, default target */
1597 gen_TABLESWITCH(cd, l, i, NULL, 0, NULL);
1599 /* actually -3 cells offset */
1601 cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1603 cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1605 codegen_addreference(cd, BLOCK_OF(table[0].insindex));
1607 /* build jump table top down and use address of lowest entry */
1612 dseg_add_target(cd, BLOCK_OF(table->insindex));
1617 /* length of dataseg after last dseg_add_target is used by load */
1618 ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1622 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
1625 lookup_target_t *lookup;
1627 lookup = iptr->dst.lookup;
1629 i = iptr->sx.s23.s2.lookupcount;
1631 /* arguments: count, datasegment address, table offset in */
1632 /* datasegment, default target */
1633 gen_LOOKUPSWITCH(cd, i, NULL, 0, NULL);
1635 /* actually -3 cells offset */
1637 cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
1639 cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
1641 /* build jump table top down and use address of lowest entry */
1644 dseg_add_target(cd, BLOCK_OF(lookup->target.insindex));
1645 dseg_add_unique_address(cd, lookup->value);
1649 codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex));
1652 /* length of dataseg after last dseg_add_target is used by load */
1653 ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
1657 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
1658 /* op1 = arg count val.a = builtintable entry */
1659 bte = iptr->sx.s23.s3.bte;
1661 for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
1662 builtin_gen *bg = &builtin_gen_table[i];
1663 if (bg->builtin == bte->fp) {
1665 goto gen_builtin_end;
1674 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
1675 /* op1 = arg count, val.a = method pointer */
1677 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1678 um = iptr->sx.s23.s3.um;
1679 md = um->methodref->parseddesc.md;
1680 gen_PATCHER_INVOKESTATIC(cd, 0, md->paramslots, um);
1683 lm = iptr->sx.s23.s3.fmiref->p.method;
1684 md = lm->parseddesc;
1685 gen_INVOKESTATIC(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1689 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
1691 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1692 um = iptr->sx.s23.s3.um;
1693 md = um->methodref->parseddesc.md;
1694 gen_PATCHER_INVOKESPECIAL(cd, 0, md->paramslots, um);
1697 lm = iptr->sx.s23.s3.fmiref->p.method;
1698 md = lm->parseddesc;
1699 gen_INVOKESPECIAL(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
1703 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
1705 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1706 um = iptr->sx.s23.s3.um;
1707 md = um->methodref->parseddesc.md;
1708 gen_PATCHER_INVOKEVIRTUAL(cd, 0, md->paramslots, um);
1711 lm = iptr->sx.s23.s3.fmiref->p.method;
1712 md = lm->parseddesc;
1714 s1 = OFFSET(vftbl_t, table[0]) +
1715 sizeof(methodptr) * lm->vftblindex;
1717 gen_INVOKEVIRTUAL(cd, s1, md->paramslots, lm);
1721 case ICMD_INVOKEINTERFACE:/* op1 = arg count, val.a = method pointer */
1723 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1724 um = iptr->sx.s23.s3.um;
1725 md = um->methodref->parseddesc.md;
1726 gen_PATCHER_INVOKEINTERFACE(cd, 0, 0, md->paramslots, um);
1729 lm = iptr->sx.s23.s3.fmiref->p.method;
1730 md = lm->parseddesc;
1732 s1 = OFFSET(vftbl_t, interfacetable[0]) -
1733 sizeof(methodptr*) * lm->class->index;
1735 s2 = sizeof(methodptr) * (lm - lm->class->methods);
1737 gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
1742 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
1743 /* op1: 0 == array, 1 == class */
1744 /* val.a: (classinfo *) superclass */
1746 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
1747 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1748 gen_PATCHER_CHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1750 gen_CHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1753 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1754 gen_PATCHER_ARRAYCHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
1756 gen_ARRAYCHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
1760 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
1761 /* op1: 0 == array, 1 == class */
1762 /* val.a: (classinfo *) superclass */
1764 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1765 gen_PATCHER_INSTANCEOF(cd, NULL, iptr->sx.s23.s3.c.ref);
1767 gen_INSTANCEOF(cd, iptr->sx.s23.s3.c.cls, iptr->sx.s23.s3.c.ref);
1770 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
1771 /* op1 = dimension, val.a = class */
1773 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1774 gen_PATCHER_MULTIANEWARRAY(cd, NULL, iptr->s1.argcount, iptr->sx.s23.s3.c.ref);
1776 gen_MULTIANEWARRAY(cd, iptr->sx.s23.s3.c.cls, iptr->s1.argcount, NULL);
1780 exceptions_throw_internalerror("Unknown ICMD %d during code generation",
1785 } /* for instruction */
1789 } /* if (bptr->flags != BBDELETED) */
1790 } /* for basic block */
1792 dseg_createlinenumbertable(cd);
1797 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
1800 /* branch resolving (walk through all basic blocks) */
1802 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
1805 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
1806 gen_resolveanybranch(((u1*) jd->code->entrypoint) + brefs->branchpos,
1807 ((u1 *)jd->code->entrypoint) + bptr->mpc);
1811 /* everything's ok */
1817 /* createcompilerstub **********************************************************
1819 Creates a stub routine which calls the compiler.
1825 +-------------+ <-- stub
1828 | framesize | (in ptrint units, does not include return address)
1835 codeptr points either to TRANSLATE or to the translated threaded code
1837 all methods are called indirectly through methodptr
1839 *******************************************************************************/
1841 #define COMPILERSTUB_DATASIZE 2
1842 #define COMPILERSTUB_CODESIZE 4
1844 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
1847 u1 *intrp_createcompilerstub(methodinfo *m)
1855 s = CNEW(Inst, COMPILERSTUB_SIZE);
1857 /* set data pointer and code pointer */
1860 s = s + COMPILERSTUB_DATASIZE;
1862 /* The codeinfo pointer is actually a pointer to the
1863 methodinfo. This fakes a codeinfo structure. */
1866 d[1] = (Inst *) &d[0]; /* fake code->m */
1868 /* mark start of dump memory area */
1870 dumpsize = dump_size();
1872 cd = DNEW(codegendata);
1873 cd->mcodeptr = (u1 *) s;
1874 cd->lastinstwithoutdispatch = ~0;
1875 cd->superstarts = NULL;
1877 genarg_ainst(cd, s + 2);
1879 if (m->flags & ACC_NATIVE) {
1880 stackframesize = m->parseddesc->paramslots;
1883 stackframesize = m->maxlocals;
1885 #if defined(ENABLE_THREADS)
1886 if (checksync && (m->flags & ACC_SYNCHRONIZED))
1887 stackframesize += 1;
1891 genarg_i(cd, stackframesize);
1894 gen_TRANSLATE(cd, m);
1898 vm_block_insert(cd->mcodeptr);
1901 #if defined(ENABLE_STATISTICS)
1903 count_cstub_len += COMPILERSTUB_SIZE;
1906 /* release dump area */
1908 dump_release(dumpsize);
1914 #if defined(WITH_FFI)
1915 static ffi_type *cacaotype2ffitype(s4 cacaotype)
1917 switch (cacaotype) {
1919 #if SIZEOF_VOID_P == 8
1920 return &ffi_type_sint64;
1922 return &ffi_type_sint32;
1925 return &ffi_type_sint64;
1927 return &ffi_type_float;
1929 return &ffi_type_double;
1931 return &ffi_type_pointer;
1933 return &ffi_type_void;
1953 #if defined(WITH_FFI)
1954 static ffi_cif *createnativecif(methodinfo *m, methoddesc *nmd)
1956 methoddesc *md = m->parseddesc;
1957 ffi_cif *pcif = NEW(ffi_cif);
1958 ffi_type **types = MNEW(ffi_type *, nmd->paramcount);
1959 ffi_type **ptypes = types;
1962 /* pass env pointer */
1964 *ptypes++ = &ffi_type_pointer;
1966 /* for static methods, pass class pointer */
1968 if (m->flags & ACC_STATIC)
1969 *ptypes++ = &ffi_type_pointer;
1971 /* pass parameter to native function */
1973 for (i = 0; i < md->paramcount; i++)
1974 *ptypes++ = cacaotype2ffitype(md->paramtypes[i].type);
1976 assert(ptypes - types == nmd->paramcount);
1978 if (ffi_prep_cif(pcif, FFI_DEFAULT_ABI, nmd->paramcount, cacaotype2ffitype(md->returntype.type), types) != FFI_OK)
1986 u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
1992 #if defined(WITH_FFI)
1999 /* get required compiler data */
2006 /* determine stackframe size (in units of ptrint) */
2008 stackframesize = nmd->paramslots;
2010 /* create method header */
2012 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
2013 (void) dseg_add_unique_s4(cd, stackframesize * SIZEOF_VOID_P); /*FrameSize*/
2014 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2015 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2016 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2017 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2018 dseg_addlinenumbertablesize(cd);
2019 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2021 #if defined(WITH_FFI)
2022 /* prepare ffi cif structure */
2024 cif = createnativecif(m, nmd);
2031 if (opt_verbosecall)
2032 gen_TRACECALL(cd, m);
2035 gen_PATCHER_NATIVECALL(cd, m, f, (u1 *)cif);
2037 if (opt_verbosecall)
2038 gen_TRACENATIVECALL(cd, m, f, (u1 *)cif);
2040 gen_NATIVECALL(cd, m, f, (u1 *)cif);
2048 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2051 return jd->code->entrypoint;
2055 /* call jni function */
2056 Cell *nativecall(functionptr f, methodinfo *m, Cell *sp, Inst *ra, Cell *fp, u1 *addrcif)
2058 #if defined(WITH_FFCALL)
2072 switch (md->returntype.type) {
2074 endsp = sp - 1 + md->paramslots;
2075 av_start_long(alist, f, endsp);
2078 endsp = sp - 2 + md->paramslots;
2079 av_start_longlong(alist, f, endsp);
2082 endsp = sp - 1 + md->paramslots;
2083 av_start_float(alist, f, endsp);
2086 endsp = sp - 2 + md->paramslots;
2087 av_start_double(alist, f, endsp);
2090 endsp = sp - 1 + md->paramslots;
2091 av_start_ptr(alist, f, void *, endsp);
2094 endsp = sp + md->paramslots;
2095 av_start_void(alist, f);
2101 av_ptr(alist, _Jv_JNIEnv *, _Jv_env);
2103 if (m->flags & ACC_STATIC)
2104 av_ptr(alist, classinfo *, m->class);
2106 for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2107 switch (md->paramtypes[i].type) {
2114 av_longlong(alist, *(s8 *)p);
2118 av_float(alist, *((float *) p));
2122 av_double(alist, *(double *) p);
2126 av_ptr(alist, void *, *(void **) p);
2135 /* create stackframe info structure */
2137 codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2138 (u1 *) fp, (u1 *) ra);
2142 *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2147 #elif defined(WITH_FFI)
2148 methoddesc *md = m->parseddesc;
2150 void *values[md->paramcount + 2];
2151 void **pvalues = values;
2162 pcif = (ffi_cif *) addrcif;
2164 /* pass env pointer */
2166 penv = (_Jv_JNIEnv *) _Jv_env;
2169 /* for static methods, pass class pointer */
2171 if (m->flags & ACC_STATIC)
2172 *pvalues++ = &m->class;
2174 /* pass parameter to native function */
2176 for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
2177 if (IS_2_WORD_TYPE(md->paramtypes[i].type))
2185 /* calculate position of return value */
2187 if (md->returntype.type == TYPE_VOID)
2188 endsp = sp + md->paramslots;
2190 endsp = sp - (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1) + md->paramslots;
2194 /* create stackframe info structure */
2196 codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
2197 (u1 *) fp, (u1 *) ra);
2199 ffi_call(pcif, FFI_FN(f), endsp, values);
2201 *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
2210 u1 *createcalljavafunction(methodinfo *m)
2220 /* mark dump memory */
2222 dumpsize = dump_size();
2224 /* allocate memory */
2228 tmpm = DNEW(methodinfo);
2229 cd = DNEW(codegendata);
2230 rd = DNEW(registerdata);
2237 /* Allocate codeinfo memory from the heap as we need to keep them. */
2239 jd->code = code_codeinfo_new(tmpm); /* XXX check allocation */
2241 /* setup code generation stuff */
2243 MSET(tmpm, 0, u1, sizeof(methodinfo));
2249 /* create method header */
2251 (void) dseg_add_unique_address(cd, NULL); /* CodeinfoPointer */
2252 (void) dseg_add_unique_s4(cd, md->paramslots * SIZEOF_VOID_P);/* FrameSize*/
2253 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
2254 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
2255 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
2256 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
2257 dseg_addlinenumbertablesize(cd);
2258 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
2264 gen_INVOKESTATIC(cd, (Inst **)m->stubroutine, md->paramslots, 0);
2272 vm_block_insert(jd->code->mcode + jd->code->mcodelength);
2274 entrypoint = jd->code->entrypoint;
2276 /* release memory */
2278 dump_release(dumpsize);
2285 * These are local overrides for various environment variables in Emacs.
2286 * Please do not remove this and leave it at the end of the file, where
2287 * Emacs will automagically detect them.
2288 * ---------------------------------------------------------------------
2291 * indent-tabs-mode: t
2295 * vim:noexpandtab:sw=4:ts=4: