/* src/vm/jit/intrp/codegen.c - code generator for Interpreter
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ 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
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 5682 2006-10-04 23:05:15Z edwin $
-
*/
#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/global.h"
-#include "vm/options.h"
#include "vm/stringlocal.h"
#include "vm/vm.h"
+
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/dseg.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"
#define gen_branch(_inst) { \
/* 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 *);
s4 i, len, s1, s2, d;
basicblock *bptr;
instruction *iptr;
- exceptiontable *ex;
+ exception_entry *ex;
u2 currentline;
methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
unresolved_method *um;
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, jd->code); /* CodeinfoPointer */
- (void) dseg_adds4(cd, m->maxlocals * SIZEOF_VOID_P); /* FrameSize */
+ (void) dseg_add_unique_address(cd, jd->code);
+ (void) dseg_add_unique_s4(cd, cd->stackframesize * SIZEOF_VOID_P);
#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_adds4(cd, 0); /* IsLeaf */
- (void) dseg_adds4(cd, 0); /* IntSave */
- (void) dseg_adds4(cd, 0); /* FltSave */
+ (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.any);
+ 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
#if defined(ENABLE_THREADS)
if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
- if (m->flags & ACC_STATIC)
+ if (m->flags & ACC_STATIC) {
gen_ACONST(cd, (java_objectheader *) m->class);
- else
+ }
+ else {
gen_ALOAD(cd, 0);
+ gen_DUP(cd);
+ gen_ASTORE(cd, index2offset(m->maxlocals));
+ }
gen_MONITORENTER(cd);
}
/* optimize ICONST (2^x) .. IREM --> IREMPOW2 (const) */
- if (len >= 1 && iptr[1].opc == ICMD_IREM) {
+ 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:
/* optimize ICONST (2^x) .. IDIV --> IDIVPOW2 (const) */
- if (len >= 1 && iptr[1].opc == ICMD_IDIV) {
+ 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)
/* optimize ICONST .. IF_ICMPxx --> IFxx (const) */
- if (len >= 1) {
+ 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;
/* optimize LCONST (2^x) .. LREM --> LREMPOW2 (const) */
- if (len >= 1 && iptr[1].opc == ICMD_LREM) {
+ 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:
/* optimize LCONST (2^x) .. LDIV --> LDIVPOW2 (const) */
- if (len >= 1 && iptr[1].opc == ICMD_LDIV) {
+ 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)
/* optimize LCONST .. LCMP .. IFxx (0) --> IF_Lxx */
- if (len >= 2 && iptr[1].opc == ICMD_LCMP && iptr[2].sx.val.i == 0) {
+ 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;
/* optimize LCMP .. IFxx (0) --> IF_LCMPxx */
- if (len >= 1 && iptr[1].sx.val.i == 0) {
+ 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;
}
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;
}
}
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;
}
if (m->flags & ACC_STATIC) {
gen_ACONST(cd, (java_objectheader *) m->class);
} 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 ==> ... */
if (m->flags & ACC_STATIC) {
gen_ACONST(cd, (java_objectheader *) m->class);
} 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 (m->flags & ACC_STATIC) {
gen_ACONST(cd, (java_objectheader *) m->class);
} 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;
table += i;
while (--i >= 0) {
- dseg_addtarget(cd, BLOCK_OF(table->insindex));
+ 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, BLOCK_OF(lookup->target.insindex));
- 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, 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;
break;
default:
- *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
+ exceptions_throw_internalerror("Unknown ICMD %d during code generation",
+ iptr->opc);
return false;
} /* switch */
+-------------+ <-- 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;
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 */
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 && (m->flags & ACC_SYNCHRONIZED))
+ stackframesize += 1;
+#endif
}
+ genarg_i(cd, stackframesize);
+
gen_BBSTART;
gen_TRANSLATE(cd, m);
gen_BBEND;
#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 */
/* 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 */