/* src/vm/jit/intrp/codegen.c - code generator for Interpreter
- Copyright (C) 1996-2005, 2006 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, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
- Anton Ertl
-
- Changes: Edwin Steiner
-
- $Id: codegen.c 5661 2006-10-04 13:35:25Z twisti $
-
*/
#include "vm/jit/intrp/codegen.h"
#include "vm/jit/intrp/intrp.h"
+#include "mm/memory.h"
+
#include "native/native.h"
+
#include "vm/builtin.h"
#include "vm/class.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/options.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
+
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/dseg.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/parse.h"
#include "vm/jit/patcher.h"
+#include "vm/jit/stack.h"
+#include "vm/jit/stacktrace.hpp"
#define gen_branch(_inst) { \
gen_##_inst(cd, 0); \
- codegen_addreference(cd, iptr->dst.block); \
+ codegen_addreference(cd, BLOCK_OF(iptr->dst.insindex)); \
}
#define index2offset(_i) (-(_i) * SIZEOF_VOID_P)
/* 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) (codegendata *);
*******************************************************************************/
+#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;
- stackptr src;
basicblock *bptr;
instruction *iptr;
- exceptiontable *ex;
u2 currentline;
methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
unresolved_method *um;
lm = NULL;
bte = NULL;
- /* create method header */
+ /* determine stackframe size (in units of ptrint slots) */
- (void) dseg_addaddress(cd, jd->code); /* CodeinfoPointer */
- (void) dseg_adds4(cd, m->maxlocals * SIZEOF_VOID_P); /* FrameSize */
+ cd->stackframesize = m->maxlocals;
#if defined(ENABLE_THREADS)
- if (checksync && (m->flags & ACC_SYNCHRONIZED))
- (void) dseg_adds4(cd, 1); /* IsSync */
- else
+ if (checksync && code_is_synchronized(code))
+ cd->stackframesize += 1;
#endif
- (void) dseg_adds4(cd, 0); /* IsSync */
-
- (void) dseg_adds4(cd, 0); /* IsLeaf */
- (void) dseg_adds4(cd, 0); /* IntSave */
- (void) dseg_adds4(cd, 0); /* FltSave */
- dseg_addlinenumbertablesize(cd);
+ /* create method header */
- (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
+ (void) dseg_add_unique_address(cd, jd->code);
+ (void) dseg_add_unique_s4(cd, cd->stackframesize * SIZEOF_VOID_P);
- /* create exception table */
+ code->synchronizedoffset = rd->memuse * 8;
- 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.any);
- }
+ /* REMOVEME: We still need it for exception handling in assembler. */
+
+ if (code_is_leafmethod(code))
+ (void) dseg_add_unique_s4(cd, 1);
+ else
+ (void) dseg_add_unique_s4(cd, 0);
+
+ (void) dseg_add_unique_s4(cd, 0);
+ (void) dseg_add_unique_s4(cd, 0);
+
+ dseg_addlinenumbertablesize(cd);
#if 0
/* initialize mcode variables */
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
+ if (checksync && code_is_synchronized(code)) {
+ if (m->flags & ACC_STATIC) {
+ gen_ACONST(cd, (java_objectheader *) m->clazz);
+ }
+ else {
gen_ALOAD(cd, 0);
+ gen_DUP(cd);
+ gen_ASTORE(cd, index2offset(m->maxlocals));
+ }
gen_MONITORENTER(cd);
}
/* walk through all basic blocks */
- for (bptr = jd->new_basicblocks; bptr != NULL; bptr = bptr->next) {
+ for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
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;
gen_BBSTART;
MCODECHECK(64); /* an instruction usually needs < 64 words */
+switch_again:
switch (iptr->opc) {
case ICMD_INLINE_START:
case ICMD_ICONST: /* ... ==> ..., constant */
/* op1 = 0, val.i = constant */
+ /* 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 */
+ /* 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_ILOAD: /* ... ==> ..., content of local variable */
/* op1 = local variable */
- gen_ILOAD(cd, index2offset(iptr->s1.localindex));
+ gen_ILOAD(cd, index2offset(iptr->s1.varindex));
break;
case ICMD_LLOAD: /* ... ==> ..., content of local variable */
/* op1 = local variable */
- gen_LLOAD(cd, index2offset(iptr->s1.localindex));
+ gen_LLOAD(cd, index2offset(iptr->s1.varindex));
break;
case ICMD_ALOAD: /* ... ==> ..., content of local variable */
/* op1 = local variable */
- gen_ALOAD(cd, index2offset(iptr->s1.localindex));
+ gen_ALOAD(cd, index2offset(iptr->s1.varindex));
break;
case ICMD_FLOAD: /* ... ==> ..., content of local variable */
/* op1 = local variable */
- gen_ILOAD(cd, index2offset(iptr->s1.localindex));
+ gen_ILOAD(cd, index2offset(iptr->s1.varindex));
break;
case ICMD_DLOAD: /* ... ==> ..., content of local variable */
/* op1 = local variable */
- gen_LLOAD(cd, index2offset(iptr->s1.localindex));
+ gen_LLOAD(cd, index2offset(iptr->s1.varindex));
break;
case ICMD_ISTORE: /* ..., value ==> ... */
/* op1 = local variable */
- gen_ISTORE(cd, index2offset(iptr->dst.localindex));
+ gen_ISTORE(cd, index2offset(iptr->dst.varindex));
break;
case ICMD_LSTORE: /* ..., value ==> ... */
/* op1 = local variable */
- gen_LSTORE(cd, index2offset(iptr->dst.localindex));
+ gen_LSTORE(cd, index2offset(iptr->dst.varindex));
break;
case ICMD_ASTORE: /* ..., value ==> ... */
/* op1 = local variable */
- gen_ASTORE(cd, index2offset(iptr->dst.localindex));
+ gen_ASTORE(cd, index2offset(iptr->dst.varindex));
break;
case ICMD_FSTORE: /* ..., value ==> ... */
/* op1 = local variable */
- gen_ISTORE(cd, index2offset(iptr->dst.localindex));
+ gen_ISTORE(cd, index2offset(iptr->dst.varindex));
break;
case ICMD_DSTORE: /* ..., value ==> ... */
/* op1 = local variable */
- gen_LSTORE(cd, index2offset(iptr->dst.localindex));
+ 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 ==> ... */
gen_POP(cd);
gen_IADD(cd);
break;
- case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
- /* val.i = constant */
-
- gen_ICONST(cd, iptr->sx.val.i);
- gen_IADD(cd);
- break;
-
case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
gen_LADD(cd);
break;
- case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
- /* val.l = constant */
-
- gen_LCONST(cd, iptr->sx.val.l);
- gen_LADD(cd);
- break;
-
case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
gen_ISUB(cd);
break;
- case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
- /* val.i = constant */
-
- gen_ICONST(cd, iptr->sx.val.i);
- gen_ISUB(cd);
- break;
-
case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
gen_LSUB(cd);
break;
- case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
- /* val.l = constant */
-
- gen_LCONST(cd, iptr->sx.val.l);
- gen_LSUB(cd);
- break;
-
case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
gen_IMUL(cd);
break;
- case ICMD_IMULCONST: /* ..., val1, val2 ==> ..., val1 * val2 */
-
- gen_ICONST(cd, iptr->sx.val.i);
- gen_IMUL(cd);
- break;
-
case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
gen_LMUL(cd);
break;
- case ICMD_LMULCONST: /* ..., val1, val2 ==> ..., val1 * val2 */
-
- gen_LCONST(cd, iptr->sx.val.l);
- gen_LMUL(cd);
- break;
-
case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
gen_IDIV(cd);
gen_ISHL(cd);
break;
- case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
- /* val.i = constant */
-
- gen_ICONST(cd, iptr->sx.val.i);
- gen_ISHL(cd);
- break;
-
case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
gen_ISHR(cd);
break;
- case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
- /* val.i = constant */
-
- gen_ICONST(cd, iptr->sx.val.i);
- gen_ISHR(cd);
- break;
-
case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
gen_IUSHR(cd);
break;
- case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
- /* val.i = constant */
-
- gen_ICONST(cd, iptr->sx.val.i);
- gen_IUSHR(cd);
- break;
-
case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
gen_LSHL(cd);
break;
- case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
- /* val.i = constant */
-
- gen_ICONST(cd, iptr->sx.val.i);
- gen_LSHL(cd);
- break;
-
case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
gen_LSHR(cd);
break;
- case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
- /* val.i = constant */
-
- gen_ICONST(cd, iptr->sx.val.i);
- gen_LSHR(cd);
- break;
-
case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
gen_LUSHR(cd);
break;
- case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
- /* val.i = constant */
-
- gen_ICONST(cd, iptr->sx.val.i);
- gen_LUSHR(cd);
- break;
-
case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
gen_IAND(cd);
break;
- case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
- /* val.i = constant */
-
- gen_ICONST(cd, iptr->sx.val.i);
- gen_IAND(cd);
- break;
-
case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
gen_LAND(cd);
break;
- case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
- /* val.l = constant */
-
- gen_LCONST(cd, iptr->sx.val.l);
- gen_LAND(cd);
- break;
-
case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
gen_IOR(cd);
break;
- case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
- /* val.i = constant */
-
- gen_ICONST(cd, iptr->sx.val.i);
- gen_IOR(cd);
- break;
-
case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
gen_LOR(cd);
break;
- case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
- /* val.l = constant */
-
- gen_LCONST(cd, iptr->sx.val.l);
- gen_LOR(cd);
- break;
-
case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
gen_IXOR(cd);
break;
- case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
- /* val.i = constant */
-
- gen_ICONST(cd, iptr->sx.val.i);
- gen_IXOR(cd);
- break;
-
case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
gen_LXOR(cd);
break;
- case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
- /* val.l = constant */
-
- gen_LCONST(cd, iptr->sx.val.l);
- gen_LXOR(cd);
- break;
-
case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
+ /* 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(cd, index2offset(iptr->s1.localindex), iptr->sx.val.i);
+ gen_IINC(cd, index2offset(iptr->s1.varindex), iptr->sx.val.i);
break;
}
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
+ uf = NULL;
fieldtype = fi->type;
}
case TYPE_INT:
if (fi == NULL)
gen_PATCHER_GETSTATIC_INT(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_GETSTATIC_CLINIT_INT(cd, 0, fi);
else
gen_GETSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
case TYPE_FLT:
if (fi == NULL)
gen_PATCHER_GETSTATIC_FLOAT(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_GETSTATIC_CLINIT_FLOAT(cd, 0, fi);
else
gen_GETSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
case TYPE_DBL:
if (fi == NULL)
gen_PATCHER_GETSTATIC_LONG(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_GETSTATIC_CLINIT_LONG(cd, 0, fi);
else
gen_GETSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
case TYPE_ADR:
if (fi == NULL)
gen_PATCHER_GETSTATIC_CELL(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_GETSTATIC_CLINIT_CELL(cd, 0, fi);
else
gen_GETSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
}
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
+ uf = NULL;
fieldtype = fi->type;
}
case TYPE_INT:
if (fi == NULL)
gen_PATCHER_PUTSTATIC_INT(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_PUTSTATIC_CLINIT_INT(cd, 0, fi);
else
gen_PUTSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
case TYPE_FLT:
if (fi == NULL)
gen_PATCHER_PUTSTATIC_FLOAT(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_PUTSTATIC_CLINIT_FLOAT(cd, 0, fi);
else
gen_PUTSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
case TYPE_DBL:
if (fi == NULL)
gen_PATCHER_PUTSTATIC_LONG(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_PUTSTATIC_CLINIT_LONG(cd, 0, fi);
else
gen_PUTSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
case TYPE_ADR:
if (fi == NULL)
gen_PATCHER_PUTSTATIC_CELL(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_PUTSTATIC_CLINIT_CELL(cd, 0, fi);
else
gen_PUTSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
}
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
+ uf = NULL;
fieldtype = fi->type;
}
}
else {
fi = iptr->sx.s23.s3.fmiref->p.field;
+ uf = NULL;
fieldtype = fi->type;
}
break;
case ICMD_GOTO: /* ... ==> ... */
- case ICMD_RET: /* ... ==> ... */
/* op1 = target JavaVM pc */
gen_branch(GOTO);
break;
/* op1 = target JavaVM pc */
gen_JSR(cd, NULL);
- codegen_addreference(cd, iptr->sx.s23.s3.jsrtarget.block);
+ codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex));
break;
-
+
+ case ICMD_RET: /* ... ==> ... */
+ /* op1 = local variable */
+
+ gen_RET(cd, index2offset(iptr->s1.varindex));
+ break;
+
case ICMD_IFNULL: /* ..., value ==> ... */
/* op1 = target JavaVM pc */
}
break;
+
case ICMD_IF_LEQ: /* ..., value ==> ... */
/* op1 = target JavaVM pc, val.l = constant */
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_FRETURN: /* ..., retvalue ==> ... */
#if defined(ENABLE_THREADS)
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ if (checksync && code_is_synchronized(code)) {
if (m->flags & ACC_STATIC) {
- gen_ACONST(cd, (java_objectheader *) m->class);
+ gen_ACONST(cd, (java_objectheader *) m->clazz);
} else {
- gen_ALOAD(cd, 0);
+ gen_ALOAD(cd, index2offset(m->maxlocals));
}
gen_MONITOREXIT(cd);
}
if (opt_verbosecall)
gen_TRACERETURN(cd, m);
- gen_IRETURN(cd, index2offset(cd->maxlocals));
+ gen_IRETURN(cd, index2offset(cd->stackframesize));
break;
case ICMD_LRETURN: /* ..., retvalue ==> ... */
case ICMD_DRETURN: /* ..., retvalue ==> ... */
#if defined(ENABLE_THREADS)
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ if (checksync && code_is_synchronized(code)) {
if (m->flags & ACC_STATIC) {
- gen_ACONST(cd, (java_objectheader *) m->class);
+ gen_ACONST(cd, (java_objectheader *) m->clazz);
} else {
- gen_ALOAD(cd, 0);
+ gen_ALOAD(cd, index2offset(m->maxlocals));
}
gen_MONITOREXIT(cd);
}
if (opt_verbosecall)
gen_TRACELRETURN(cd, m);
- gen_LRETURN(cd, index2offset(cd->maxlocals));
+ gen_LRETURN(cd, index2offset(cd->stackframesize));
break;
case ICMD_RETURN: /* ... ==> ... */
#if defined(ENABLE_THREADS)
- if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
+ if (checksync && code_is_synchronized(code)) {
if (m->flags & ACC_STATIC) {
- gen_ACONST(cd, (java_objectheader *) m->class);
+ gen_ACONST(cd, (java_objectheader *) m->clazz);
} else {
- gen_ALOAD(cd, 0);
+ gen_ALOAD(cd, index2offset(m->maxlocals));
}
gen_MONITOREXIT(cd);
}
if (opt_verbosecall)
gen_TRACERETURN(cd, m);
- gen_RETURN(cd, index2offset(cd->maxlocals));
+ gen_RETURN(cd, index2offset(cd->stackframesize));
break;
dseg_adddata(cd);
cd->mcodeptr = (u1 *) cd->mcodeptr + 2 * sizeof(Inst);
- codegen_addreference(cd, table[0].block);
+ codegen_addreference(cd, BLOCK_OF(table[0].insindex));
/* build jump table top down and use address of lowest entry */
table += i;
while (--i >= 0) {
- dseg_addtarget(cd, table->block);
+ dseg_add_target(cd, BLOCK_OF(table->insindex));
--table;
}
}
- /* length of dataseg after last dseg_addtarget is used by load */
+ /* length of dataseg after last dseg_add_target is used by load */
((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
break;
/* build jump table top down and use address of lowest entry */
while (--i >= 0) {
- dseg_addtarget(cd, lookup->target.block);
- dseg_addaddress(cd, lookup->value);
+ dseg_add_target(cd, BLOCK_OF(lookup->target.insindex));
+ dseg_add_unique_address(cd, lookup->value);
lookup++;
}
- codegen_addreference(cd, iptr->sx.s23.s3.lookupdefault.block);
+ codegen_addreference(cd, BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex));
}
- /* length of dataseg after last dseg_addtarget is used by load */
+ /* length of dataseg after last dseg_add_target is used by load */
((ptrint *)(cd->mcodeptr))[-2] = (ptrint) -(cd->dseglen);
break;
md = lm->parseddesc;
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * lm->class->index;
+ sizeof(methodptr*) * lm->clazz->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
}
break;
default:
- *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
+ exceptions_throw_internalerror("Unknown ICMD %d during code generation",
+ iptr->opc);
return false;
} /* switch */
gen_BBEND;
- } /* if (bptr->flags >= BBREACHED) */
+ } /* if (bptr->flags != BBDELETED) */
} /* for basic block */
dseg_createlinenumbertable(cd);
/* branch resolving (walk through all basic blocks) */
- for (bptr = jd->new_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) {
+-------------+ <-- stub
| codeptr |
+-------------+
- | maxlocals |
+ | framesize | (in ptrint units, does not include return address)
+-------------+
| TRANSLATE |
+-------------+
*******************************************************************************/
-#define COMPILERSTUB_DATASIZE 1
+#define COMPILERSTUB_DATASIZE 2
#define COMPILERSTUB_CODESIZE 4
#define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
Inst *s;
Inst *d;
codegendata *cd;
- codeinfo *code;
- s4 dumpsize;
+ s4 stackframesize;
+ int32_t dumpmarker;
s = CNEW(Inst, COMPILERSTUB_SIZE);
d = s;
s = s + COMPILERSTUB_DATASIZE;
- /* Store the codeinfo pointer in the same place as in the
- methodheader for compiled methods. */
+ /* The codeinfo pointer is actually a pointer to the
+ methodinfo. This fakes a codeinfo structure. */
- code = code_codeinfo_new(m);
- d[0] = (Inst *) code;
+ d[0] = (Inst *) m;
+ d[1] = (Inst *) &d[0]; /* fake code->m */
/* mark start of dump memory area */
- dumpsize = dump_size();
+ DMARKER;
cd = DNEW(codegendata);
cd->mcodeptr = (u1 *) s;
genarg_ainst(cd, s + 2);
if (m->flags & ACC_NATIVE) {
- genarg_i(cd, m->parseddesc->paramslots);
- } else {
- genarg_i(cd, m->maxlocals);
+ stackframesize = m->parseddesc->paramslots;
+ }
+ else {
+ stackframesize = m->maxlocals;
+
+#if defined(ENABLE_THREADS)
+ if (checksync && code_is_synchronized(code))
+ stackframesize += 1;
+#endif
}
+ genarg_i(cd, stackframesize);
+
gen_BBSTART;
gen_TRANSLATE(cd, m);
gen_BBEND;
/* release dump area */
- dump_release(dumpsize);
+ DRELEASE;
return (u1 *) s;
}
#else
u1 *cif;
#endif
+ s4 stackframesize;
/* get required compiler data */
- m = jd->m;
- cd = jd->cd;
- rd = jd->rd;
+ m = jd->m;
+ code = jd->code;
+ cd = jd->cd;
+ rd = jd->rd;
- /* create method header */
+ /* determine stackframe size (in units of ptrint) */
- /* Store the codeinfo pointer in the same place as in the
- methodheader for compiled methods. */
+ stackframesize = nmd->paramslots;
- code = code_codeinfo_new(m);
+ /* create method header */
- (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
- (void) dseg_adds4(cd, nmd->paramslots * SIZEOF_VOID_P); /* FrameSize */
- (void) dseg_adds4(cd, 0); /* IsSync */
- (void) dseg_adds4(cd, 0); /* IsLeaf */
- (void) dseg_adds4(cd, 0); /* IntSave */
- (void) dseg_adds4(cd, 0); /* FltSave */
+ (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 */
assert(false);
}
- av_ptr(alist, _Jv_JNIEnv *, _Jv_env);
+ av_ptr(alist, _Jv_JNIEnv *, VM_get_jnienv());
if (m->flags & ACC_STATIC)
- av_ptr(alist, classinfo *, m->class);
+ av_ptr(alist, classinfo *, m->clazz);
for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
switch (md->paramtypes[i].type) {
av_call(alist);
- codegen_finish_native_call(((u1 *) &s) + sizeof(s));
+ *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
CLEAR_global_sp;
/* pass env pointer */
- penv = (_Jv_JNIEnv *) _Jv_env;
+ penv = (_Jv_JNIEnv *) VM_get_jnienv();
*pvalues++ = &penv;
/* for static methods, pass class pointer */
if (m->flags & ACC_STATIC)
- *pvalues++ = &m->class;
+ *pvalues++ = &m->clazz;
/* pass parameter to native function */
ffi_call(pcif, FFI_FN(f), endsp, values);
- codegen_finish_native_call(((u1 *) &s) + sizeof(s));
+ *exceptionptr = codegen_finish_native_call(((u1 *) &s) + sizeof(s));
CLEAR_global_sp;
jitdata *jd;
codegendata *cd;
registerdata *rd;
- s4 dumpsize;
methoddesc *md;
+ int32_t dumpmarker;
/* mark dump memory */
- dumpsize = dump_size();
+ DMARKER;
/* allocate memory */
/* create method header */
- (void) dseg_addaddress(cd, NULL); /* CodeinfoPointer */
- (void) dseg_adds4(cd, md->paramslots * SIZEOF_VOID_P); /* FrameSize */
- (void) dseg_adds4(cd, 0); /* IsSync */
- (void) dseg_adds4(cd, 0); /* IsLeaf */
- (void) dseg_adds4(cd, 0); /* IntSave */
- (void) dseg_adds4(cd, 0); /* FltSave */
+ (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_adds4(cd, 0); /* ExTableSize */
+ (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
/* generate code */
/* release memory */
- dump_release(dumpsize);
+ DRELEASE;
return entrypoint;
}