Christian Thalinger
Christian Ullrich
- $Id: stack.c 5024 2006-06-10 14:53:54Z edwin $
+ $Id: stack.c 5251 2006-08-18 13:01:00Z twisti $
*/
#include "vm/resolve.h"
#include "vm/statistics.h"
#include "vm/stringlocal.h"
+#include "vm/jit/cfg.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/abi.h"
#include "vm/jit/show.h"
#define DUP_SLOT(sp) \
do { \
- if ((sp)->varkind == STACKVAR) \
+ if ((sp)->varkind != TEMPVAR) \
NEWSTACK((sp)->type, TEMPVAR, stackdepth); \
else \
NEWSTACK((sp)->type, (sp)->varkind, (sp)->varnum); \
bool new_stack_analyse(jitdata *jd)
{
methodinfo *m; /* method being analyzed */
+ codeinfo *code;
codegendata *cd;
registerdata *rd;
int b_count; /* basic block counter */
/* get required compiler data - initialization */
- m = jd->m;
- cd = jd->cd;
- rd = jd->rd;
+ m = jd->m;
+ code = jd->code;
+ cd = jd->cd;
+ rd = jd->rd;
#if defined(ENABLE_LSRA)
m->maxlifetimes = 0;
bptr->type = BBTYPE_EXH;
bptr->instack = new;
bptr->indepth = 1;
- bptr->pre_count = 10000;
+ bptr->predecessorcount = CFG_UNKNOWN_PREDECESSORS;
STACKRESET;
NEWXSTACK;
}
- /* count predecessors of each block **************************************/
+ /* count predecessors of each block ***************************************/
#if CONDITIONAL_LOADCONST
/* XXX move this to a separate function */
case ICMD_IF_ACMPEQ:
case ICMD_IF_ACMPNE:
/* XXX add missing conditional branches */
- bptr[1].pre_count++;
+ bptr[1].predecessorcount++;
/* FALLTHROUGH */
/* unconditional branch */
case ICMD_GOTO:
- BLOCK_OF(iptr->dst.insindex)->pre_count++;
+ BLOCK_OF(iptr->dst.insindex)->predecessorcount++;
break;
/* switches */
case ICMD_TABLESWITCH:
table = iptr->dst.table;
- BLOCK_OF((table++)->insindex)->pre_count++;
+ BLOCK_OF((table++)->insindex)->predecessorcount++;
i = iptr->sx.s23.s3.tablehigh
- iptr->sx.s23.s2.tablelow + 1;
while (--i >= 0) {
- BLOCK_OF((table++)->insindex)->pre_count++;
+ BLOCK_OF((table++)->insindex)->predecessorcount++;
}
break;
case ICMD_LOOKUPSWITCH:
lookup = iptr->dst.lookup;
- BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex)->pre_count++;
+ BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex)->predecessorcount++;
i = iptr->sx.s23.s2.lookupcount;
while (--i >= 0) {
- BLOCK_OF((lookup++)->target.insindex)->pre_count++;
+ BLOCK_OF((lookup++)->target.insindex)->predecessorcount++;
}
break;
/* default - fall into next block */
default:
- bptr[1].pre_count++;
+ bptr[1].predecessorcount++;
break;
} /* end switch */
} /* end basic block loop */
while (--b_count >= 0) {
#if defined(STACK_VERBOSE)
- printf("ANALYZING BLOCK L%03d\n", bptr->debug_nr);
+ printf("ANALYZING BLOCK L%03d\n", bptr->nr);
#endif
if (bptr->flags == BBDELETED) {
bte = builtintable_get_automatic(opcode);
if (bte && bte->opcode == opcode) {
- iptr->opc = ICMD_BUILTIN;
- iptr->flags.bits = INS_FLAG_NOCHECK;
+ iptr->opc = ICMD_BUILTIN;
+ iptr->flags.bits = INS_FLAG_NOCHECK;
iptr->sx.s23.s3.bte = bte;
/* iptr->line is already set */
- m->isleafmethod = false;
+ jd->isleafmethod = false;
goto icmd_BUILTIN;
}
);
CLR_DST; /* XXX live through? */
break;
- case ICMD_IFEQ_ICONST:
- case ICMD_IFNE_ICONST:
- case ICMD_IFLT_ICONST:
- case ICMD_IFGE_ICONST:
- case ICMD_IFGT_ICONST:
- case ICMD_IFLE_ICONST:
- case ICMD_ELSE_ICONST:
- USE_S1(TYPE_INT);
- CLR_SX;
- CLR_DST; /* XXX live through? */
- break;
-
case ICMD_RET:
USE_S1_LOCAL(TYPE_ADR);
CLR_SX;
putconst_tail:
/* set the field reference (s3) */
- if (iptr[1].flags.bits & INS_FLAG_UNRESOLVED)
- iptr->sx.s23.s3.fmiref = iptr[1].sx.s23.s3.fmiref;
- else
+ if (iptr[1].flags.bits & INS_FLAG_UNRESOLVED) {
iptr->sx.s23.s3.uf = iptr[1].sx.s23.s3.uf;
+ iptr->flags.bits |= INS_FLAG_UNRESOLVED;
+ }
+ else {
+ iptr->sx.s23.s3.fmiref = iptr[1].sx.s23.s3.fmiref;
+ }
switch (iptr[1].opc) {
case ICMD_PUTSTATIC:
i--;
copy = copy->prev;
}
- /* XXX */
+
+ iptr->dst.localindex = iptr->s1.localindex;
break;
/* pop 1 push 0 store */
case ICMD_FRETURN:
case ICMD_DRETURN:
case ICMD_ARETURN:
- IF_JIT( md_return_alloc(m, rd, opcode - ICMD_IRETURN,
- curstack); )
+ IF_JIT( md_return_alloc(jd, curstack); )
COUNT(count_pcmd_return);
NEW_OP1_0(opcode - ICMD_IRETURN);
superblockend = true;
iptr->dst.dupslots = DMNEW(stackptr, 2 + 3);
iptr->dst.dupslots[0] = curstack->prev;
iptr->dst.dupslots[1] = curstack;
- curstack = curstack->prev->prev;
+ POPANY; POPANY;
DUP_SLOT(iptr->dst.dupslots[1]);
iptr->dst.dupslots[2+0] = curstack;
iptr->dst.dupslots[0] = curstack->prev->prev;
iptr->dst.dupslots[1] = curstack->prev;
iptr->dst.dupslots[2] = curstack;
- curstack = curstack->prev->prev->prev;
+ POPANY; POPANY; POPANY;
DUP_SLOT(iptr->dst.dupslots[1]);
iptr->dst.dupslots[3+0] = curstack;
iptr->dst.dupslots[0] = curstack->prev->prev;
iptr->dst.dupslots[1] = curstack->prev;
iptr->dst.dupslots[2] = curstack;
- curstack = curstack->prev->prev->prev;
+ POPANY; POPANY; POPANY;
DUP_SLOT(iptr->dst.dupslots[2]);
iptr->dst.dupslots[3+0] = curstack;
iptr->dst.dupslots[1] = curstack->prev->prev;
iptr->dst.dupslots[2] = curstack->prev;
iptr->dst.dupslots[3] = curstack;
- curstack = curstack->prev->prev->prev->prev;
+ POPANY; POPANY; POPANY; POPANY;
DUP_SLOT(iptr->dst.dupslots[2]);
iptr->dst.dupslots[4+0] = curstack;
iptr->dst.dupslots = DMNEW(stackptr, 2 + 2);
iptr->dst.dupslots[0] = curstack->prev;
iptr->dst.dupslots[1] = curstack;
- curstack = curstack->prev->prev;
+ POPANY; POPANY;
DUP_SLOT(iptr->dst.dupslots[1]);
iptr->dst.dupslots[2+0] = curstack;
NEW_CHECKOVERFLOW;
/* calculate stack after return */
- NEW_OP1_0_ANY;
+ POPANY;
+ stackdepth--;
break;
/* pop many push any */
REQUIRE(i);
/* XXX optimize for <= 2 args */
- iptr->s1.argcount = i;
- iptr->sx.s23.s2.args = DMNEW(stackptr, i);
+ /* XXX not for ICMD_BUILTIN */
+ iptr->s1.argcount = stackdepth;
+ iptr->sx.s23.s2.args = DMNEW(stackptr, stackdepth);
copy = curstack;
for (i-- ; i >= 0; i--) {
copy->varkind = ARGVAR;
copy->varnum = i;
- IF_NO_INTRP(
+#if defined(ENABLE_INTRP)
+ if (!opt_intrp) {
+#endif
if (md->params[i].inmemory) {
copy->flags = INMEMORY;
copy->regoff = md->params[i].regoff;
#else
copy->regoff =
rd->argfltregs[md->params[i].regoff];
-#endif
+#endif /* SUPPORT_PASS_FLOATARGS_IN_INTREGS */
}
else {
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
else
-#endif
+#endif /* SUPPORT_COMBINE_INTEGER_REGISTERS */
copy->regoff =
rd->argintregs[md->params[i].regoff];
}
}
- )
+#if defined(ENABLE_INTRP)
+ } /* end if (!opt_intrp) */
+#endif
}
copy = copy->prev;
}
+ /* deal with live-through stack slots "under" the arguments */
+ /* XXX not for ICMD_BUILTIN */
+
+ i = md->paramcount;
+
while (copy) {
+ iptr->sx.s23.s2.args[i++] = copy;
copy->flags |= SAVEDVAR;
copy = copy->prev;
}
+ /* pop the arguments */
+
i = md->paramcount;
stackdepth -= i;
POPANY;
}
+ /* push the return value */
+
if (md->returntype.type != TYPE_VOID) {
NEW_DST(md->returntype.type, stackdepth);
stackdepth++;
#if defined(SPECIALMEMUSE)
# if defined(__DARWIN__)
- if (rd->memuse < (i + INT_ARG_CNT + LA_WORD_SIZE))
- rd->memuse = i + LA_WORD_SIZE + INT_ARG_CNT;
+ if (rd->memuse < (i + INT_ARG_CNT + LA_SIZE_IN_POINTERS))
+ rd->memuse = i + LA_SIZE_IN_POINTERS + INT_ARG_CNT;
# else
- if (rd->memuse < (i + LA_WORD_SIZE + 3))
- rd->memuse = i + LA_WORD_SIZE + 3;
+ if (rd->memuse < (i + LA_SIZE_IN_POINTERS + 3))
+ rd->memuse = i + LA_SIZE_IN_POINTERS + 3;
# endif
#else
# if defined(__I386__)
copy->flags |= INMEMORY;
#if defined(SPECIALMEMUSE)
# if defined(__DARWIN__)
- copy->regoff = i + LA_WORD_SIZE + INT_ARG_CNT;
+ copy->regoff = i + LA_SIZE_IN_POINTERS + INT_ARG_CNT;
# else
- copy->regoff = i + LA_WORD_SIZE + 3;
+ copy->regoff = i + LA_SIZE_IN_POINTERS + 3;
# endif
#else
# if defined(__I386__)
#if defined(ENABLE_VERIFIER)
throw_stack_underflow:
- *exceptionptr =
- new_verifyerror(m, "Unable to pop operand off an empty stack");
+ exceptions_throw_verifyerror(m, "Unable to pop operand off an empty stack");
return false;
throw_stack_overflow:
- *exceptionptr = new_verifyerror(m, "Stack size too large");
+ exceptions_throw_verifyerror(m, "Stack size too large");
return false;
throw_stack_depth_error:
- *exceptionptr = new_verifyerror(m,"Stack depth mismatch");
+ exceptions_throw_verifyerror(m,"Stack depth mismatch");
return false;
throw_stack_type_error:
return false;
throw_stack_category_error:
- *exceptionptr =
- new_verifyerror(m, "Attempt to split long or double on the stack");
+ exceptions_throw_verifyerror(m, "Attempt to split long or double on the stack");
return false;
#endif
bool stack_analyse(jitdata *jd)
{
methodinfo *m;
+ codeinfo *code;
codegendata *cd;
registerdata *rd;
int b_count;
/* get required compiler data */
- m = jd->m;
- cd = jd->cd;
- rd = jd->rd;
-
-#if defined(ENABLE_LSRA)
- m->maxlifetimes = 0;
-#endif
+ m = jd->m;
+ code = jd->code;
+ cd = jd->cd;
+ rd = jd->rd;
last_store = DMNEW(s4 , cd->maxlocals * 5);
bptr->type = BBTYPE_EXH;
bptr->instack = new;
bptr->indepth = 1;
- bptr->pre_count = 10000;
+ bptr->predecessorcount = CFG_UNKNOWN_PREDECESSORS;
STACKRESET;
NEWXSTACK;
}
-#if CONDITIONAL_LOADCONST
- b_count = m->basicblockcount;
- bptr = m->basicblocks;
- while (--b_count >= 0) {
- if (bptr->icount != 0) {
- iptr = bptr->iinstr + bptr->icount - 1;
- switch (iptr->opc) {
- case ICMD_RET:
- case ICMD_RETURN:
- case ICMD_IRETURN:
- case ICMD_LRETURN:
- case ICMD_FRETURN:
- case ICMD_DRETURN:
- case ICMD_ARETURN:
- case ICMD_ATHROW:
- break;
-
- case ICMD_IFEQ:
- case ICMD_IFNE:
- case ICMD_IFLT:
- case ICMD_IFGE:
- case ICMD_IFGT:
- case ICMD_IFLE:
-
- case ICMD_IFNULL:
- case ICMD_IFNONNULL:
-
- case ICMD_IF_ICMPEQ:
- case ICMD_IF_ICMPNE:
- case ICMD_IF_ICMPLT:
- case ICMD_IF_ICMPGE:
- case ICMD_IF_ICMPGT:
- case ICMD_IF_ICMPLE:
-
- case ICMD_IF_ACMPEQ:
- case ICMD_IF_ACMPNE:
- bptr[1].pre_count++;
- case ICMD_GOTO:
- m->basicblocks[m->basicblockindex[iptr->op1]].pre_count++;
- break;
-
- case ICMD_TABLESWITCH:
- s4ptr = iptr->val.a;
- m->basicblocks[m->basicblockindex[*s4ptr++]].pre_count++;
- i = *s4ptr++; /* low */
- i = *s4ptr++ - i + 1; /* high */
- while (--i >= 0) {
- m->basicblocks[m->basicblockindex[*s4ptr++]].pre_count++;
- }
- break;
-
- case ICMD_LOOKUPSWITCH:
- s4ptr = iptr->val.a;
- m->basicblocks[m->basicblockindex[*s4ptr++]].pre_count++;
- i = *s4ptr++; /* count */
- while (--i >= 0) {
- m->basicblocks[m->basicblockindex[s4ptr[1]]].pre_count++;
- s4ptr += 2;
- }
- break;
- default:
- bptr[1].pre_count++;
- break;
- }
- }
- bptr++;
- }
-#endif /* CONDITIONAL_LOADCONST */
-
-
do {
loops++;
b_count = m->basicblockcount;
while (--len >= 0) {
opcode = iptr->opc;
+ /* check if ICMD opcode could throw an exception */
+ /* and if so remember the instruction index in last_pei */
+
+ if (op_data[opcode][PEI])
+ last_pei = bptr->icount - len - 1;
+
#if defined(USEBUILTINTABLE)
# if defined(ENABLE_INTRP)
if (!opt_intrp) {
# endif
+ /* check for opcodes to replace */
+
bte = builtintable_get_automatic(opcode);
if (bte && bte->opcode == opcode) {
- iptr->opc = ICMD_BUILTIN;
- iptr->op1 = false; /* don't check for exception */
+ iptr->opc = ICMD_BUILTIN;
+ iptr->op1 = false; /* don't check for exception */
iptr->val.a = bte;
- m->isleafmethod = false;
+ jd->isleafmethod = false;
goto builtin;
}
# if defined(ENABLE_INTRP)
# endif
#endif /* defined(USEBUILTINTABLE) */
+ /* Check for functions to replace with builtin
+ functions. */
+
+ if (builtintable_replace_function(iptr))
+ goto builtin;
+
/* this is the main switch */
switch (opcode) {
case ICMD_CHECKNULL:
COUNT(count_check_null);
case ICMD_NOP:
-
- case ICMD_IFEQ_ICONST:
- case ICMD_IFNE_ICONST:
- case ICMD_IFLT_ICONST:
- case ICMD_IFGE_ICONST:
- case ICMD_IFGT_ICONST:
- case ICMD_IFLE_ICONST:
- case ICMD_ELSE_ICONST:
SETDST;
break;
# if defined(ENABLE_INTRP)
if (!opt_intrp)
# endif
- md_return_alloc(m, rd, opcode - ICMD_IRETURN,
- curstack);
+ md_return_alloc(jd, curstack);
#endif
COUNT(count_pcmd_return);
OP1_0(opcode - ICMD_IRETURN);
case ICMD_IFGT:
case ICMD_IFLE:
COUNT(count_pcmd_bra);
-#if CONDITIONAL_LOADCONST && 0
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
- tbptr = m->basicblocks + b_index;
-
- if ((b_count >= 3) &&
- ((b_index + 2) == m->basicblockindex[iptr[0].op1]) &&
- (tbptr[1].pre_count == 1) &&
- (tbptr[1].iinstr[0].opc == ICMD_ICONST) &&
- (tbptr[1].iinstr[1].opc == ICMD_GOTO) &&
- ((b_index + 3) == m->basicblockindex[tbptr[1].iinstr[1].op1]) &&
- (tbptr[2].pre_count == 1) &&
- (tbptr[2].iinstr[0].opc == ICMD_ICONST) &&
- (tbptr[2].icount==1)) {
- /*printf("tbptr[2].icount=%d\n",tbptr[2].icount);*/
- OP1_1(TYPE_INT, TYPE_INT);
- switch (iptr[0].opc) {
- case ICMD_IFEQ:
- iptr[0].opc = ICMD_IFNE_ICONST;
- break;
- case ICMD_IFNE:
- iptr[0].opc = ICMD_IFEQ_ICONST;
- break;
- case ICMD_IFLT:
- iptr[0].opc = ICMD_IFGE_ICONST;
- break;
- case ICMD_IFGE:
- iptr[0].opc = ICMD_IFLT_ICONST;
- break;
- case ICMD_IFGT:
- iptr[0].opc = ICMD_IFLE_ICONST;
- break;
- case ICMD_IFLE:
- iptr[0].opc = ICMD_IFGT_ICONST;
- break;
- }
-#if 1
- iptr[0].val.i = iptr[1].val.i;
- iptr[1].opc = ICMD_ELSE_ICONST;
- iptr[1].val.i = iptr[3].val.i;
- iptr[2].opc = ICMD_NOP;
- iptr[3].opc = ICMD_NOP;
-#else
- /* HACK: save compare value in iptr[1].op1 */
- iptr[1].op1 = iptr[0].val.i;
- iptr[0].val.i = tbptr[1].iinstr[0].val.i;
- iptr[1].opc = ICMD_ELSE_ICONST;
- iptr[1].val.i = tbptr[2].iinstr[0].val.i;
- tbptr[1].iinstr[0].opc = ICMD_NOP;
- tbptr[1].iinstr[1].opc = ICMD_NOP;
- tbptr[2].iinstr[0].opc = ICMD_NOP;
-#endif
- tbptr[1].flags = BBDELETED;
- tbptr[2].flags = BBDELETED;
- tbptr[1].icount = 0;
- tbptr[2].icount = 0;
- if (tbptr[3].pre_count == 2) {
- len += tbptr[3].icount + 3;
- bptr->icount += tbptr[3].icount + 3;
- tbptr[3].flags = BBDELETED;
- tbptr[3].icount = 0;
- b_index++;
- }
- else {
- bptr->icount++;
- len ++;
- }
- b_index += 2;
- break;
- }
-# if defined(ENABLE_INTRP)
- }
-# endif
-
-#endif /* CONDITIONAL_LOADCONST */
/* iptr->val.i is set implicitly in parse by
clearing the memory or from IF_ICMPxx
/* pop many push any */
case ICMD_BUILTIN:
-#if defined(USEBUILTINTABLE)
builtin:
-#endif
bte = (builtintable_entry *) iptr->val.a;
md = bte->md;
goto _callhandling;
_callhandling:
- last_pei = bptr->icount - len - 1;
+/* last_pei = bptr->icount - len - 1; */
i = md->paramcount;
REQUIRE(i);
#if defined(SPECIALMEMUSE)
# if defined(__DARWIN__)
- if (rd->memuse < (i + INT_ARG_CNT + LA_WORD_SIZE))
- rd->memuse = i + LA_WORD_SIZE + INT_ARG_CNT;
+ if (rd->memuse < (i + INT_ARG_CNT + LA_SIZE_IN_POINTERS))
+ rd->memuse = i + LA_SIZE_IN_POINTERS + INT_ARG_CNT;
# else
- if (rd->memuse < (i + LA_WORD_SIZE + 3))
- rd->memuse = i + LA_WORD_SIZE + 3;
+ if (rd->memuse < (i + LA_SIZE_IN_POINTERS + 3))
+ rd->memuse = i + LA_SIZE_IN_POINTERS + 3;
# endif
#else
# if defined(__I386__)
copy->flags |= INMEMORY;
#if defined(SPECIALMEMUSE)
# if defined(__DARWIN__)
- copy->regoff = i + LA_WORD_SIZE + INT_ARG_CNT;
+ copy->regoff = i + LA_SIZE_IN_POINTERS + INT_ARG_CNT;
# else
- copy->regoff = i + LA_WORD_SIZE + 3;
+ copy->regoff = i + LA_SIZE_IN_POINTERS + 3;
# endif
#else
# if defined(__I386__)
#if defined(ENABLE_VERIFIER)
throw_stack_underflow:
- *exceptionptr =
- new_verifyerror(m, "Unable to pop operand off an empty stack");
+ exceptions_throw_verifyerror(m, "Unable to pop operand off an empty stack");
return false;
throw_stack_overflow:
- *exceptionptr = new_verifyerror(m, "Stack size too large");
+ exceptions_throw_verifyerror(m, "Stack size too large");
return false;
throw_stack_depth_error:
- *exceptionptr = new_verifyerror(m,"Stack depth mismatch");
+ exceptions_throw_verifyerror(m, "Stack depth mismatch");
return false;
throw_stack_type_error:
return false;
throw_stack_category_error:
- *exceptionptr =
- new_verifyerror(m, "Attempt to split long or double on the stack");
+ exceptions_throw_verifyerror(m, "Attempt to split long or double on the stack");
return false;
#endif