Christian Thalinger
Christian Ullrich
- $Id: stack.c 5358 2006-09-06 00:18:21Z christian $
+ $Id: stack.c 5359 2006-09-06 09:57:21Z edwin $
*/
instruction *iptr; /* the current instruction */
basicblock *bptr; /* the current basic block */
basicblock *tbptr;
- s4 *last_store; /* instruction index of last XSTORE */
- /* [ local_index * 5 + type ] */
- s4 last_pei; /* ins. index of last possible exception */
- /* used for conflict resolution for copy */
- /* elimination (XLOAD, IINC, XSTORE) */
- s4 last_dupx;
+
+ stackptr *last_store_boundary;
+ stackptr last_pei_boundary;
+ stackptr last_dup_boundary;
+
branch_target_t *table;
lookup_target_t *lookup;
#if defined(ENABLE_VERIFIER)
iteration_count = 0;
#endif
- last_store = DMNEW(s4 , cd->maxlocals * 5);
+ last_store_boundary = DMNEW(stackptr , cd->maxlocals);
/* initialize in-stack of first block */
/* reset variables for dependency checking */
- last_pei = -1;
- last_dupx = -1;
+ last_pei_boundary = new;
+ last_dup_boundary = new;
for( i = 0; i < cd->maxlocals; i++)
- for( j = 0; j < 5; j++)
- last_store[5 * i + j] = -1;
+ last_store_boundary[i] = new;
/* XXX store the start of the block's stack representation */
break;
case ICMD_CHECKNULL:
+ last_pei_boundary = new;
COUNT(count_check_null);
USE_S1(TYPE_ADR);
CLR_SX;
/************************** ACONST OPTIMIZATIONS **************************/
case ICMD_ACONST:
+ last_pei_boundary = new;
COUNT(count_pcmd_load);
#if SUPPORT_CONST_STORE
IF_INTRP( goto normal_ACONST; )
case ICMD_FALOAD:
case ICMD_DALOAD:
case ICMD_AALOAD:
+ last_pei_boundary = new;
COUNT(count_check_null);
COUNT(count_check_bound);
COUNT(count_pcmd_mem);
case ICMD_BALOAD:
case ICMD_CALOAD:
case ICMD_SALOAD:
+ last_pei_boundary = new;
COUNT(count_check_null);
COUNT(count_check_bound);
COUNT(count_pcmd_mem);
/* for new vars */
/* iptr->s1.localindex = jd->local_map[iptr->s1.localindex * 5 + i]; */
- last_store[5 * iptr->s1.localindex + TYPE_INT] = bptr->icount - len - 1;
+ last_store_boundary[iptr->s1.localindex] = new;
copy = curstack;
i = stackdepth - 1;
REQUIRE_1;
i = opcode - ICMD_ISTORE; /* type */
+ j = iptr->dst.localindex; /* index */
/* for new vars */
-/* iptr->s1.localindex = jd->local_map[iptr->s1.localindex * 5 + i]; */
+/* iptr->dst.localindex = jd->local_map[iptr->dst.localindex * 5 + i]; */
- IF_NO_INTRP( rd->locals[iptr->dst.localindex][i].type = i; )
+ IF_NO_INTRP( rd->locals[j][i].type = i; )
#if defined(ENABLE_STATISTICS)
if (opt_stat) {
}
#endif
/* check for conflicts as described in Figure 5.2 */
+
copy = curstack->prev;
i = stackdepth - 2;
while (copy) {
if ((copy->varkind == LOCALVAR) &&
- (copy->varnum == iptr->dst.localindex))
+ (copy->varnum == j))
{
copy->varkind = TEMPVAR;
copy->varnum = i;
copy = copy->prev;
}
+ /* if the variable is already coalesced, don't bother */
+
+ if (curstack->varkind == STACKVAR
+ || (curstack->varkind == LOCALVAR && curstack->varnum != j))
+ goto store_tail;
+
+ /* there is no STORE Lj while curstack is live */
+
+ if (curstack < last_store_boundary[j])
+ goto assume_conflict;
+
+ /* there is no PEI while curstack is live */
+
+ if (curstack < last_pei_boundary)
+ goto assume_conflict;
+
+ /* there is no non-consuming USE while curstack is live */
+
+ if (curstack < last_dup_boundary)
+ goto assume_conflict;
+
+ /* there is no DEF LOCALVAR(j) while curstack is live */
+
+ copy = new; /* most recent stackslot created + 1 */
+ while (--copy > curstack) {
+ if (copy->varkind == LOCALVAR && copy->varnum == j)
+ goto assume_conflict;
+ }
+
+ /* coalesce the temporary variable with Lj */
+
+ curstack->varkind = LOCALVAR;
+ curstack->varnum = j;
+ goto store_tail;
+
+ /* revert the coalescing, if it has been done earlier */
+assume_conflict:
if ((curstack->varkind == LOCALVAR)
- && (curstack->varnum == iptr->dst.localindex))
+ && (curstack->varnum == j))
{
curstack->varkind = TEMPVAR;
curstack->varnum = stackdepth-1;
}
- last_store[5 * iptr->dst.localindex + (opcode - ICMD_ISTORE)] = bptr->icount - len - 1;
+ /* remember the stack boundary at this store */
+store_tail:
+ last_store_boundary[j] = new;
- NEW_STORE(opcode - ICMD_ISTORE, iptr->dst.localindex);
+ NEW_STORE(opcode - ICMD_ISTORE, j);
break;
/* pop 3 push 0 */
case ICMD_AASTORE:
+ last_pei_boundary = new;
COUNT(count_check_null);
COUNT(count_check_bound);
COUNT(count_pcmd_mem);
case ICMD_LASTORE:
case ICMD_FASTORE:
case ICMD_DASTORE:
+ last_pei_boundary = new;
COUNT(count_check_null);
COUNT(count_check_bound);
COUNT(count_pcmd_mem);
case ICMD_BASTORE:
case ICMD_CASTORE:
case ICMD_SASTORE:
+ last_pei_boundary = new;
COUNT(count_check_null);
COUNT(count_check_bound);
COUNT(count_pcmd_mem);
case ICMD_FRETURN:
case ICMD_DRETURN:
case ICMD_ARETURN:
+ last_pei_boundary = new;
IF_JIT( md_return_alloc(jd, curstack); )
COUNT(count_pcmd_return);
NEW_OP1_0(opcode - ICMD_IRETURN);
break;
case ICMD_ATHROW:
+ last_pei_boundary = new;
COUNT(count_check_null);
NEW_OP1_0(TYPE_ADR);
STACKRESET;
break;
case ICMD_PUTSTATIC:
+ last_pei_boundary = new;
COUNT(count_pcmd_mem);
INSTRUCTION_GET_FIELDREF(iptr, fmiref);
NEW_OP1_0(fmiref->parseddesc.fd->type);
case ICMD_MONITORENTER:
case ICMD_MONITOREXIT:
+ last_pei_boundary = new;
COUNT(count_check_null);
NEW_OP1_0(TYPE_ADR);
break;
/* pop 2 push 0 */
case ICMD_PUTFIELD:
+ last_pei_boundary = new;
COUNT(count_check_null);
COUNT(count_pcmd_mem);
INSTRUCTION_GET_FIELDREF(iptr, fmiref);
goto throw_stack_category_error;
}
#endif
- last_dupx = bptr->icount - len - 1;
COUNT(count_dup_instruction);
icmd_DUP:
USE_S1_ANY; /* XXX live through */
DUP_SLOT(iptr->s1.var);
+ last_dup_boundary = new - 1;
iptr->dst.var = curstack;
stackdepth++;
break;
case ICMD_DUP2:
- last_dupx = bptr->icount - len - 1;
REQUIRE_1;
if (IS_2_WORD_TYPE(curstack->type)) {
/* ..., cat2 */
iptr->dst.dupslots[2+0] = curstack;
DUP_SLOT(iptr->dst.dupslots[1]);
iptr->dst.dupslots[2+1] = curstack;
+ last_dup_boundary = new;
stackdepth += 2;
}
break;
goto throw_stack_category_error;
}
#endif
- last_dupx = bptr->icount - len - 1;
icmd_DUP_X1:
iptr->dst.dupslots = DMNEW(stackptr, 2 + 3);
iptr->dst.dupslots[2+1] = curstack;
DUP_SLOT(iptr->dst.dupslots[1]);
iptr->dst.dupslots[2+2] = curstack;
+ last_dup_boundary = new;
stackdepth++;
break;
case ICMD_DUP2_X1:
- last_dupx = bptr->icount - len - 1;
REQUIRE_2;
if (IS_2_WORD_TYPE(curstack->type)) {
/* ..., ????, cat2 */
iptr->dst.dupslots[3+3] = curstack;
DUP_SLOT(iptr->dst.dupslots[2]);
iptr->dst.dupslots[3+4] = curstack;
+ last_dup_boundary = new;
stackdepth += 2;
}
break;
/* pop 3 push 4 dup */
case ICMD_DUP_X2:
- last_dupx = bptr->icount - len - 1;
REQUIRE_2;
if (IS_2_WORD_TYPE(curstack->prev->type)) {
/* ..., cat2, ???? */
iptr->dst.dupslots[3+2] = curstack;
DUP_SLOT(iptr->dst.dupslots[2]);
iptr->dst.dupslots[3+3] = curstack;
+ last_dup_boundary = new;
stackdepth++;
}
break;
case ICMD_DUP2_X2:
- last_dupx = bptr->icount - len - 1;
REQUIRE_2;
if (IS_2_WORD_TYPE(curstack->type)) {
/* ..., ????, cat2 */
iptr->dst.dupslots[4+4] = curstack;
DUP_SLOT(iptr->dst.dupslots[3]);
iptr->dst.dupslots[4+5] = curstack;
+ last_dup_boundary = new;
stackdepth += 2;
}
break;
/* pop 2 push 2 swap */
case ICMD_SWAP:
- last_dupx = bptr->icount - len - 1;
#ifdef ENABLE_VERIFIER
if (opt_verify) {
REQUIRE_2;
iptr->dst.dupslots[2+0] = curstack;
DUP_SLOT(iptr->dst.dupslots[0]);
iptr->dst.dupslots[2+1] = curstack;
+ last_dup_boundary = new;
break;
/* pop 2 push 1 */
case ICMD_IDIV:
case ICMD_IREM:
+ last_pei_boundary = new;
#if !SUPPORT_DIVISION
bte = iptr->sx.s23.s3.bte;
md = bte->md;
case ICMD_LDIV:
case ICMD_LREM:
+ last_pei_boundary = new;
#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
bte = iptr->sx.s23.s3.bte;
md = bte->md;
break;
case ICMD_CHECKCAST:
+ last_pei_boundary = new;
if (iptr->flags.bits & INS_FLAG_ARRAY) {
/* array type cast-check */
case ICMD_INSTANCEOF:
case ICMD_ARRAYLENGTH:
+ last_pei_boundary = new;
NEW_OP1_1(TYPE_ADR, TYPE_INT);
break;
case ICMD_NEWARRAY:
case ICMD_ANEWARRAY:
+ last_pei_boundary = new;
NEW_OP1_1(TYPE_INT, TYPE_ADR);
break;
case ICMD_GETFIELD:
+ last_pei_boundary = new;
COUNT(count_check_null);
COUNT(count_pcmd_mem);
INSTRUCTION_GET_FIELDREF(iptr, fmiref);
/* pop 0 push 1 */
case ICMD_GETSTATIC:
+ last_pei_boundary = new;
COUNT(count_pcmd_mem);
INSTRUCTION_GET_FIELDREF(iptr, fmiref);
NEW_OP0_1(fmiref->parseddesc.fd->type);
break;
case ICMD_NEW:
+ last_pei_boundary = new;
NEW_OP0_1(TYPE_ADR);
break;
_callhandling:
- last_pei = bptr->icount - len - 1;
+ last_pei_boundary = new;
i = md->paramcount;
break;
case ICMD_MULTIANEWARRAY:
+ last_pei_boundary = new;
if (rd->argintreguse < 3)
rd->argintreguse = 3;