-/* src/vm/jit/alpha/codegen.c - machine code generator for Alpha
+/* src/vm/jit/intrp/codegen.c - code generator for Interpreter
- Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+ C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+ E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+ J. Wenninger, Institut f. Computersprachen - TU Wien
This file is part of CACAO.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Andreas Krall
- Reinhard Grafl
-
- Changes: Joseph Wenninger
- Christian Thalinger
- Christian Ullrich
-
- $Id: codegen.c 3142 2005-09-05 15:12:36Z twisti $
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
*/
+#include "config.h"
+
+#include <assert.h>
#include <stdio.h>
-#include "config.h"
+#if defined(WITH_FFI)
+# include <ffi.h>
+#elif defined(WITH_FFCALL)
+# include <avcall.h>
+#else
+# error neither WITH_FFI nor WITH_FFCALL defined
+#endif
-#include "machine-instr.h"
+#include "vm/types.h"
+
+#include "arch.h"
-#include "vm/jit/intrp/arch.h"
#include "vm/jit/intrp/codegen.h"
-#include "vm/jit/intrp/types.h"
+#include "vm/jit/intrp/intrp.h"
+
+#include "mm/memory.h"
-#include "cacao/cacao.h"
#include "native/native.h"
+
#include "vm/builtin.h"
+#include "vm/exceptions.h"
#include "vm/global.h"
-#include "vm/loader.h"
#include "vm/stringlocal.h"
-#include "vm/tables.h"
+#include "vm/vm.h"
+
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen.inc"
+#include "vm/jit/codegen-common.h"
+#include "vm/jit/dseg.h"
#include "vm/jit/jit.h"
-
#include "vm/jit/parse.h"
#include "vm/jit/patcher.h"
+#include "vm/jit/stack.h"
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/class.h"
+#include "vmcore/options.h"
-#include "vm/jit/intrp/intrp.h"
#define gen_branch(_inst) { \
- gen_##_inst(&mcodeptr, 0); \
- codegen_addreference(cd, (basicblock *) (iptr->target), mcodeptr); \
+ gen_##_inst(cd, 0); \
+ codegen_addreference(cd, BLOCK_OF(iptr->dst.insindex)); \
}
+#define index2offset(_i) (-(_i) * SIZEOF_VOID_P)
/* functions used by cacao-gen.i */
-void
-genarg_v(Inst ** ptr2current_threaded, Cell v)
+void genarg_v(codegendata *cd1, Cell v)
{
- *((Cell *) *ptr2current_threaded) = v;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((Cell *) *mcodepp) = v;
+ (*mcodepp)++;
}
-void
-genarg_i(Inst ** ptr2cur_threaded, s4 i)
+void genarg_i(codegendata *cd1, s4 i)
{
- *((Cell *) *ptr2cur_threaded) = i;
- (*ptr2cur_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((Cell *) *mcodepp) = i;
+ (*mcodepp)++;
}
-void
-genarg_b(Inst ** ptr2cur_threaded, s4 i)
+void genarg_b(codegendata *cd1, s4 i)
{
- genarg_i(ptr2cur_threaded, i);
+ genarg_i(cd1, i);
}
-void
-genarg_f(Inst ** ptr2cur_threaded, float f)
+void genarg_f(codegendata *cd1, float f)
{
s4 fi;
vm_f2Cell(f,fi);
- genarg_i(ptr2cur_threaded, fi);
+ genarg_i(cd1, fi);
}
-void
-genarg_l(Inst ** ptr2cur_threaded, s8 l)
+void genarg_l(codegendata *cd1, s8 l)
{
- vm_l2twoCell(l, ((Cell*)*ptr2cur_threaded)[1], ((Cell*)*ptr2cur_threaded)[0]);
- (*ptr2cur_threaded) +=2;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ vm_l2twoCell(l, ((Cell *) *mcodepp)[1], ((Cell *) *mcodepp)[0]);
+ (*mcodepp) +=2;
}
-void
-genarg_aRef(Inst ** ptr2current_threaded, java_objectheader *a)
+void genarg_aRef(codegendata *cd1, java_objectheader *a)
{
- *((java_objectheader **) *ptr2current_threaded) = a;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((java_objectheader **) *mcodepp) = a;
+ (*mcodepp)++;
}
-void
-genarg_aArray(Inst ** ptr2current_threaded, java_arrayheader *a)
+void genarg_aArray(codegendata *cd1, java_arrayheader *a)
{
- *((java_arrayheader **) *ptr2current_threaded) = a;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((java_arrayheader **) *mcodepp) = a;
+ (*mcodepp)++;
}
-void
-genarg_aaTarget(Inst ** ptr2current_threaded, Inst **a)
+void genarg_aaTarget(codegendata *cd1, Inst **a)
{
- *((Inst ***) *ptr2current_threaded) = a;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((Inst ***) *mcodepp) = a;
+ (*mcodepp)++;
}
-void
-genarg_aClass(Inst ** ptr2current_threaded, classinfo *a)
+void genarg_aClass(codegendata *cd1, classinfo *a)
{
- *((classinfo **) *ptr2current_threaded) = a;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((classinfo **) *mcodepp) = a;
+ (*mcodepp)++;
}
-void
-genarg_acr(Inst ** ptr2current_threaded, constant_classref *a)
+void genarg_acr(codegendata *cd1, constant_classref *a)
{
- *((constant_classref **) *ptr2current_threaded) = a;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((constant_classref **) *mcodepp) = a;
+ (*mcodepp)++;
}
-void
-genarg_addr(Inst ** ptr2current_threaded, u1 *a)
+void genarg_addr(codegendata *cd1, u1 *a)
{
- *((u1 **) *ptr2current_threaded) = a;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((u1 **) *mcodepp) = a;
+ (*mcodepp)++;
}
-void
-genarg_af(Inst ** ptr2current_threaded, functionptr a)
+void genarg_af(codegendata *cd1, functionptr a)
{
- *((functionptr *) *ptr2current_threaded) = a;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((functionptr *) *mcodepp) = a;
+ (*mcodepp)++;
}
-void
-genarg_am(Inst ** ptr2current_threaded, methodinfo *a)
+void genarg_afi(codegendata *cd1, fieldinfo *a)
{
- *((methodinfo **) *ptr2current_threaded) = a;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((fieldinfo **) *mcodepp) = a;
+ (*mcodepp)++;
}
-void
-genarg_acell(Inst ** ptr2current_threaded, Cell *a)
+void genarg_am(codegendata *cd1, methodinfo *a)
{
- *((Cell **) *ptr2current_threaded) = a;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((methodinfo **) *mcodepp) = a;
+ (*mcodepp)++;
}
-void
-genarg_ainst(Inst ** ptr2current_threaded, Inst *a)
+void genarg_acell(codegendata *cd1, Cell *a)
{
- *((Inst **) *ptr2current_threaded) = a;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((Cell **) *mcodepp) = a;
+ (*mcodepp)++;
}
-void
-genarg_auf(Inst ** ptr2current_threaded, unresolved_field *a)
+void genarg_ainst(codegendata *cd1, Inst *a)
{
- *((unresolved_field **) *ptr2current_threaded) = a;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((Inst **) *mcodepp) = a;
+ (*mcodepp)++;
}
-void
-genarg_aum(Inst ** ptr2current_threaded, unresolved_method *a)
+void genarg_auf(codegendata *cd1, unresolved_field *a)
{
- *((unresolved_method **) *ptr2current_threaded) = a;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((unresolved_field **) *mcodepp) = a;
+ (*mcodepp)++;
}
-void
-genarg_avftbl(Inst ** ptr2current_threaded, vftbl_t *a)
+void genarg_aum(codegendata *cd1, unresolved_method *a)
{
- *((vftbl_t **) *ptr2current_threaded) = a;
- (*ptr2current_threaded)++;
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((unresolved_method **) *mcodepp) = a;
+ (*mcodepp)++;
+}
+
+void genarg_avftbl(codegendata *cd1, vftbl_t *a)
+{
+ Inst **mcodepp = (Inst **) &(cd1->mcodeptr);
+ *((vftbl_t **) *mcodepp) = a;
+ (*mcodepp)++;
}
/* include the interpreter generation functions *******************************/
-#include "vm/jit/intrp/java-gen.i"
+/* Do not use "java-gen.i", it does not work with builddir. */
+#include <java-gen.i>
-typedef void (*genfunctionptr) (Inst **);
+typedef void (*genfunctionptr) (codegendata *);
typedef struct builtin_gen builtin_gen;
{BUILTIN_newarray_float, gen_NEWARRAY_FLOAT, },
{BUILTIN_newarray_double, gen_NEWARRAY_DOUBLE, },
{BUILTIN_arrayinstanceof, gen_ARRAYINSTANCEOF, },
-#if defined(USE_THREADS)
- {BUILTIN_monitorenter, gen_MONITORENTER, },
- {BUILTIN_monitorexit, gen_MONITOREXIT, },
+
+#if defined(ENABLE_THREADS)
+ {LOCK_monitor_enter, gen_MONITORENTER, },
+ {LOCK_monitor_exit, gen_MONITOREXIT, },
#endif
-};
-/*
- The following ones cannot use the BUILTIN mechanism, because they
- need the class as immediate arguments of the patcher
+#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
+ {BUILTIN_f2l, gen_F2L, },
+#endif
- PATCHER_builtin_new, gen_PATCHER_NEW,
- PATCHER_builtin_newarray, gen_PATCHER_NEWARRAY,
- PATCHER_builtin_arrayinstanceof, gen_PATCHER_ARRAYINSTANCEOF,
-*/
+#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
+ {BUILTIN_d2l, gen_D2L, },
+#endif
+
+#if !(SUPPORT_FLOAT && SUPPORT_F2I)
+ {BUILTIN_f2i, gen_F2I, },
+#endif
+
+#if !(SUPPORT_DOUBLE && SUPPORT_D2I)
+ {BUILTIN_d2i, gen_D2I, },
+#endif
+
+#if !SUPPORT_DIVISION
+ {BUILTIN_idiv, gen_IDIV, },
+ {BUILTIN_irem, gen_IREM, },
+#endif
+#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
+ {BUILTIN_ldiv, gen_LDIV, },
+ {BUILTIN_lrem, gen_LREM, },
+#endif
+ {BUILTIN_frem, gen_FREM, },
+ {BUILTIN_drem, gen_DREM, },
+};
/* codegen *********************************************************************
*******************************************************************************/
-void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
+#define I(value) iptr[0].sx.val.i = (value); break;
+
+bool intrp_codegen(jitdata *jd)
{
+ methodinfo *m;
+ codegendata *cd;
+ registerdata *rd;
s4 i, len, s1, s2, d;
- Inst *mcodeptr;
- stackptr src;
basicblock *bptr;
instruction *iptr;
- exceptiontable *ex;
+ exception_entry *ex;
u2 currentline;
methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
unresolved_method *um;
builtintable_entry *bte;
methoddesc *md;
+ fieldinfo *fi;
+ unresolved_field *uf;
+ s4 fieldtype;
+
+ /* get required compiler data */
+
+ m = jd->m;
+ cd = jd->cd;
+ rd = jd->rd;
/* prevent compiler warnings */
lm = NULL;
bte = NULL;
+ /* determine stackframe size (in units of ptrint slots) */
+
+ cd->stackframesize = m->maxlocals;
+
+#if defined(ENABLE_THREADS)
+ if (checksync && (m->flags & ACC_SYNCHRONIZED))
+ cd->stackframesize += 1;
+#endif
+
/* create method header */
- (void) dseg_addaddress(cd, m); /* MethodPointer */
+ (void) dseg_add_unique_address(cd, jd->code);
+ (void) dseg_add_unique_s4(cd, cd->stackframesize * SIZEOF_VOID_P);
-#if defined(USE_THREADS)
+#if defined(ENABLE_THREADS)
if (checksync && (m->flags & ACC_SYNCHRONIZED))
- (void) dseg_adds4(cd, 1); /* IsSync */
+ (void) dseg_add_unique_s4(cd, 1);
else
#endif
- (void) dseg_adds4(cd, 0); /* IsSync */
+ (void) dseg_add_unique_s4(cd, 0);
+ (void) dseg_add_unique_s4(cd, 0);
+ (void) dseg_add_unique_s4(cd, 0);
+ (void) dseg_add_unique_s4(cd, 0);
+
dseg_addlinenumbertablesize(cd);
- (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
+ (void) dseg_add_unique_s4(cd, jd->exceptiontablelength);
/* create exception table */
- for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
- dseg_addtarget(cd, ex->start);
- dseg_addtarget(cd, ex->end);
- dseg_addtarget(cd, ex->handler);
- (void) dseg_addaddress(cd, ex->catchtype.cls);
+ for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
+ dseg_add_target(cd, ex->start);
+ dseg_add_target(cd, ex->end);
+ dseg_add_target(cd, ex->handler);
+ (void) dseg_add_unique_address(cd, ex->catchtype.any);
}
-
+
+#if 0
/* initialize mcode variables */
- mcodeptr = (s4 *) cd->mcodebase;
+ cd->mcodeptr = cd->mcodebase;
cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
+#endif
+
+ gen_BBSTART;
+
+#if defined(ENABLE_THREADS)
+ if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ if (m->flags & ACC_STATIC) {
+ gen_ACONST(cd, (java_objectheader *) m->class);
+ }
+ else {
+ gen_ALOAD(cd, 0);
+ gen_DUP(cd);
+ gen_ASTORE(cd, index2offset(m->maxlocals));
+ }
+
+ gen_MONITORENTER(cd);
+ }
+#endif
+
+ if (opt_verbosecall)
+ gen_TRACECALL(cd, m);
- if (runverbose)
- gen_TRACECALL(&mcodeptr);
+ gen_BBEND;
/* walk through all basic blocks */
- for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
+ for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
- bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
+ bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
- if (bptr->flags >= BBREACHED) {
+ if (bptr->flags != BBDELETED) {
/* walk through all instructions */
- src = bptr->instack;
len = bptr->icount;
- for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
+ gen_BBSTART;
+
+ for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
if (iptr->line != currentline) {
- dseg_addlinenumber(cd, iptr->line, (u1 *) mcodeptr);
+ dseg_addlinenumber(cd, iptr->line);
currentline = iptr->line;
}
MCODECHECK(64); /* an instruction usually needs < 64 words */
+
+switch_again:
switch (iptr->opc) {
case ICMD_INLINE_START:
case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
- gen_CHECKNULL(&mcodeptr);
+ gen_CHECKNULL(cd);
break;
/* constant operations ************************************************/
case ICMD_ICONST: /* ... ==> ..., constant */
/* op1 = 0, val.i = constant */
- gen_ICONST(&mcodeptr, iptr->val.i);
+ /* optimize ICONST (2^x) .. IREM --> IREMPOW2 (const) */
+
+ if (len >= 2 && iptr[1].opc == ICMD_IREM) {
+ switch (iptr[0].sx.val.i) {
+ case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
+ case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
+ case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
+ case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
+ case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
+ case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
+ case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
+ case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
+ iptr[0].opc = ICMD_IREMPOW2;
+ iptr[0].sx.val.i--;
+ iptr[1].opc = ICMD_NOP;
+ goto switch_again;
+ }
+ }
+
+ /* optimize ICONST (2^x) .. IDIV --> IDIVPOW2 (const) */
+
+ if (len >= 2 && iptr[1].opc == ICMD_IDIV) {
+ switch (iptr[0].sx.val.i) {
+ case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
+ case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
+ case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
+ case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
+ case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
+ case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
+ case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
+ case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
+ default: goto dont_opt_IDIVPOW2;
+ }
+ iptr[0].opc = ICMD_IDIVPOW2;
+ iptr[1].opc = ICMD_NOP;
+ goto switch_again;
+ }
+dont_opt_IDIVPOW2:
+
+ /* optimize ICONST .. IF_ICMPxx --> IFxx (const) */
+
+ if (len >= 2) {
+ switch (iptr[1].opc) {
+ case ICMD_IF_ICMPEQ: iptr[0].opc = ICMD_IFEQ; break;
+ case ICMD_IF_ICMPNE: iptr[0].opc = ICMD_IFNE; break;
+ case ICMD_IF_ICMPLT: iptr[0].opc = ICMD_IFLT; break;
+ case ICMD_IF_ICMPLE: iptr[0].opc = ICMD_IFLE; break;
+ case ICMD_IF_ICMPGT: iptr[0].opc = ICMD_IFGT; break;
+ case ICMD_IF_ICMPGE: iptr[0].opc = ICMD_IFGE; break;
+ default: goto dont_opt_IFxx;
+ }
+ iptr[0].dst.insindex = iptr[1].dst.insindex;
+ iptr[1].opc = ICMD_NOP;
+ goto switch_again;
+ }
+dont_opt_IFxx:
+
+ gen_ICONST(cd, iptr->sx.val.i);
break;
case ICMD_LCONST: /* ... ==> ..., constant */
/* op1 = 0, val.l = constant */
- gen_LCONST(&mcodeptr, iptr->val.l);
+ /* optimize LCONST (2^x) .. LREM --> LREMPOW2 (const) */
+
+ if (len >= 2 && iptr[1].opc == ICMD_LREM) {
+ switch (iptr[0].sx.val.l) {
+ case 0x00000001: case 0x00000002: case 0x00000004: case 0x00000008:
+ case 0x00000010: case 0x00000020: case 0x00000040: case 0x00000080:
+ case 0x00000100: case 0x00000200: case 0x00000400: case 0x00000800:
+ case 0x00001000: case 0x00002000: case 0x00004000: case 0x00008000:
+ case 0x00010000: case 0x00020000: case 0x00040000: case 0x00080000:
+ case 0x00100000: case 0x00200000: case 0x00400000: case 0x00800000:
+ case 0x01000000: case 0x02000000: case 0x04000000: case 0x08000000:
+ case 0x10000000: case 0x20000000: case 0x40000000: case 0x80000000:
+ iptr[0].opc = ICMD_LREMPOW2;
+ iptr[0].sx.val.l--;
+ iptr[1].opc = ICMD_NOP;
+ goto switch_again;
+ }
+ }
+
+ /* optimize LCONST (2^x) .. LDIV --> LDIVPOW2 (const) */
+
+ if (len >= 2 && iptr[1].opc == ICMD_LDIV) {
+ switch (iptr[0].sx.val.l) {
+ case 0x00000002: I( 1) case 0x00000004: I( 2) case 0x00000008: I( 3)
+ case 0x00000010: I( 4) case 0x00000020: I( 5) case 0x00000040: I( 6) case 0x00000080: I( 7)
+ case 0x00000100: I( 8) case 0x00000200: I( 9) case 0x00000400: I(10) case 0x00000800: I(11)
+ case 0x00001000: I(12) case 0x00002000: I(13) case 0x00004000: I(14) case 0x00008000: I(15)
+ case 0x00010000: I(16) case 0x00020000: I(17) case 0x00040000: I(18) case 0x00080000: I(19)
+ case 0x00100000: I(20) case 0x00200000: I(21) case 0x00400000: I(22) case 0x00800000: I(23)
+ case 0x01000000: I(24) case 0x02000000: I(25) case 0x04000000: I(26) case 0x08000000: I(27)
+ case 0x10000000: I(28) case 0x20000000: I(29) case 0x40000000: I(30) case 0x80000000: I(31)
+ default: goto dont_opt_LDIVPOW2;
+ }
+ iptr[0].opc = ICMD_LDIVPOW2;
+ iptr[1].opc = ICMD_NOP;
+ goto switch_again;
+ }
+dont_opt_LDIVPOW2:
+
+ /* optimize LCONST .. LCMP .. IFxx (0) --> IF_Lxx */
+
+ if (len >= 3 && iptr[1].opc == ICMD_LCMP && iptr[2].sx.val.i == 0) {
+ switch (iptr[2].opc) {
+ case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LEQ; break;
+ case ICMD_IFNE: iptr[0].opc = ICMD_IF_LNE; break;
+ case ICMD_IFLT: iptr[0].opc = ICMD_IF_LLT; break;
+ case ICMD_IFLE: iptr[0].opc = ICMD_IF_LLE; break;
+ case ICMD_IFGT: iptr[0].opc = ICMD_IF_LGT; break;
+ case ICMD_IFGE: iptr[0].opc = ICMD_IF_LGE; break;
+ default: goto dont_opt_IF_Lxx;
+ }
+ iptr[0].dst.insindex = iptr[2].dst.insindex;
+ iptr[1].opc = ICMD_NOP;
+ iptr[2].opc = ICMD_NOP;
+ goto switch_again;
+ }
+dont_opt_IF_Lxx:
+
+ gen_LCONST(cd, iptr->sx.val.l);
break;
case ICMD_FCONST: /* ... ==> ..., constant */
/* op1 = 0, val.f = constant */
{
- s4 fi;
+ ptrint fi;
- vm_f2Cell(iptr->val.f, fi);
- gen_ICONST(&mcodeptr, fi);
+ vm_f2Cell(iptr->sx.val.f, fi);
+ gen_ICONST(cd, fi);
}
break;
case ICMD_DCONST: /* ... ==> ..., constant */
/* op1 = 0, val.d = constant */
- gen_LCONST(&mcodeptr, *(s8 *)&(iptr->val.d));
+ gen_LCONST(cd, *(s8 *)&(iptr->sx.val.d));
break;
case ICMD_ACONST: /* ... ==> ..., constant */
/* op1 = 0, val.a = constant */
- gen_ACONST(&mcodeptr, iptr->val.a);
+ if (INSTRUCTION_IS_UNRESOLVED(iptr))
+ gen_PATCHER_ACONST(cd, NULL, iptr->sx.val.c.ref);
+ else
+ gen_ACONST(cd, iptr->sx.val.anyptr);
break;
case ICMD_ILOAD: /* ... ==> ..., content of local variable */
/* op1 = local variable */
- gen_ILOAD(&mcodeptr, iptr->op1);
+ gen_ILOAD(cd, index2offset(iptr->s1.varindex));
break;
case ICMD_LLOAD: /* ... ==> ..., content of local variable */
/* op1 = local variable */
- gen_LLOAD(&mcodeptr, iptr->op1);
+ gen_LLOAD(cd, index2offset(iptr->s1.varindex));
break;
case ICMD_ALOAD: /* ... ==> ..., content of local variable */
/* op1 = local variable */
- gen_ALOAD(&mcodeptr, iptr->op1);
+ gen_ALOAD(cd, index2offset(iptr->s1.varindex));
break;
case ICMD_FLOAD: /* ... ==> ..., content of local variable */
/* op1 = local variable */
- gen_ILOAD(&mcodeptr, iptr->op1);
+ gen_ILOAD(cd, index2offset(iptr->s1.varindex));
break;
case ICMD_DLOAD: /* ... ==> ..., content of local variable */
/* op1 = local variable */
- gen_LLOAD(&mcodeptr, iptr->op1);
+ gen_LLOAD(cd, index2offset(iptr->s1.varindex));
break;
case ICMD_ISTORE: /* ..., value ==> ... */
/* op1 = local variable */
- gen_ISTORE(&mcodeptr, iptr->op1);
+ gen_ISTORE(cd, index2offset(iptr->dst.varindex));
break;
case ICMD_LSTORE: /* ..., value ==> ... */
/* op1 = local variable */
- gen_LSTORE(&mcodeptr, iptr->op1);
+ gen_LSTORE(cd, index2offset(iptr->dst.varindex));
break;
case ICMD_ASTORE: /* ..., value ==> ... */
/* op1 = local variable */
- gen_ASTORE(&mcodeptr, iptr->op1);
+ gen_ASTORE(cd, index2offset(iptr->dst.varindex));
break;
case ICMD_FSTORE: /* ..., value ==> ... */
/* op1 = local variable */
- gen_ISTORE(&mcodeptr, iptr->op1);
+ gen_ISTORE(cd, index2offset(iptr->dst.varindex));
break;
case ICMD_DSTORE: /* ..., value ==> ... */
/* op1 = local variable */
- gen_LSTORE(&mcodeptr, iptr->op1);
+ gen_LSTORE(cd, index2offset(iptr->dst.varindex));
break;
/* pop/dup/swap operations ********************************************/
- /* attention: double and longs are only one entry in CACAO ICMDs */
-
- /* stack.c changes stack manipulation operations to treat
- longs/doubles as occupying a single slot. Here we are
- undoing that (and only those things that stack.c did). */
-
case ICMD_POP: /* ..., value ==> ... */
- if (IS_2_WORD_TYPE(src->type))
- gen_POP2(&mcodeptr);
- else
- gen_POP(&mcodeptr);
+ gen_POP(cd);
break;
case ICMD_POP2: /* ..., value, value ==> ... */
- gen_POP2(&mcodeptr);
+ gen_POP2(cd);
break;
case ICMD_DUP: /* ..., a ==> ..., a, a */
- if (IS_2_WORD_TYPE(src->type))
- gen_DUP2(&mcodeptr);
- else
- gen_DUP(&mcodeptr);
+ gen_DUP(cd);
break;
case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
- if (IS_2_WORD_TYPE(src->type)) {
- if (IS_2_WORD_TYPE(src->prev->type)) {
- gen_DUP2_X2(&mcodeptr);
- } else {
- gen_DUP2_X1(&mcodeptr);
- }
- } else {
- if (IS_2_WORD_TYPE(src->prev->type)) {
- gen_DUP_X2(&mcodeptr);
- } else {
- gen_DUP_X1(&mcodeptr);
- }
- }
+ gen_DUP_X1(cd);
break;
case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
- if (IS_2_WORD_TYPE(src->type)) {
- gen_DUP2_X2(&mcodeptr);
- } else
- gen_DUP_X2(&mcodeptr);
+ gen_DUP_X2(cd);
break;
case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
- gen_DUP2(&mcodeptr);
+ gen_DUP2(cd);
break;
case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
- if (IS_2_WORD_TYPE(src->prev->prev->type))
- gen_DUP2_X2(&mcodeptr);
- else
- gen_DUP2_X1(&mcodeptr);
+ gen_DUP2_X1(cd);
break;
case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
- gen_DUP2_X2(&mcodeptr);
+ gen_DUP2_X2(cd);
break;
case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
- gen_SWAP(&mcodeptr);
+ gen_SWAP(cd);
break;
case ICMD_INEG: /* ..., value ==> ..., - value */
- gen_INEG(&mcodeptr);
+ gen_INEG(cd);
break;
case ICMD_LNEG: /* ..., value ==> ..., - value */
- gen_LNEG(&mcodeptr);
+ gen_LNEG(cd);
break;
case ICMD_I2L: /* ..., value ==> ..., value */
- gen_I2L(&mcodeptr);
+ gen_I2L(cd);
break;
case ICMD_L2I: /* ..., value ==> ..., value */
- gen_L2I(&mcodeptr);
+ gen_L2I(cd);
break;
case ICMD_INT2BYTE: /* ..., value ==> ..., value */
- gen_INT2BYTE(&mcodeptr);
+ gen_INT2BYTE(cd);
break;
case ICMD_INT2CHAR: /* ..., value ==> ..., value */
- gen_INT2CHAR(&mcodeptr);
+ gen_INT2CHAR(cd);
break;
case ICMD_INT2SHORT: /* ..., value ==> ..., value */
- gen_INT2SHORT(&mcodeptr);
+ gen_INT2SHORT(cd);
break;
case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
- gen_IADD(&mcodeptr);
- break;
-
- case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
- /* val.i = constant */
-
- gen_ICONST(&mcodeptr, iptr->val.i);
- gen_IADD(&mcodeptr);
+ gen_IADD(cd);
break;
case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
- gen_LADD(&mcodeptr);
- break;
-
- case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
- /* val.l = constant */
-
- gen_LCONST(&mcodeptr, iptr->val.l);
- gen_LADD(&mcodeptr);
+ gen_LADD(cd);
break;
case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
- gen_ISUB(&mcodeptr);
- break;
-
- case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
- /* val.i = constant */
-
- gen_ICONST(&mcodeptr, iptr->val.i);
- gen_ISUB(&mcodeptr);
+ gen_ISUB(cd);
break;
case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
- gen_LSUB(&mcodeptr);
- break;
-
- case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
- /* val.l = constant */
-
- gen_LCONST(&mcodeptr, iptr->val.l);
- gen_LSUB(&mcodeptr);
+ gen_LSUB(cd);
break;
case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
- gen_IMUL(&mcodeptr);
- break;
-
- case ICMD_IMULCONST: /* ..., val1, val2 ==> ..., val1 * val2 */
-
- gen_ICONST(&mcodeptr, iptr->val.i);
- gen_IMUL(&mcodeptr);
+ gen_IMUL(cd);
break;
case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
- gen_LMUL(&mcodeptr);
- break;
-
- case ICMD_LMULCONST: /* ..., val1, val2 ==> ..., val1 * val2 */
-
- gen_LCONST(&mcodeptr, iptr->val.l);
- gen_LMUL(&mcodeptr);
+ gen_LMUL(cd);
break;
case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
- gen_IDIV(&mcodeptr);
+ gen_IDIV(cd);
break;
case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
- gen_IREM(&mcodeptr);
+ gen_IREM(cd);
break;
case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
- gen_LDIV(&mcodeptr);
+ gen_LDIV(cd);
break;
case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
- gen_LREM(&mcodeptr);
+ gen_LREM(cd);
break;
case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
/* val.i = constant */
- gen_IDIVPOW2(&mcodeptr, iptr->val.i);
+ gen_IDIVPOW2(cd, iptr->sx.val.i);
break;
case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
/* val.i = constant */
- gen_IREMPOW2(&mcodeptr, iptr->val.i);
+ gen_IREMPOW2(cd, iptr->sx.val.i);
break;
case ICMD_LDIVPOW2: /* ..., value ==> ..., value << constant */
/* val.i = constant */
- gen_LDIVPOW2(&mcodeptr, iptr->val.i);
+ gen_LDIVPOW2(cd, iptr->sx.val.i);
break;
case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
/* val.l = constant */
- gen_LREMPOW2(&mcodeptr, iptr->val.i);
+ gen_LREMPOW2(cd, iptr->sx.val.i);
break;
case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
- gen_ISHL(&mcodeptr);
- break;
-
- case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
- /* val.i = constant */
-
- gen_ICONST(&mcodeptr, iptr->val.i);
- gen_ISHL(&mcodeptr);
+ gen_ISHL(cd);
break;
case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
- gen_ISHR(&mcodeptr);
- break;
-
- case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
- /* val.i = constant */
-
- gen_ICONST(&mcodeptr, iptr->val.i);
- gen_ISHR(&mcodeptr);
+ gen_ISHR(cd);
break;
case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
- gen_IUSHR(&mcodeptr);
- break;
-
- case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
- /* val.i = constant */
-
- gen_ICONST(&mcodeptr, iptr->val.i);
- gen_IUSHR(&mcodeptr);
+ gen_IUSHR(cd);
break;
case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
- gen_LSHL(&mcodeptr);
- break;
-
- case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
- /* val.i = constant */
-
- gen_ICONST(&mcodeptr, iptr->val.i);
- gen_LSHL(&mcodeptr);
+ gen_LSHL(cd);
break;
case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
- gen_LSHR(&mcodeptr);
- break;
-
- case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
- /* val.i = constant */
-
- gen_ICONST(&mcodeptr, iptr->val.i);
- gen_LSHR(&mcodeptr);
+ gen_LSHR(cd);
break;
case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
- gen_LUSHR(&mcodeptr);
- break;
-
- case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
- /* val.i = constant */
-
- gen_ICONST(&mcodeptr, iptr->val.i);
- gen_LUSHR(&mcodeptr);
+ gen_LUSHR(cd);
break;
case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
- gen_IAND(&mcodeptr);
- break;
-
- case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
- /* val.i = constant */
-
- gen_ICONST(&mcodeptr, iptr->val.i);
- gen_IAND(&mcodeptr);
+ gen_IAND(cd);
break;
case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
- gen_LAND(&mcodeptr);
- break;
-
- case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
- /* val.l = constant */
-
- gen_LCONST(&mcodeptr, iptr->val.l);
- gen_LAND(&mcodeptr);
+ gen_LAND(cd);
break;
case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
- gen_IOR(&mcodeptr);
- break;
-
- case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
- /* val.i = constant */
-
- gen_ICONST(&mcodeptr, iptr->val.i);
- gen_IOR(&mcodeptr);
+ gen_IOR(cd);
break;
case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
- gen_LOR(&mcodeptr);
- break;
-
- case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
- /* val.l = constant */
-
- gen_LCONST(&mcodeptr, iptr->val.l);
- gen_LOR(&mcodeptr);
+ gen_LOR(cd);
break;
case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
- gen_IXOR(&mcodeptr);
- break;
-
- case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
- /* val.i = constant */
-
- gen_ICONST(&mcodeptr, iptr->val.i);
- gen_IXOR(&mcodeptr);
+ gen_IXOR(cd);
break;
case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
- gen_LXOR(&mcodeptr);
- break;
-
- case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
- /* val.l = constant */
-
- gen_LCONST(&mcodeptr, iptr->val.l);
- gen_LXOR(&mcodeptr);
+ gen_LXOR(cd);
break;
case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
- gen_LCMP(&mcodeptr);
+ /* optimize LCMP .. IFxx (0) --> IF_LCMPxx */
+
+ if (len >= 2 && iptr[1].sx.val.i == 0) {
+ switch (iptr[1].opc) {
+ case ICMD_IFEQ: iptr[0].opc = ICMD_IF_LCMPEQ; break;
+ case ICMD_IFNE: iptr[0].opc = ICMD_IF_LCMPNE; break;
+ case ICMD_IFLT: iptr[0].opc = ICMD_IF_LCMPLT; break;
+ case ICMD_IFLE: iptr[0].opc = ICMD_IF_LCMPLE; break;
+ case ICMD_IFGT: iptr[0].opc = ICMD_IF_LCMPGT; break;
+ case ICMD_IFGE: iptr[0].opc = ICMD_IF_LCMPGE; break;
+ default: goto dont_opt_IF_LCMPxx;
+ }
+ iptr[0].dst.insindex = iptr[1].dst.insindex;
+ iptr[1].opc = ICMD_NOP;
+ goto switch_again;
+ }
+dont_opt_IF_LCMPxx:
+
+ gen_LCMP(cd);
break;
case ICMD_IINC: /* ..., value ==> ..., value + constant */
/* op1 = variable, val.i = constant */
- gen_IINC(&mcodeptr, iptr->op1, iptr->val.i);
+ gen_IINC(cd, index2offset(iptr->s1.varindex), iptr->sx.val.i);
break;
case ICMD_FNEG: /* ..., value ==> ..., - value */
- gen_FNEG(&mcodeptr);
+ gen_FNEG(cd);
break;
case ICMD_DNEG: /* ..., value ==> ..., - value */
- gen_DNEG(&mcodeptr);
+ gen_DNEG(cd);
break;
case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
- gen_FADD(&mcodeptr);
+ gen_FADD(cd);
break;
case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
- gen_DADD(&mcodeptr);
+ gen_DADD(cd);
break;
case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
- gen_FSUB(&mcodeptr);
+ gen_FSUB(cd);
break;
case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
- gen_DSUB(&mcodeptr);
+ gen_DSUB(cd);
break;
case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
- gen_FMUL(&mcodeptr);
+ gen_FMUL(cd);
break;
case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
- gen_DMUL(&mcodeptr);
+ gen_DMUL(cd);
break;
case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
- gen_FDIV(&mcodeptr);
+ gen_FDIV(cd);
break;
case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
- gen_DDIV(&mcodeptr);
+ gen_DDIV(cd);
+ break;
+
+ case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
+
+ gen_FREM(cd);
+ break;
+
+ case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
+
+ gen_DREM(cd);
break;
case ICMD_I2F: /* ..., value ==> ..., (float) value */
- gen_I2F(&mcodeptr);
+ gen_I2F(cd);
break;
case ICMD_L2F: /* ..., value ==> ..., (float) value */
- gen_L2F(&mcodeptr);
+ gen_L2F(cd);
break;
case ICMD_I2D: /* ..., value ==> ..., (double) value */
- gen_I2D(&mcodeptr);
+ gen_I2D(cd);
break;
case ICMD_L2D: /* ..., value ==> ..., (double) value */
- gen_L2D(&mcodeptr);
+ gen_L2D(cd);
break;
case ICMD_F2I: /* ..., value ==> ..., (int) value */
- gen_F2I(&mcodeptr);
+ gen_F2I(cd);
break;
case ICMD_D2I: /* ..., value ==> ..., (int) value */
- gen_D2I(&mcodeptr);
+ gen_D2I(cd);
break;
case ICMD_F2L: /* ..., value ==> ..., (long) value */
- gen_F2L(&mcodeptr);
+ gen_F2L(cd);
break;
case ICMD_D2L: /* ..., value ==> ..., (long) value */
- gen_D2L(&mcodeptr);
+ gen_D2L(cd);
break;
case ICMD_F2D: /* ..., value ==> ..., (double) value */
- gen_F2D(&mcodeptr);
+ gen_F2D(cd);
break;
case ICMD_D2F: /* ..., value ==> ..., (float) value */
- gen_D2F(&mcodeptr);
+ gen_D2F(cd);
break;
case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
- gen_FCMPL(&mcodeptr);
+ gen_FCMPL(cd);
break;
case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
- gen_DCMPL(&mcodeptr);
+ gen_DCMPL(cd);
break;
case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
- gen_FCMPG(&mcodeptr);
+ gen_FCMPG(cd);
break;
case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
- gen_DCMPG(&mcodeptr);
+ gen_DCMPG(cd);
break;
case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
- gen_ARRAYLENGTH(&mcodeptr);
+ gen_ARRAYLENGTH(cd);
break;
case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
- gen_BALOAD(&mcodeptr);
+ gen_BALOAD(cd);
break;
case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
- gen_CALOAD(&mcodeptr);
+ gen_CALOAD(cd);
break;
case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
- gen_SALOAD(&mcodeptr);
+ gen_SALOAD(cd);
break;
case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
+
+ gen_IALOAD(cd);
+ break;
+
case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
- gen_IALOAD(&mcodeptr);
+ gen_FALOAD(cd);
break;
case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
- gen_LALOAD(&mcodeptr);
+ gen_LALOAD(cd);
break;
case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
- gen_AALOAD(&mcodeptr);
+ gen_AALOAD(cd);
break;
case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
- gen_BASTORE(&mcodeptr);
+ gen_BASTORE(cd);
break;
case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
- gen_CASTORE(&mcodeptr);
+ gen_CASTORE(cd);
break;
case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
+
+ gen_IASTORE(cd);
+ break;
+
case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
- gen_IASTORE(&mcodeptr);
+ gen_FASTORE(cd);
break;
case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
- gen_LASTORE(&mcodeptr);
+ gen_LASTORE(cd);
break;
case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
- gen_AASTORE(&mcodeptr);
+ gen_AASTORE(cd);
break;
case ICMD_GETSTATIC: /* ... ==> ..., value */
/* op1 = type, val.a = field address */
- {
- fieldinfo *fi = iptr->val.a;
- unresolved_field *uf = iptr->target;
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ fi = NULL;
+ uf = iptr->sx.s23.s3.uf;
+ fieldtype = uf->fieldref->parseddesc.fd->type;
+ }
+ else {
+ fi = iptr->sx.s23.s3.fmiref->p.field;
+ uf = NULL;
+ fieldtype = fi->type;
+ }
- switch (iptr->op1) {
+ switch (fieldtype) {
case TYPE_INT:
+ if (fi == NULL)
+ gen_PATCHER_GETSTATIC_INT(cd, 0, uf);
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ gen_PATCHER_GETSTATIC_CLINIT_INT(cd, 0, fi);
+ else
+ gen_GETSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
+ break;
case TYPE_FLT:
- if (fi == NULL || !fi->class->initialized) {
- gen_PATCHER_GETSTATIC_INT(&mcodeptr, 0, uf);
- } else {
- gen_GETSTATIC_INT(&mcodeptr, (u1 *)&(fi->value.i), uf);
- }
+ if (fi == NULL)
+ gen_PATCHER_GETSTATIC_FLOAT(cd, 0, uf);
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ gen_PATCHER_GETSTATIC_CLINIT_FLOAT(cd, 0, fi);
+ else
+ gen_GETSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
break;
case TYPE_LNG:
case TYPE_DBL:
- if (fi == NULL || !fi->class->initialized) {
- gen_PATCHER_GETSTATIC_LONG(&mcodeptr, 0, uf);
- } else {
- gen_GETSTATIC_LONG(&mcodeptr, (u1 *)&(fi->value.l), uf);
- }
+ if (fi == NULL)
+ gen_PATCHER_GETSTATIC_LONG(cd, 0, uf);
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ gen_PATCHER_GETSTATIC_CLINIT_LONG(cd, 0, fi);
+ else
+ gen_GETSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
break;
case TYPE_ADR:
- if (fi == NULL || !fi->class->initialized) {
- gen_PATCHER_GETSTATIC_CELL(&mcodeptr, 0, uf);
- } else {
- gen_GETSTATIC_CELL(&mcodeptr, (u1 *)&(fi->value.a), uf);
- }
+ if (fi == NULL)
+ gen_PATCHER_GETSTATIC_CELL(cd, 0, uf);
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ gen_PATCHER_GETSTATIC_CLINIT_CELL(cd, 0, fi);
+ else
+ gen_GETSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
break;
}
- }
break;
case ICMD_PUTSTATIC: /* ..., value ==> ... */
/* op1 = type, val.a = field address */
- {
- fieldinfo *fi = iptr->val.a;
- unresolved_field *uf = iptr->target;
-
- switch (iptr->op1) {
- case TYPE_INT:
- case TYPE_FLT:
- if (fi == NULL || !fi->class->initialized) {
- gen_PATCHER_PUTSTATIC_INT(&mcodeptr, 0, uf);
- } else {
- gen_PUTSTATIC_INT(&mcodeptr, (u1 *)&(fi->value.i), uf);
- }
- break;
- case TYPE_LNG:
- case TYPE_DBL:
- if (fi == NULL || !fi->class->initialized) {
- gen_PATCHER_PUTSTATIC_LONG(&mcodeptr, 0, uf);
- } else {
- gen_PUTSTATIC_LONG(&mcodeptr, (u1 *)&(fi->value.l), uf);
- }
- break;
- case TYPE_ADR:
- if (fi == NULL || !fi->class->initialized) {
- gen_PATCHER_PUTSTATIC_CELL(&mcodeptr, 0, uf);
- } else {
- gen_PUTSTATIC_CELL(&mcodeptr, (u1 *)&(fi->value.a), uf);
- }
- break;
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ fi = NULL;
+ uf = iptr->sx.s23.s3.uf;
+ fieldtype = uf->fieldref->parseddesc.fd->type;
}
+ else {
+ fi = iptr->sx.s23.s3.fmiref->p.field;
+ uf = NULL;
+ fieldtype = fi->type;
}
- break;
-
- case ICMD_PUTSTATICCONST: /* ... ==> ... */
- /* val = value (in current instruction) */
- /* op1 = type, val.a = field address (in */
- /* following NOP) */
-
- {
- fieldinfo *fi = iptr[1].val.a;
- unresolved_field *uf = iptr[1].target;
- switch (iptr->op1) {
+ switch (fieldtype) {
case TYPE_INT:
+ if (fi == NULL)
+ gen_PATCHER_PUTSTATIC_INT(cd, 0, uf);
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ gen_PATCHER_PUTSTATIC_CLINIT_INT(cd, 0, fi);
+ else
+ gen_PUTSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
+ break;
case TYPE_FLT:
- gen_ICONST(&mcodeptr, iptr->val.i);
- if (fi == NULL || !fi->class->initialized) {
- gen_PATCHER_PUTSTATIC_INT(&mcodeptr, 0, uf);
- } else {
- gen_PUTSTATIC_INT(&mcodeptr, (u1 *)&(fi->value.i), uf);
- }
+ if (fi == NULL)
+ gen_PATCHER_PUTSTATIC_FLOAT(cd, 0, uf);
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ gen_PATCHER_PUTSTATIC_CLINIT_FLOAT(cd, 0, fi);
+ else
+ gen_PUTSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
break;
case TYPE_LNG:
case TYPE_DBL:
- gen_LCONST(&mcodeptr, iptr->val.l);
- if (fi == NULL || !fi->class->initialized) {
- gen_PATCHER_PUTSTATIC_LONG(&mcodeptr, 0, uf);
- } else {
- gen_PUTSTATIC_LONG(&mcodeptr, (u1 *)&(fi->value.l), uf);
- }
+ if (fi == NULL)
+ gen_PATCHER_PUTSTATIC_LONG(cd, 0, uf);
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ gen_PATCHER_PUTSTATIC_CLINIT_LONG(cd, 0, fi);
+ else
+ gen_PUTSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
break;
case TYPE_ADR:
- gen_ACONST(&mcodeptr, iptr->val.a);
- if (fi == NULL || !fi->class->initialized) {
- gen_PATCHER_PUTSTATIC_CELL(&mcodeptr, 0, uf);
- } else {
- gen_PUTSTATIC_CELL(&mcodeptr, (u1 *)&(fi->value.a), uf);
- }
+ if (fi == NULL)
+ gen_PATCHER_PUTSTATIC_CELL(cd, 0, uf);
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ gen_PATCHER_PUTSTATIC_CLINIT_CELL(cd, 0, fi);
+ else
+ gen_PUTSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
break;
}
- }
break;
case ICMD_GETFIELD: /* ... ==> ..., value */
/* op1 = type, val.a = field address */
- {
- fieldinfo *fi = iptr->val.a;
- unresolved_field *uf = iptr->target;
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ fi = NULL;
+ uf = iptr->sx.s23.s3.uf;
+ fieldtype = uf->fieldref->parseddesc.fd->type;
+ }
+ else {
+ fi = iptr->sx.s23.s3.fmiref->p.field;
+ uf = NULL;
+ fieldtype = fi->type;
+ }
- switch (iptr->op1) {
+ switch (fieldtype) {
case TYPE_INT:
+ if (fi == NULL)
+ gen_PATCHER_GETFIELD_INT(cd, 0, uf);
+ else
+ gen_GETFIELD_INT(cd, fi->offset, fi);
+ break;
case TYPE_FLT:
- if (fi == NULL) {
- gen_PATCHER_GETFIELD_INT(&mcodeptr, 0, uf);
- } else {
- gen_GETFIELD_INT(&mcodeptr, fi->offset, uf);
- }
+ if (fi == NULL)
+ gen_PATCHER_GETFIELD_FLOAT(cd, 0, uf);
+ else
+ gen_GETFIELD_FLOAT(cd, fi->offset, fi);
break;
case TYPE_LNG:
case TYPE_DBL:
- if (fi == NULL) {
- gen_PATCHER_GETFIELD_LONG(&mcodeptr, 0, uf);
- } else {
- gen_GETFIELD_LONG(&mcodeptr, fi->offset, uf);
- }
+ if (fi == NULL)
+ gen_PATCHER_GETFIELD_LONG(cd, 0, uf);
+ else
+ gen_GETFIELD_LONG(cd, fi->offset, fi);
break;
case TYPE_ADR:
- if (fi == NULL) {
- gen_PATCHER_GETFIELD_CELL(&mcodeptr, 0, uf);
- } else {
- gen_GETFIELD_CELL(&mcodeptr, fi->offset, uf);
- }
+ if (fi == NULL)
+ gen_PATCHER_GETFIELD_CELL(cd, 0, uf);
+ else
+ gen_GETFIELD_CELL(cd, fi->offset, fi);
break;
}
- }
break;
case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
/* op1 = type, val.a = field address */
- {
- fieldinfo *fi = iptr->val.a;
- unresolved_field *uf = iptr->target;
-
- switch (iptr->op1) {
- case TYPE_INT:
- case TYPE_FLT:
- if (fi == NULL) {
- gen_PATCHER_PUTFIELD_INT(&mcodeptr, 0, uf);
- } else {
- gen_PUTFIELD_INT(&mcodeptr, fi->offset, uf);
- }
- break;
- case TYPE_LNG:
- case TYPE_DBL:
- if (fi == NULL) {
- gen_PATCHER_PUTFIELD_LONG(&mcodeptr, 0, uf);
- } else {
- gen_PUTFIELD_LONG(&mcodeptr, fi->offset, uf);
- }
- break;
- case TYPE_ADR:
- if (fi == NULL) {
- gen_PATCHER_PUTFIELD_CELL(&mcodeptr, 0, uf);
- } else {
- gen_PUTFIELD_CELL(&mcodeptr, fi->offset, uf);
- }
- break;
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ fi = NULL;
+ uf = iptr->sx.s23.s3.uf;
+ fieldtype = uf->fieldref->parseddesc.fd->type;
}
+ else {
+ fi = iptr->sx.s23.s3.fmiref->p.field;
+ uf = NULL;
+ fieldtype = fi->type;
}
- break;
- case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
- /* val = value (in current instruction) */
- /* op1 = type, val.a = field address (in */
- /* following NOP) */
-
- {
- fieldinfo *fi = iptr[1].val.a;
- unresolved_field *uf = iptr[1].target;
-
- switch (iptr[1].op1) {
+ switch (fieldtype) {
case TYPE_INT:
+ if (fi == NULL)
+ gen_PATCHER_PUTFIELD_INT(cd, 0, uf);
+ else
+ gen_PUTFIELD_INT(cd, fi->offset, fi);
+ break;
case TYPE_FLT:
- gen_ICONST(&mcodeptr, iptr->val.i);
- if (fi == NULL) {
- gen_PATCHER_PUTFIELD_INT(&mcodeptr, 0, uf);
- } else {
- gen_PUTFIELD_INT(&mcodeptr, fi->offset, uf);
- }
+ if (fi == NULL)
+ gen_PATCHER_PUTFIELD_FLOAT(cd, 0, uf);
+ else
+ gen_PUTFIELD_FLOAT(cd, fi->offset, fi);
break;
case TYPE_LNG:
case TYPE_DBL:
- gen_LCONST(&mcodeptr, iptr->val.l);
- if (fi == NULL) {
- gen_PATCHER_PUTFIELD_LONG(&mcodeptr, 0, uf);
- } else {
- gen_PUTFIELD_LONG(&mcodeptr, fi->offset, uf);
- }
+ if (fi == NULL)
+ gen_PATCHER_PUTFIELD_LONG(cd, 0, uf);
+ else
+ gen_PUTFIELD_LONG(cd, fi->offset, fi);
break;
case TYPE_ADR:
- gen_ACONST(&mcodeptr, iptr->val.a);
- if (fi == NULL) {
- gen_PATCHER_PUTFIELD_CELL(&mcodeptr, 0, uf);
- } else {
- gen_PUTFIELD_CELL(&mcodeptr, fi->offset, uf);
- }
+ if (fi == NULL)
+ gen_PATCHER_PUTFIELD_CELL(cd, 0, uf);
+ else
+ gen_PUTFIELD_CELL(cd, fi->offset, fi);
break;
}
- }
break;
case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
- gen_ATHROW(&mcodeptr);
+ gen_ATHROW(cd);
break;
case ICMD_GOTO: /* ... ==> ... */
case ICMD_JSR: /* ... ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(JSR);
+
+ gen_JSR(cd, NULL);
+ codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex));
break;
-
+
case ICMD_RET: /* ... ==> ... */
/* op1 = local variable */
- gen_RET(&mcodeptr, iptr->op1);
+ gen_RET(cd, index2offset(iptr->s1.varindex));
break;
case ICMD_IFNULL: /* ..., value ==> ... */
case ICMD_IFEQ: /* ..., value ==> ... */
/* op1 = target JavaVM pc, val.i = constant */
- if (iptr->val.i == 0) {
+ if (iptr->sx.val.i == 0) {
gen_branch(IFEQ);
} else {
- gen_ICONST(&mcodeptr, iptr->val.i);
+ gen_ICONST(cd, iptr->sx.val.i);
gen_branch(IF_ICMPEQ);
}
break;
case ICMD_IFLT: /* ..., value ==> ... */
/* op1 = target JavaVM pc, val.i = constant */
- if (iptr->val.i == 0) {
+ if (iptr->sx.val.i == 0) {
gen_branch(IFLT);
} else {
- gen_ICONST(&mcodeptr, iptr->val.i);
+ gen_ICONST(cd, iptr->sx.val.i);
gen_branch(IF_ICMPLT);
}
break;
case ICMD_IFLE: /* ..., value ==> ... */
/* op1 = target JavaVM pc, val.i = constant */
- if (iptr->val.i == 0) {
+ if (iptr->sx.val.i == 0) {
gen_branch(IFLE);
} else {
- gen_ICONST(&mcodeptr, iptr->val.i);
+ gen_ICONST(cd, iptr->sx.val.i);
gen_branch(IF_ICMPLE);
}
break;
case ICMD_IFNE: /* ..., value ==> ... */
/* op1 = target JavaVM pc, val.i = constant */
- if (iptr->val.i == 0) {
+ if (iptr->sx.val.i == 0) {
gen_branch(IFNE);
} else {
- gen_ICONST(&mcodeptr, iptr->val.i);
+ gen_ICONST(cd, iptr->sx.val.i);
gen_branch(IF_ICMPNE);
}
break;
case ICMD_IFGT: /* ..., value ==> ... */
/* op1 = target JavaVM pc, val.i = constant */
- if (iptr->val.i == 0) {
+ if (iptr->sx.val.i == 0) {
gen_branch(IFGT);
} else {
- gen_ICONST(&mcodeptr, iptr->val.i);
+ gen_ICONST(cd, iptr->sx.val.i);
gen_branch(IF_ICMPGT);
}
break;
case ICMD_IFGE: /* ..., value ==> ... */
/* op1 = target JavaVM pc, val.i = constant */
- if (iptr->val.i == 0) {
+ if (iptr->sx.val.i == 0) {
gen_branch(IFGE);
} else {
- gen_ICONST(&mcodeptr, iptr->val.i);
+ gen_ICONST(cd, iptr->sx.val.i);
gen_branch(IF_ICMPGE);
}
break;
+
case ICMD_IF_LEQ: /* ..., value ==> ... */
/* op1 = target JavaVM pc, val.l = constant */
- gen_LCONST(&mcodeptr, iptr->val.l);
+ gen_LCONST(cd, iptr->sx.val.l);
gen_branch(IF_LCMPEQ);
break;
case ICMD_IF_LLT: /* ..., value ==> ... */
/* op1 = target JavaVM pc, val.l = constant */
- gen_LCONST(&mcodeptr, iptr->val.l);
+ gen_LCONST(cd, iptr->sx.val.l);
gen_branch(IF_LCMPLT);
break;
case ICMD_IF_LLE: /* ..., value ==> ... */
/* op1 = target JavaVM pc, val.l = constant */
- gen_LCONST(&mcodeptr, iptr->val.l);
+ gen_LCONST(cd, iptr->sx.val.l);
gen_branch(IF_LCMPLE);
break;
case ICMD_IF_LNE: /* ..., value ==> ... */
/* op1 = target JavaVM pc, val.l = constant */
- gen_LCONST(&mcodeptr, iptr->val.l);
+ gen_LCONST(cd, iptr->sx.val.l);
gen_branch(IF_LCMPNE);
break;
case ICMD_IF_LGT: /* ..., value ==> ... */
/* op1 = target JavaVM pc, val.l = constant */
- gen_LCONST(&mcodeptr, iptr->val.l);
+ gen_LCONST(cd, iptr->sx.val.l);
gen_branch(IF_LCMPGT);
break;
case ICMD_IF_LGE: /* ..., value ==> ... */
/* op1 = target JavaVM pc, val.l = constant */
- gen_LCONST(&mcodeptr, iptr->val.l);
+ gen_LCONST(cd, iptr->sx.val.l);
gen_branch(IF_LCMPGE);
break;
- case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
+ case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_ICMPEQ);
+ gen_branch(IF_LCMPEQ);
break;
- case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
+ case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_LCMPEQ);
+ gen_branch(IF_LCMPNE);
break;
- case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
+ case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_ACMPEQ);
+ gen_branch(IF_LCMPLT);
break;
- case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
+ case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_ICMPNE);
+ gen_branch(IF_LCMPGT);
break;
- case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
+ case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_LCMPNE);
+ gen_branch(IF_LCMPLE);
break;
- case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
+ case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_ACMPNE);
+ gen_branch(IF_LCMPGE);
break;
- case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
+
+ case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_ICMPLT);
+ gen_branch(IF_ICMPEQ);
break;
- case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
+ case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_LCMPLT);
+ gen_branch(IF_ACMPEQ);
break;
- case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_ICMPGT);
+ gen_branch(IF_ICMPNE);
break;
- case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
+ case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_LCMPGT);
+ gen_branch(IF_ACMPNE);
break;
- case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_ICMPLE);
+ gen_branch(IF_ICMPLT);
break;
- case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_LCMPLE);
+ gen_branch(IF_ICMPGT);
break;
- case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_ICMPGE);
+ gen_branch(IF_ICMPLE);
break;
- case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
+ case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
/* op1 = target JavaVM pc */
- gen_branch(IF_LCMPGE);
+ gen_branch(IF_ICMPGE);
break;
case ICMD_IRETURN: /* ..., retvalue ==> ... */
case ICMD_FRETURN: /* ..., retvalue ==> ... */
-#if defined(USE_THREADS)
+#if defined(ENABLE_THREADS)
if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
if (m->flags & ACC_STATIC) {
- gen_ACONST(&mcodeptr, m->class);
+ gen_ACONST(cd, (java_objectheader *) m->class);
} else {
- gen_ALOAD(&mcodeptr, 0);
+ gen_ALOAD(cd, index2offset(m->maxlocals));
}
- gen_MONITOREXIT(&mcodeptr);
+ gen_MONITOREXIT(cd);
}
#endif
- if (runverbose)
- gen_TRACERETURN(&mcodeptr);
+ if (opt_verbosecall)
+ gen_TRACERETURN(cd, m);
- gen_IRETURN(&mcodeptr, cd->maxlocals);
+ gen_IRETURN(cd, index2offset(cd->stackframesize));
break;
case ICMD_LRETURN: /* ..., retvalue ==> ... */
case ICMD_DRETURN: /* ..., retvalue ==> ... */
-#if defined(USE_THREADS)
+#if defined(ENABLE_THREADS)
if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
if (m->flags & ACC_STATIC) {
- gen_ACONST(&mcodeptr, m->class);
+ gen_ACONST(cd, (java_objectheader *) m->class);
} else {
- gen_ALOAD(&mcodeptr, 0);
+ gen_ALOAD(cd, index2offset(m->maxlocals));
}
- gen_MONITOREXIT(&mcodeptr);
+ gen_MONITOREXIT(cd);
}
#endif
- if (runverbose)
- gen_TRACELRETURN(&mcodeptr);
+ if (opt_verbosecall)
+ gen_TRACELRETURN(cd, m);
- gen_LRETURN(&mcodeptr, cd->maxlocals);
+ gen_LRETURN(cd, index2offset(cd->stackframesize));
break;
case ICMD_RETURN: /* ... ==> ... */
-#if defined(USE_THREADS)
+#if defined(ENABLE_THREADS)
if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
if (m->flags & ACC_STATIC) {
- gen_ACONST(&mcodeptr, m->class);
+ gen_ACONST(cd, (java_objectheader *) m->class);
} else {
- gen_ALOAD(&mcodeptr, 0);
+ gen_ALOAD(cd, index2offset(m->maxlocals));
}
- gen_MONITOREXIT(&mcodeptr);
+ gen_MONITOREXIT(cd);
}
#endif
- if (runverbose)
- gen_TRACERETURN(&mcodeptr);
+ if (opt_verbosecall)
+ gen_TRACERETURN(cd, m);
- gen_RETURN(&mcodeptr, cd->maxlocals);
+ gen_RETURN(cd, index2offset(cd->stackframesize));
break;
case ICMD_TABLESWITCH: /* ..., index ==> ... */
{
- s4 i, l, *s4ptr;
- void **tptr;
+ s4 i, l;
+ branch_target_t *table;
- tptr = (void **) iptr->target;
+ table = iptr->dst.table;
- s4ptr = iptr->val.a;
- l = s4ptr[1]; /* low */
- i = s4ptr[2]; /* high */
+ l = iptr->sx.s23.s2.tablelow;
+ i = iptr->sx.s23.s3.tablehigh;
i = i - l + 1;
- /* arguments: low, range, datasegment address, table offset in */
- /* datasegment, default target */
- gen_TABLESWITCH(&mcodeptr, l, i, NULL, 0, NULL);
- dseg_adddata(cd, (u1 *) (mcodeptr - 2)); /* actually mcodeptr[-3] */
- codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
+ /* arguments: low, range, datasegment address, table
+ offset in datasegment, default target */
+
+ gen_TABLESWITCH(cd, l, i, NULL, 0, NULL);
+
+ /* actually -3 cells offset */
+
+ cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
+ dseg_adddata(cd);
+ cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
+
+ codegen_addreference(cd, BLOCK_OF(table[0].insindex));
/* build jump table top down and use address of lowest entry */
- tptr += i;
+ table += i;
while (--i >= 0) {
- dseg_addtarget(cd, (basicblock *) tptr[0]);
- --tptr;
+ dseg_add_target(cd, BLOCK_OF(table->insindex));
+ --table;
}
}
- /* length of dataseg after last dseg_addtarget is used by load */
- mcodeptr[-2] = (Inst) (ptrint) -(cd->dseglen);
+ /* length of dataseg after last dseg_add_target is used by load */
+ ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
break;
case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
{
- s4 i, *s4ptr;
- void **tptr;
+ s4 i;
+ lookup_target_t *lookup;
- tptr = (void **) iptr->target;
+ lookup = iptr->dst.lookup;
- s4ptr = iptr->val.a;
-
- /* s4ptr[0] is equal to tptr[0] */
- i = s4ptr[1]; /* count */
+ i = iptr->sx.s23.s2.lookupcount;
/* arguments: count, datasegment address, table offset in */
/* datasegment, default target */
- gen_LOOKUPSWITCH(&mcodeptr, i, NULL, 0, NULL);
- dseg_adddata(cd, (u1 *) (mcodeptr - 2)); /* actually mcodeptr[-3] */
- codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
+ gen_LOOKUPSWITCH(cd, i, NULL, 0, NULL);
- /* build jump table top down and use address of lowest entry */
+ /* actually -3 cells offset */
- tptr += i;
- s4ptr += i * 2;
+ cd->mcodeptr = (u1 *) cd->mcodeptr - 2 * sizeof(Inst);
+ dseg_adddata(cd);
+ cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
+
+ /* build jump table top down and use address of lowest entry */
while (--i >= 0) {
- dseg_addtarget(cd, (basicblock *) tptr[0]);
- dseg_addaddress(cd, s4ptr[0]);
- --tptr;
- s4ptr -= 2;
+ dseg_add_target(cd, BLOCK_OF(lookup->target.insindex));
+ dseg_add_unique_address(cd, lookup->value);
+ lookup++;
}
+
+ codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex));
}
- /* length of dataseg after last dseg_addtarget is used by load */
- mcodeptr[-2] = (Inst) (ptrint) -(cd->dseglen);
+ /* length of dataseg after last dseg_add_target is used by load */
+ ((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
break;
case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
/* op1 = arg count val.a = builtintable entry */
- bte = iptr->val.a;
- if (bte->fp == PATCHER_builtin_new) {
- gen_PATCHER_NEW(&mcodeptr, 0);
- } else if (bte->fp == PATCHER_builtin_newarray) {
- gen_PATCHER_NEWARRAY(&mcodeptr, 0);
- } else if (bte->fp == PATCHER_builtin_arrayinstanceof) {
- gen_PATCHER_ARRAYINSTANCEOF(&mcodeptr, 0);
- } else {
- for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
- builtin_gen *bg = &builtin_gen_table[i];
- if (bg->builtin == bte->fp) {
- (bg->gen)(&mcodeptr);
- break;
- }
+ bte = iptr->sx.s23.s3.bte;
+
+ for (i = 0; i < sizeof(builtin_gen_table)/sizeof(builtin_gen); i++) {
+ builtin_gen *bg = &builtin_gen_table[i];
+ if (bg->builtin == bte->fp) {
+ (bg->gen)(cd);
+ goto gen_builtin_end;
}
}
+
+ vm_abort(0);
+
+ gen_builtin_end:
break;
case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
/* op1 = arg count, val.a = method pointer */
- lm = iptr->val.a;
- um = iptr->target;
-
- if (lm == NULL) {
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ um = iptr->sx.s23.s3.um;
md = um->methodref->parseddesc.md;
- gen_PATCHER_INVOKESTATIC(&mcodeptr, 0, md->paramslots, um);
-
- } else {
+ gen_PATCHER_INVOKESTATIC(cd, 0, md->paramslots, um);
+ }
+ else {
+ lm = iptr->sx.s23.s3.fmiref->p.method;
md = lm->parseddesc;
- gen_INVOKESTATIC(&mcodeptr, (Inst **)lm->stubroutine, md->paramslots, um);
+ gen_INVOKESTATIC(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
}
break;
case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
- lm = iptr->val.a;
- um = iptr->target;
-
- if (lm == NULL) {
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ um = iptr->sx.s23.s3.um;
md = um->methodref->parseddesc.md;
- gen_PATCHER_INVOKESPECIAL(&mcodeptr, 0, md->paramslots, um);
-
- } else {
+ gen_PATCHER_INVOKESPECIAL(cd, 0, md->paramslots, um);
+ }
+ else {
+ lm = iptr->sx.s23.s3.fmiref->p.method;
md = lm->parseddesc;
- gen_INVOKESPECIAL(&mcodeptr, (Inst **)lm->stubroutine, md->paramslots, um);
+ gen_INVOKESPECIAL(cd, (Inst **) lm->stubroutine, md->paramslots, lm);
}
break;
case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
- lm = iptr->val.a;
- um = iptr->target;
-
- if (lm == NULL) {
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ um = iptr->sx.s23.s3.um;
md = um->methodref->parseddesc.md;
- gen_PATCHER_INVOKEVIRTUAL(&mcodeptr, 0, md->paramslots, um);
-
- } else {
+ gen_PATCHER_INVOKEVIRTUAL(cd, 0, md->paramslots, um);
+ }
+ else {
+ lm = iptr->sx.s23.s3.fmiref->p.method;
md = lm->parseddesc;
s1 = OFFSET(vftbl_t, table[0]) +
sizeof(methodptr) * lm->vftblindex;
- gen_INVOKEVIRTUAL(&mcodeptr, s1, md->paramslots, um);
+ gen_INVOKEVIRTUAL(cd, s1, md->paramslots, lm);
}
break;
case ICMD_INVOKEINTERFACE:/* op1 = arg count, val.a = method pointer */
- lm = iptr->val.a;
- um = iptr->target;
-
- if (lm == NULL) {
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ um = iptr->sx.s23.s3.um;
md = um->methodref->parseddesc.md;
- gen_PATCHER_INVOKEINTERFACE(&mcodeptr, 0, 0, md->paramslots, um);
-
- } else {
+ gen_PATCHER_INVOKEINTERFACE(cd, 0, 0, md->paramslots, um);
+ }
+ else {
+ lm = iptr->sx.s23.s3.fmiref->p.method;
md = lm->parseddesc;
s1 = OFFSET(vftbl_t, interfacetable[0]) -
s2 = sizeof(methodptr) * (lm - lm->class->methods);
- gen_INVOKEINTERFACE(&mcodeptr, s1, s2, md->paramslots, um);
+ gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
}
break;
/* op1: 0 == array, 1 == class */
/* val.a: (classinfo *) superclass */
- if (iptr->val.a == NULL) {
- gen_PATCHER_CHECKCAST(&mcodeptr, 0, iptr->target);
-
- } else {
- gen_CHECKCAST(&mcodeptr, iptr->val.a, iptr->target);
+ if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
+ if (INSTRUCTION_IS_UNRESOLVED(iptr))
+ gen_PATCHER_CHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
+ else
+ gen_CHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
}
-
- break;
-
- case ICMD_ARRAYCHECKCAST: /* ..., objectref ==> ..., objectref */
- /* op1: 1... resolved, 0... not resolved */
-
- if (iptr->op1 == 0) {
- gen_PATCHER_ARRAYCHECKCAST(&mcodeptr, 0, iptr->target);
- } else {
- gen_ARRAYCHECKCAST(&mcodeptr, iptr->target, 0);
+ else {
+ if (INSTRUCTION_IS_UNRESOLVED(iptr))
+ gen_PATCHER_ARRAYCHECKCAST(cd, NULL, iptr->sx.s23.s3.c.ref);
+ else
+ gen_ARRAYCHECKCAST(cd, iptr->sx.s23.s3.c.cls, NULL);
}
break;
/* op1: 0 == array, 1 == class */
/* val.a: (classinfo *) superclass */
- if (iptr->val.a == NULL) {
- gen_PATCHER_INSTANCEOF(&mcodeptr, 0, iptr->target);
- } else {
- gen_INSTANCEOF(&mcodeptr, iptr->val.a, iptr->target);
- }
-
- break;
-
-
- case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
-
- /* XXX remove me! */
- break;
-
- case ICMD_CHECKEXCEPTION: /* ..., objectref ==> ..., objectref */
-
- gen_CHECKEXCEPTION(&mcodeptr);
+ if (INSTRUCTION_IS_UNRESOLVED(iptr))
+ gen_PATCHER_INSTANCEOF(cd, NULL, iptr->sx.s23.s3.c.ref);
+ else
+ gen_INSTANCEOF(cd, iptr->sx.s23.s3.c.cls, iptr->sx.s23.s3.c.ref);
break;
case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
- /* op1 = dimension, val.a = array descriptor */
+ /* op1 = dimension, val.a = class */
- if (iptr->target) {
- gen_PATCHER_MULTIANEWARRAY(&mcodeptr, 0, iptr->op1, iptr->val.a);
- } else {
- gen_MULTIANEWARRAY(&mcodeptr, iptr->val.a, iptr->op1, 0);
- }
+ if (INSTRUCTION_IS_UNRESOLVED(iptr))
+ gen_PATCHER_MULTIANEWARRAY(cd, NULL, iptr->s1.argcount, iptr->sx.s23.s3.c.ref);
+ else
+ gen_MULTIANEWARRAY(cd, iptr->sx.s23.s3.c.cls, iptr->s1.argcount, NULL);
break;
default:
- throw_cacao_exception_exit(string_java_lang_InternalError,
- "Unknown ICMD %d", iptr->opc);
+ exceptions_throw_internalerror("Unknown ICMD %d during code generation",
+ iptr->opc);
+ return false;
} /* switch */
} /* for instruction */
-
- } /* if (bptr -> flags >= BBREACHED) */
+
+ gen_BBEND;
+
+ } /* if (bptr->flags != BBDELETED) */
} /* for basic block */
- codegen_createlinenumbertable(cd);
+ dseg_createlinenumbertable(cd);
- codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
+ codegen_finish(jd);
+#ifdef VM_PROFILING
+ vm_block_insert(jd->code->mcode + jd->code->mcodelength);
+#endif
/* branch resolving (walk through all basic blocks) */
- for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
+ for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
branchref *brefs;
for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
- gen_resolveanybranch(((u1*) m->entrypoint) + brefs->branchpos,
- ((u1 *)m->entrypoint) + bptr->mpc);
+ gen_resolveanybranch(((u1*) jd->code->entrypoint) + brefs->branchpos,
+ ((u1 *)jd->code->entrypoint) + bptr->mpc);
}
}
+
+ /* everything's ok */
+
+ return true;
}
-/* a stub consists of
+/* createcompilerstub **********************************************************
-+---------+
-|codeptr |
-+---------+
-|maxlocals|
-+---------+
-|TRANSLATE|
-+---------+
-|methodinf|
-+---------+
+ Creates a stub routine which calls the compiler.
-codeptr points either to TRANSLATE or to the translated threaded code
+ A stub consists of:
-all methods are called indirectly through methodptr
-*/
+ +-------------+
+ | codeinfo * |
+ +-------------+ <-- stub
+ | codeptr |
+ +-------------+
+ | framesize | (in ptrint units, does not include return address)
+ +-------------+
+ | TRANSLATE |
+ +-------------+
+ | methodinfo |
+ +-------------+
-#define STUBSIZE 4
+ codeptr points either to TRANSLATE or to the translated threaded code
-functionptr createcompilerstub (methodinfo *m)
+ all methods are called indirectly through methodptr
+
+*******************************************************************************/
+
+#define COMPILERSTUB_DATASIZE 2
+#define COMPILERSTUB_CODESIZE 4
+
+#define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
+
+
+u1 *intrp_createcompilerstub(methodinfo *m)
{
- Inst * t = CNEW(Inst, STUBSIZE);
- Inst * codeptr=t;
- genarg_ainst(&t, t+2);
+ Inst *s;
+ Inst *d;
+ codegendata *cd;
+ s4 dumpsize;
+ s4 stackframesize;
+
+ s = CNEW(Inst, COMPILERSTUB_SIZE);
+
+ /* set data pointer and code pointer */
+
+ d = s;
+ s = s + COMPILERSTUB_DATASIZE;
+
+ /* The codeinfo pointer is actually a pointer to the
+ methodinfo. This fakes a codeinfo structure. */
+
+ d[0] = (Inst *) m;
+ d[1] = (Inst *) &d[0]; /* fake code->m */
+
+ /* mark start of dump memory area */
+
+ dumpsize = dump_size();
+
+ cd = DNEW(codegendata);
+ cd->mcodeptr = (u1 *) s;
+ cd->lastinstwithoutdispatch = ~0;
+ cd->superstarts = NULL;
+
+ genarg_ainst(cd, s + 2);
if (m->flags & ACC_NATIVE) {
- genarg_i(&t, m->parseddesc->paramslots);
- } else {
- genarg_i(&t, m->maxlocals);
+ stackframesize = m->parseddesc->paramslots;
+ }
+ else {
+ stackframesize = m->maxlocals;
+
+#if defined(ENABLE_THREADS)
+ if (checksync && (m->flags & ACC_SYNCHRONIZED))
+ stackframesize += 1;
+#endif
}
- gen_TRANSLATE(&t, m);
- return (functionptr)codeptr;
+ genarg_i(cd, stackframesize);
+
+ gen_BBSTART;
+ gen_TRANSLATE(cd, m);
+ gen_BBEND;
+
+#ifdef VM_PROFILING
+ vm_block_insert(cd->mcodeptr);
+#endif
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_cstub_len += COMPILERSTUB_SIZE;
+#endif
+
+ /* release dump area */
+
+ dump_release(dumpsize);
+
+ return (u1 *) s;
+}
+
+
+#if defined(WITH_FFI)
+static ffi_type *cacaotype2ffitype(s4 cacaotype)
+{
+ switch (cacaotype) {
+ case TYPE_INT:
+#if SIZEOF_VOID_P == 8
+ return &ffi_type_sint64;
+#else
+ return &ffi_type_sint32;
+#endif
+ case TYPE_LNG:
+ return &ffi_type_sint64;
+ case TYPE_FLT:
+ return &ffi_type_float;
+ case TYPE_DBL:
+ return &ffi_type_double;
+ case TYPE_ADR:
+ return &ffi_type_pointer;
+ case TYPE_VOID:
+ return &ffi_type_void;
+ default:
+ assert(false);
+ }
}
+#endif
/* native stub:
+---------+
|function |
+---------+
-
-where maxlocals==paramslots
+|cif |
++---------+
*/
-#define NATIVE_STUBSIZE 5
+#if defined(WITH_FFI)
+static ffi_cif *createnativecif(methodinfo *m, methoddesc *nmd)
+{
+ methoddesc *md = m->parseddesc;
+ ffi_cif *pcif = NEW(ffi_cif);
+ ffi_type **types = MNEW(ffi_type *, nmd->paramcount);
+ ffi_type **ptypes = types;
+ s4 i;
+
+ /* pass env pointer */
+
+ *ptypes++ = &ffi_type_pointer;
+
+ /* for static methods, pass class pointer */
+
+ if (m->flags & ACC_STATIC)
+ *ptypes++ = &ffi_type_pointer;
+
+ /* pass parameter to native function */
+
+ for (i = 0; i < md->paramcount; i++)
+ *ptypes++ = cacaotype2ffitype(md->paramtypes[i].type);
-functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
- registerdata *rd, methoddesc *md)
+ assert(ptypes - types == nmd->paramcount);
+
+ if (ffi_prep_cif(pcif, FFI_DEFAULT_ABI, nmd->paramcount, cacaotype2ffitype(md->returntype.type), types) != FFI_OK)
+ assert(0);
+
+ return pcif;
+}
+#endif
+
+
+u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
{
- Inst *mcodeptr;
+ methodinfo *m;
+ codeinfo *code;
+ codegendata *cd;
+ registerdata *rd;
+#if defined(WITH_FFI)
+ ffi_cif *cif;
+#else
+ u1 *cif;
+#endif
+ s4 stackframesize;
- mcodeptr = (s4 *) cd->mcodebase;
- cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
+ /* get required compiler data */
+
+ m = jd->m;
+ code = jd->code;
+ cd = jd->cd;
+ rd = jd->rd;
+
+ /* determine stackframe size (in units of ptrint) */
+
+ stackframesize = nmd->paramslots;
/* create method header */
- (void) dseg_addaddress(cd, m); /* MethodPointer */
- (void) dseg_adds4(cd, 0); /* IsSync */
+ (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
+ (void) dseg_add_unique_s4(cd, stackframesize * SIZEOF_VOID_P); /*FrameSize*/
+ (void) dseg_add_unique_s4(cd, 0); /* IsSync */
+ (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
+ (void) dseg_add_unique_s4(cd, 0); /* IntSave */
+ (void) dseg_add_unique_s4(cd, 0); /* FltSave */
dseg_addlinenumbertablesize(cd);
- (void) dseg_adds4(cd, 0); /* ExTableSize */
+ (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
+
+#if defined(WITH_FFI)
+ /* prepare ffi cif structure */
- if (runverbose)
- gen_TRACECALL(&mcodeptr);
+ cif = createnativecif(m, nmd);
+#else
+ cif = NULL;
+#endif
+
+ gen_BBSTART;
+
+ if (opt_verbosecall)
+ gen_TRACECALL(cd, m);
if (f == NULL) {
- gen_PATCHER_NATIVECALL(&mcodeptr, m, f);
+ gen_PATCHER_NATIVECALL(cd, m, f, (u1 *)cif);
} else {
- if (runverbose)
- gen_TRACENATIVECALL(&mcodeptr, m, f);
+ if (opt_verbosecall)
+ gen_TRACENATIVECALL(cd, m, f, (u1 *)cif);
+ else
+ gen_NATIVECALL(cd, m, f, (u1 *)cif);
+ }
+
+ gen_BBEND;
+
+ codegen_finish(jd);
+
+#ifdef VM_PROFILING
+ vm_block_insert(jd->code->mcode + jd->code->mcodelength);
+#endif
+
+ return jd->code->entrypoint;
+}
+
+
+/* call jni function */
+Cell *nativecall(functionptr f, methodinfo *m, Cell *sp, Inst *ra, Cell *fp, u1 *addrcif)
+{
+#if defined(WITH_FFCALL)
+ av_alist alist;
+ methoddesc *md;
+ Cell *p;
+ Cell *endsp;
+ s4 i;
+
+ struct {
+ stackframeinfo sfi;
+ localref_table lrt;
+ } s;
+
+ md = m->parseddesc;
+
+ switch (md->returntype.type) {
+ case TYPE_INT:
+ endsp = sp - 1 + md->paramslots;
+ av_start_long(alist, f, endsp);
+ break;
+ case TYPE_LNG:
+ endsp = sp - 2 + md->paramslots;
+ av_start_longlong(alist, f, endsp);
+ break;
+ case TYPE_FLT:
+ endsp = sp - 1 + md->paramslots;
+ av_start_float(alist, f, endsp);
+ break;
+ case TYPE_DBL:
+ endsp = sp - 2 + md->paramslots;
+ av_start_double(alist, f, endsp);
+ break;
+ case TYPE_ADR:
+ endsp = sp - 1 + md->paramslots;
+ av_start_ptr(alist, f, void *, endsp);
+ break;
+ case TYPE_VOID:
+ endsp = sp + md->paramslots;
+ av_start_void(alist, f);
+ break;
+ default:
+ assert(false);
+ }
+
+ av_ptr(alist, _Jv_JNIEnv *, _Jv_env);
+
+ if (m->flags & ACC_STATIC)
+ av_ptr(alist, classinfo *, m->class);
+
+ for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
+ switch (md->paramtypes[i].type) {
+ case TYPE_INT:
+ p -= 1;
+ av_long(alist, *p);
+ break;
+ case TYPE_LNG:
+ p -= 2;
+ av_longlong(alist, *(s8 *)p);
+ break;
+ case TYPE_FLT:
+ p -= 1;
+ av_float(alist, *((float *) p));
+ break;
+ case TYPE_DBL:
+ p -= 2;
+ av_double(alist, *(double *) p);
+ break;
+ case TYPE_ADR:
+ p -= 1;
+ av_ptr(alist, void *, *(void **) p);
+ break;
+ default:
+ assert(false);
+ }
+ }
+
+ global_sp = sp;
+
+ /* create stackframe info structure */
+
+ codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
+ (u1 *) fp, (u1 *) ra);
+
+ av_call(alist);
+
+ *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
+
+ CLEAR_global_sp;
+
+ return endsp;
+#elif defined(WITH_FFI)
+ methoddesc *md = m->parseddesc;
+ ffi_cif *pcif;
+ void *values[md->paramcount + 2];
+ void **pvalues = values;
+ Cell *p;
+ Cell *endsp;
+ s4 i;
+ _Jv_JNIEnv *penv;
+
+ struct {
+ stackframeinfo sfi;
+ localref_table lrt;
+ } s;
+
+ pcif = (ffi_cif *) addrcif;
+
+ /* pass env pointer */
+
+ penv = (_Jv_JNIEnv *) _Jv_env;
+ *pvalues++ = &penv;
+
+ /* for static methods, pass class pointer */
+
+ if (m->flags & ACC_STATIC)
+ *pvalues++ = &m->class;
+
+ /* pass parameter to native function */
+
+ for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
+ if (IS_2_WORD_TYPE(md->paramtypes[i].type))
+ p -= 2;
else
- gen_NATIVECALL(&mcodeptr, m, f);
+ p--;
+
+ *pvalues++ = p;
}
- codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
+ /* calculate position of return value */
+
+ if (md->returntype.type == TYPE_VOID)
+ endsp = sp + md->paramslots;
+ else
+ endsp = sp - (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1) + md->paramslots;
+
+ global_sp = sp;
+
+ /* create stackframe info structure */
+
+ codegen_start_native_call(((u1 *) &s) + sizeof(s), m->code->entrypoint,
+ (u1 *) fp, (u1 *) ra);
+
+ ffi_call(pcif, FFI_FN(f), endsp, values);
+
+ *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
+
+ CLEAR_global_sp;
+
+ return endsp;
+#endif
+}
+
+
+u1 *createcalljavafunction(methodinfo *m)
+{
+ methodinfo *tmpm;
+ u1 *entrypoint;
+ jitdata *jd;
+ codegendata *cd;
+ registerdata *rd;
+ s4 dumpsize;
+ methoddesc *md;
+
+ /* mark dump memory */
+
+ dumpsize = dump_size();
+
+ /* allocate memory */
+
+ jd = DNEW(jitdata);
+
+ tmpm = DNEW(methodinfo);
+ cd = DNEW(codegendata);
+ rd = DNEW(registerdata);
+
+ jd->m = tmpm;
+ jd->flags = 0;
+ jd->cd = cd;
+ jd->rd = rd;
+
+ /* Allocate codeinfo memory from the heap as we need to keep them. */
+
+ jd->code = code_codeinfo_new(tmpm); /* XXX check allocation */
+
+ /* setup code generation stuff */
+
+ MSET(tmpm, 0, u1, sizeof(methodinfo));
+
+ codegen_setup(jd);
+
+ md = m->parseddesc;
+
+ /* create method header */
+
+ (void) dseg_add_unique_address(cd, NULL); /* CodeinfoPointer */
+ (void) dseg_add_unique_s4(cd, md->paramslots * SIZEOF_VOID_P);/* FrameSize*/
+ (void) dseg_add_unique_s4(cd, 0); /* IsSync */
+ (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
+ (void) dseg_add_unique_s4(cd, 0); /* IntSave */
+ (void) dseg_add_unique_s4(cd, 0); /* FltSave */
+ dseg_addlinenumbertablesize(cd);
+ (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
+
+
+ /* generate code */
+
+ gen_BBSTART;
+ gen_INVOKESTATIC(cd, (Inst **)m->stubroutine, md->paramslots, 0);
+ gen_END(cd);
+
+ gen_BBEND;
+
+ codegen_finish(jd);
+
+#ifdef VM_PROFILING
+ vm_block_insert(jd->code->mcode + jd->code->mcodelength);
+#endif
+ entrypoint = jd->code->entrypoint;
+
+ /* release memory */
+
+ dump_release(dumpsize);
- return m->entrypoint;
+ return entrypoint;
}
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/