Christian Thalinger
Christian Ullrich
- $Id: stack.c 5244 2006-08-16 12:21:35Z christian $
+ $Id: stack.c 5454 2006-09-10 11:20:40Z edwin $
*/
#if defined(ENABLE_STATISTICS)
#define STATISTICS_STACKDEPTH_DISTRIBUTION(distr) \
- do { \
- if (opt_stat) { \
- if (stackdepth >= 10) \
- count_store_depth[10]++; \
- else \
- count_store_depth[stackdepth]++; \
- } \
- } while (0)
+ do { \
+ if (opt_stat) { \
+ if (stackdepth >= 10) \
+ count_store_depth[10]++; \
+ else \
+ count_store_depth[stackdepth]++; \
+ } \
+ } while (0)
#else /* !defined(ENABLE_STATISTICS) */
#define STATISTICS_STACKDEPTH_DISTRIBUTION(distr)
#endif
-/* stack_init ******************************************************************
+/* stackdata_t ****************************************************************/
- Initialized the stack analysis subsystem (called by jit_init).
+typedef struct stackdata_t stackdata_t;
-*******************************************************************************/
+struct stackdata_t {
+ basicblock *bptr;
+ stackptr new;
+ s4 vartop;
+ s4 localcount;
+ s4 varcount;
+ varinfo *var;
+ methodinfo *m;
+};
-bool stack_init(void)
-{
- return true;
-}
+/* macros for allocating/releasing variable indices */
-/* stack_analyse ***************************************************************
+#define GET_NEW_INDEX(sd, new_varindex) \
+ do { \
+ assert((sd).vartop < (sd).varcount); \
+ (new_varindex) = ((sd).vartop)++; \
+ } while (0)
- Analyse_stack uses the intermediate code created by parse.c to
- build a model of the JVM operand stack for the current method.
-
- The following checks are performed:
- - check for operand stack underflow (before each instruction)
- - check for operand stack overflow (after[1] each instruction)
- - check for matching stack depth at merging points
- - check for matching basic types[2] at merging points
- - check basic types for instruction input (except for BUILTIN*
- opcodes, INVOKE* opcodes and MULTIANEWARRAY)
-
- [1]) Checking this after the instruction should be ok. parse.c
- counts the number of required stack slots in such a way that it is
- only vital that we don't exceed `maxstack` at basic block
- boundaries.
-
- [2]) 'basic types' means the distinction between INT, LONG, FLOAT,
- DOUBLE and ADDRESS types. Subtypes of INT and different ADDRESS
- types are not discerned.
+/* not implemented now, can be used to reuse varindices */
+/* pay attention to not release a localvar once implementing it! */
+#define RELEASE_INDEX(sd, varindex)
-*******************************************************************************/
+#define GET_NEW_VAR(sd, new_varindex, newtype) \
+ do { \
+ GET_NEW_INDEX((sd), (new_varindex)); \
+ (sd).var[new_index].type = (newtype); \
+ } while (0)
+
+/* macros for querying variable properties **************************/
+
+#define IS_OUTVAR(sp) \
+ (sd.var[(sp)->varnum].flags & OUTVAR)
+
+#define IS_PREALLOC(sp) \
+ (sd.var[(sp)->varnum].flags & PREALLOC)
+
+#define IS_TEMPVAR(sp) \
+ ( ((sp)->varnum >= sd.localcount) \
+ && !(sd.var[(sp)->varnum].flags & (OUTVAR | PREALLOC)) )
+
+#define IS_LOCALVAR_SD(sd, sp) \
+ ((sp)->varnum < (sd).localcount)
+
+#define IS_LOCALVAR(sp) \
+ IS_LOCALVAR_SD(sd, (sp))
-#define BLOCK_OF(index) \
- (jd->new_basicblocks + jd->new_basicblockindex[index])
+
+/* macros for setting variable properties ****************************/
+
+#define SET_TEMPVAR(sp) \
+ do { \
+ if (IS_LOCALVAR((sp))) { \
+ GET_NEW_VAR(sd, new_index, (sp)->type); \
+ sd.var[new_index].flags = (sp)->flags; \
+ (sp)->varnum = new_index; \
+ (sp)->varkind = TEMPVAR; \
+ if ((sp)->creator) \
+ (sp)->creator->dst.varindex = new_index; \
+ } \
+ sd.var[(sp)->varnum].flags &= ~(OUTVAR | PREALLOC); \
+ } while (0);
+
+#define SET_PREALLOC(sp) \
+ do { \
+ assert(!IS_LOCALVAR((sp))); \
+ sd.var[(sp)->varnum].flags |= PREALLOC; \
+ } while (0);
+
+/* macros for source operands ***************************************/
#define CLR_S1 \
- (iptr->s1.var = NULL)
+ (iptr->s1.varindex = -1)
#define USE_S1_LOCAL(type1)
#define USE_S1(type1) \
do { \
- REQUIRE_1; \
+ REQUIRE(1); \
CHECK_BASIC_TYPE(type1, curstack->type); \
- iptr->s1.var = curstack; \
+ iptr->s1.varindex = curstack->varnum; \
} while (0)
#define USE_S1_ANY \
do { \
- REQUIRE_1; \
- iptr->s1.var = curstack; \
+ REQUIRE(1); \
+ iptr->s1.varindex = curstack->varnum; \
} while (0)
#define USE_S1_S2(type1, type2) \
do { \
- REQUIRE_2; \
+ REQUIRE(2); \
CHECK_BASIC_TYPE(type1, curstack->prev->type); \
CHECK_BASIC_TYPE(type2, curstack->type); \
- iptr->sx.s23.s2.var = curstack; \
- iptr->s1.var = curstack->prev; \
+ iptr->sx.s23.s2.varindex = curstack->varnum; \
+ iptr->s1.varindex = curstack->prev->varnum; \
} while (0)
#define USE_S1_S2_ANY_ANY \
do { \
- REQUIRE_2; \
- iptr->sx.s23.s2.var = curstack; \
- iptr->s1.var = curstack->prev; \
+ REQUIRE(2); \
+ iptr->sx.s23.s2.varindex = curstack->varnum; \
+ iptr->s1.varindex = curstack->prev->varnum; \
} while (0)
#define USE_S1_S2_S3(type1, type2, type3) \
do { \
- REQUIRE_3; \
+ REQUIRE(3); \
CHECK_BASIC_TYPE(type1, curstack->prev->prev->type); \
CHECK_BASIC_TYPE(type2, curstack->prev->type); \
CHECK_BASIC_TYPE(type3, curstack->type); \
- iptr->sx.s23.s3.var = curstack; \
- iptr->sx.s23.s2.var = curstack->prev; \
- iptr->s1.var = curstack->prev->prev; \
+ iptr->sx.s23.s3.varindex = curstack->varnum; \
+ iptr->sx.s23.s2.varindex = curstack->prev->varnum; \
+ iptr->s1.varindex = curstack->prev->prev->varnum; \
+ } while (0)
+
+/* The POPANY macro does NOT check stackdepth, or set stackdepth! */
+#define POPANY \
+ do { \
+ if (curstack->varkind == UNDEFVAR) \
+ curstack->varkind = TEMPVAR; \
+ curstack = curstack->prev; \
} while (0)
#define POP_S1(type1) \
#define CLR_SX \
(iptr->sx.val.l = 0)
+
+/* macros for setting the destination operand ***********************/
+
#define CLR_DST \
- (iptr->dst.var = NULL)
+ (iptr->dst.varindex = -1)
-#define NEW_DST(typed, depth) \
+#define DST(typed, index) \
do { \
- NEWSTACKn(typed, (depth)); \
- iptr->dst.var = curstack; \
+ NEWSTACKn((typed),(index)); \
+ curstack->creator = iptr; \
+ iptr->dst.varindex = (index); \
} while (0)
-#define NEW_DST_LOCALVAR(typed, index) \
+#define DST_LOCALVAR(typed, index) \
do { \
- NEWSTACK(typed, LOCALVAR, (index)); \
- iptr->dst.var = curstack; \
+ NEWSTACK((typed), LOCALVAR, (index)); \
+ curstack->creator = iptr; \
+ iptr->dst.varindex = (index); \
} while (0)
-#define NEW_OP0_0 \
+
+/* stack modelling macros *******************************************/
+
+#define OP0_1(typed) \
do { \
CLR_S1; \
- CLR_DST; \
+ GET_NEW_VAR(sd, new_index, (typed)); \
+ DST(typed, new_index); \
+ stackdepth++; \
} while (0)
-#define NEW_OP0_BRANCH \
+#define OP1_0_ANY \
do { \
- CLR_S1; \
+ POP_S1_ANY; \
+ CLR_DST; \
+ stackdepth--; \
} while (0)
-#define NEW_OP0_1(typed) \
+#define OP1_BRANCH(type1) \
do { \
- CLR_S1; \
- NEW_DST(typed, stackdepth); \
- stackdepth++; \
+ POP_S1(type1); \
+ stackdepth--; \
} while (0)
-#define NEW_OP1_0(type1) \
+#define OP1_1(type1, typed) \
do { \
POP_S1(type1); \
- CLR_DST; \
+ GET_NEW_VAR(sd, new_index, (typed)); \
+ DST(typed, new_index); \
+ } while (0)
+
+#define OP2_1(type1, type2, typed) \
+ do { \
+ POP_S1_S2(type1, type2); \
+ GET_NEW_VAR(sd, new_index, (typed)); \
+ DST(typed, new_index); \
stackdepth--; \
} while (0)
-#define NEW_OP1_0_ANY \
+#define OP0_0 \
do { \
- POP_S1_ANY; \
+ CLR_S1; \
CLR_DST; \
- stackdepth--; \
} while (0)
-#define NEW_OP1_BRANCH(type1) \
+#define OP0_BRANCH \
do { \
- POP_S1(type1); \
- stackdepth--; \
+ CLR_S1; \
} while (0)
-#define NEW_OP1_1(type1, typed) \
+#define OP1_0(type1) \
do { \
POP_S1(type1); \
- NEW_DST(typed, stackdepth - 1); \
+ CLR_DST; \
+ stackdepth--; \
} while (0)
-#define NEW_OP2_0(type1, type2) \
+#define OP2_0(type1, type2) \
do { \
POP_S1_S2(type1, type2); \
CLR_DST; \
stackdepth -= 2; \
} while (0)
-#define NEW_OP2_BRANCH(type1, type2) \
+#define OP2_BRANCH(type1, type2) \
do { \
POP_S1_S2(type1, type2); \
stackdepth -= 2; \
} while (0)
-#define NEW_OP2_0_ANY_ANY \
+#define OP2_0_ANY_ANY \
do { \
POP_S1_S2_ANY_ANY; \
CLR_DST; \
stackdepth -= 2; \
} while (0)
-#define NEW_OP2_1(type1, type2, typed) \
- do { \
- POP_S1_S2(type1, type2); \
- NEW_DST(typed, stackdepth - 2); \
- stackdepth--; \
- } while (0)
-
-#define NEW_OP3_0(type1, type2, type3) \
+#define OP3_0(type1, type2, type3) \
do { \
POP_S1_S2_S3(type1, type2, type3); \
CLR_DST; \
stackdepth -= 3; \
} while (0)
-#define NEW_LOAD(type1, index) \
+#define LOAD(type1, index) \
do { \
- NEW_DST_LOCALVAR(type1, index); \
+ DST_LOCALVAR(type1, index); \
stackdepth++; \
} while (0)
-#define NEW_STORE(type1, index) \
+#define STORE(type1, index) \
do { \
POP_S1(type1); \
stackdepth--; \
} while (0)
+
+/* macros for DUP elimination ***************************************/
+
+#define DUP_SLOT(sp) \
+ do { \
+ GET_NEW_VAR(sd, new_index, (sp)->type); \
+ NEWSTACK((sp)->type, TEMPVAR, new_index); \
+ } while(0)
+
+/* does not check input stackdepth */
+#define MOVE_UP(sp) \
+ do { \
+ iptr->opc = ICMD_MOVE; \
+ iptr->s1.varindex = (sp)->varnum; \
+ DUP_SLOT(sp); \
+ curstack->creator = iptr; \
+ iptr->dst.varindex = curstack->varnum; \
+ stackdepth++; \
+ } while (0)
+
+/* does not check input stackdepth */
+#define COPY_UP(sp) \
+ do { \
+ SET_TEMPVAR((sp)); \
+ iptr->opc = ICMD_COPY; \
+ iptr->s1.varindex = (sp)->varnum; \
+ DUP_SLOT(sp); \
+ curstack->creator = iptr; \
+ iptr->dst.varindex = curstack->varnum; \
+ stackdepth++; \
+ } while (0)
+
+#define COPY_DOWN(s, d) \
+ do { \
+ SET_TEMPVAR((s)); \
+ iptr->opc = ICMD_COPY; \
+ iptr->s1.varindex = (s)->varnum; \
+ iptr->dst.varindex = (d)->varnum; \
+ (d)->creator = iptr; \
+ } while (0)
+
+
+/* macros for branching / reaching basic blocks *********************/
+
+#if defined(ENABLE_VERIFIER)
+#define MARKREACHED(b, c) \
+ do { \
+ if (!stack_mark_reached(&sd, (b), curstack, stackdepth)) \
+ return false; \
+ } while (0)
+#else
+#define MARKREACHED(b, c) \
+ do { \
+ (void) stack_mark_reached(&sd, (b), curstack, stackdepth); \
+ } while (0)
+#endif
+
#define BRANCH_TARGET(bt, tempbptr, tempsp) \
do { \
(bt).block = tempbptr = BLOCK_OF((bt).insindex); \
MARKREACHED(tempbptr, tempsp); \
} while (0)
-#define DUP_SLOT(sp) \
- do { \
- if ((sp)->varkind != TEMPVAR) \
- NEWSTACK((sp)->type, TEMPVAR, stackdepth); \
- else \
- NEWSTACK((sp)->type, (sp)->varkind, (sp)->varnum); \
- } while(0)
+
+/* stack_init ******************************************************************
+
+ Initialized the stack analysis subsystem (called by jit_init).
+
+*******************************************************************************/
+
+bool stack_init(void)
+{
+ return true;
+}
+
+
+/* stack_create_invars *********************************************************
+
+ Create the invars for the given basic block.
+
+ IN:
+ sd...........stack analysis data
+ b............block to create the invars for
+ curstack.....current stack top
+ stackdepth...current stack depth
+
+ This function creates STACKDEPTH invars and sets their types to the
+ types to the types of the corresponding slot in the current stack.
+
+*******************************************************************************/
+
+static void stack_create_invars(stackdata_t *sd, basicblock *b,
+ stackptr curstack, int stackdepth)
+{
+ stackptr sp;
+ int i;
+ int index;
+ varinfo *v;
+
+ assert(sd->vartop + stackdepth <= sd->varcount);
+
+ b->indepth = stackdepth;
+ b->invars = DMNEW(s4, stackdepth);
+
+ /* allocate the variable indices */
+ index = (sd->vartop += stackdepth);
+
+ i = stackdepth;
+ for (sp = curstack; i--; sp = sp->prev) {
+ b->invars[i] = --index;
+ v = sd->var + index;
+ v->type = sp->type;
+ v->flags = OUTVAR;
+ }
+}
+
+
+/* stack_check_invars **********************************************************
+
+ Check the current stack against the invars of the given basic block.
+ Depth and types must match.
+
+ IN:
+ sd...........stack analysis data
+ b............block which invars to check against
+ curstack.....current stack top
+ stackdepth...current stack depth
+
+ RETURN VALUE:
+ true.........everything ok
+ false........a VerifyError has been thrown
+
+*******************************************************************************/
+
+/* XXX only if ENABLE_VERIFIER */
+static bool stack_check_invars(stackdata_t *sd, basicblock *b,
+ stackptr curstack, int stackdepth)
+{
+ int depth;
+
+ depth = b->indepth;
+
+ if (depth != stackdepth) {
+ exceptions_throw_verifyerror(sd->m, "Stack depth mismatch");
+ return false;
+ }
+
+ while (depth--) {
+ if (sd->var[b->invars[depth]].type != curstack->type) {
+ exceptions_throw_verifyerror_for_stack(sd->m,
+ sd->var[b->invars[depth]].type);
+ return false;
+ }
+ curstack = curstack->prev;
+ }
+
+ return true;
+}
+
+
+/* stack_create_instack ********************************************************
+
+ Create the instack of the current basic block.
+
+ IN:
+ sd...........stack analysis data
+
+ RETURN VALUE:
+ the current stack top at the start of the basic block.
+
+*******************************************************************************/
+
+static stackptr stack_create_instack(stackdata_t *sd)
+{
+ stackptr sp;
+ int depth;
+ int index;
+
+ if ((depth = sd->bptr->indepth) == 0)
+ return NULL;
+
+ sp = (sd->new += depth);
+
+ while (depth--) {
+ sp--;
+ index = sd->bptr->invars[depth];
+ sp->varnum = index;
+ sp->type = sd->var[index].type;
+ sp->prev = sp - 1;
+ sp->creator = NULL;
+ sp->flags = 0;
+ sp->varkind = STACKVAR;
+ }
+ sp->prev = NULL;
+
+ /* return the top of the created stack */
+ return sd->new - 1;
+}
+
+
+/* MARKREACHED marks the destination block <b> as reached. If this
+ * block has been reached before we check if stack depth and types
+ * match. Otherwise the destination block receives a copy of the
+ * current stack as its input stack.
+ *
+ * b...destination block
+ * c...current stack
+ */
+
+static bool stack_mark_reached(stackdata_t *sd, basicblock *b, stackptr curstack, int stackdepth)
+{
+ /* mark targets of backward branches */
+ if (b <= sd->bptr)
+ b->bitflags |= BBFLAG_REPLACEMENT;
+
+ if (b->flags < BBREACHED) {
+ /* b is reached for the first time. Create its instack */
+ stack_create_invars(sd, b, curstack, stackdepth);
+
+ b->flags = BBREACHED;
+ }
+ else {
+ /* b has been reached before. Check that its instack matches */
+ if (!stack_check_invars(sd, b, curstack, stackdepth))
+ return false;
+ }
+
+ return true;
+}
+
+
+/* stack_analyse ***************************************************************
+
+ Analyse_stack uses the intermediate code created by parse.c to
+ build a model of the JVM operand stack for the current method.
+
+ The following checks are performed:
+ - check for operand stack underflow (before each instruction)
+ - check for operand stack overflow (after[1] each instruction)
+ - check for matching stack depth at merging points
+ - check for matching basic types[2] at merging points
+ - check basic types for instruction input (except for BUILTIN*
+ opcodes, INVOKE* opcodes and MULTIANEWARRAY)
+
+ [1]) Checking this after the instruction should be ok. parse.c
+ counts the number of required stack slots in such a way that it is
+ only vital that we don't exceed `maxstack` at basic block
+ boundaries.
+
+ [2]) 'basic types' means the distinction between INT, LONG, FLOAT,
+ DOUBLE and ADDRESS types. Subtypes of INT and different ADDRESS
+ types are not discerned.
+
+*******************************************************************************/
bool new_stack_analyse(jitdata *jd)
{
codeinfo *code;
codegendata *cd;
registerdata *rd;
+ stackdata_t sd;
int b_count; /* basic block counter */
int b_index; /* basic block index */
int stackdepth;
stackptr curstack; /* current stack top */
- stackptr new;
stackptr copy;
int opcode; /* opcode of current instruction */
int i, j;
+ int javaindex;
int len; /* # of instructions after the current one */
bool superblockend; /* if true, no fallthrough to next block */
bool repeat; /* if true, outermost loop must run again */
bool deadcode; /* true if no live code has been reached */
- new_instruction *iptr; /* the current instruction */
- basicblock *bptr; /* the current basic block */
+ instruction *iptr; /* the current instruction */
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 coalescing_boundary;
+
+ stackptr src1, src2, src3, src4, dst1, dst2;
+
branch_target_t *table;
lookup_target_t *lookup;
#if defined(ENABLE_VERIFIER)
#if defined(ENABLE_STATISTICS)
int iteration_count; /* number of iterations of analysis */
#endif
+ int new_index; /* used to get a new var index with GET_NEW_INDEX*/
#if defined(STACK_VERBOSE)
new_show_method(jd, SHOW_PARSE);
cd = jd->cd;
rd = jd->rd;
+ /* initialize the stackdata_t struct */
+
+ sd.m = m;
+ sd.varcount = jd->varcount;
+ sd.vartop = jd->vartop;
+ sd.localcount = jd->localcount;
+ sd.var = jd->var;
+
#if defined(ENABLE_LSRA)
m->maxlifetimes = 0;
#endif
iteration_count = 0;
#endif
- last_store = DMNEW(s4 , cd->maxlocals * 5);
+ /* init jd->interface_map */
- /* initialize in-stack of first block */
+ jd->interface_map = DMNEW(interface_info, m->maxstack * 5);
+ for (i = 0; i < m->maxstack * 5; i++)
+ jd->interface_map[i].flags = UNUSED;
+
+ last_store_boundary = DMNEW(stackptr, cd->maxlocals);
+
+ /* initialize flags and invars (none) of first block */
- new = jd->new_stack;
jd->new_basicblocks[0].flags = BBREACHED;
- jd->new_basicblocks[0].instack = 0;
+ jd->new_basicblocks[0].invars = NULL;
jd->new_basicblocks[0].indepth = 0;
- /* initialize in-stack of exception handlers */
+ /* initialize invars of exception handlers */
for (i = 0; i < cd->exceptiontablelength; i++) {
- bptr = BLOCK_OF(cd->exceptiontable[i].handlerpc);
- bptr->flags = BBREACHED;
- bptr->type = BBTYPE_EXH;
- bptr->instack = new;
- bptr->indepth = 1;
- bptr->predecessorcount = CFG_UNKNOWN_PREDECESSORS;
- STACKRESET;
- NEWXSTACK;
- }
-
- /* count predecessors of each block ***************************************/
-
-#if CONDITIONAL_LOADCONST
- /* XXX move this to a separate function */
- {
- b_count = jd->new_basicblockcount;
- bptr = jd->new_basicblocks;
- for (; --b_count >= 0; bptr++) {
- if (bptr->icount == 0)
- continue;
-
- /* get the last instruction of the block */
-
- iptr = /* XXX */ (new_instruction *) bptr->iinstr + (bptr->icount - 1);
-
- switch (iptr->opc) {
- /* instruction stopping control flow */
- 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;
-
- /* conditional branches */
- 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:
- /* XXX add missing conditional branches */
- bptr[1].predecessorcount++;
- /* FALLTHROUGH */
-
- /* unconditional branch */
- case ICMD_GOTO:
- BLOCK_OF(iptr->dst.insindex)->predecessorcount++;
- break;
-
- /* switches */
- case ICMD_TABLESWITCH:
- table = iptr->dst.table;
- BLOCK_OF((table++)->insindex)->predecessorcount++;
- i = iptr->sx.s23.s3.tablehigh
- - iptr->sx.s23.s2.tablelow + 1;
- while (--i >= 0) {
- BLOCK_OF((table++)->insindex)->predecessorcount++;
- }
- break;
-
- case ICMD_LOOKUPSWITCH:
- lookup = iptr->dst.lookup;
- BLOCK_OF(iptr->sx.s23.s3.lookupdefault.insindex)->predecessorcount++;
- i = iptr->sx.s23.s2.lookupcount;
- while (--i >= 0) {
- BLOCK_OF((lookup++)->target.insindex)->predecessorcount++;
- }
- break;
-
- /* default - fall into next block */
- default:
- bptr[1].predecessorcount++;
- break;
- } /* end switch */
- } /* end basic block loop */
+ sd.bptr = BLOCK_OF(cd->exceptiontable[i].handlerpc);
+ sd.bptr->flags = BBREACHED;
+ sd.bptr->type = BBTYPE_EXH;
+ sd.bptr->predecessorcount = CFG_UNKNOWN_PREDECESSORS;
+
+ GET_NEW_VAR(sd, new_index, TYPE_ADR);
+ sd.bptr->invars = DMNEW(s4, 1);
+ sd.bptr->invars[0] = new_index;
+ sd.bptr->indepth = 1;
+ sd.var[new_index].flags |= OUTVAR;
+
+ /* mark this interface variable used */
+ jd->interface_map[0 * 5 + TYPE_ADR].flags = 0;
}
-#endif /* CONDITIONAL_LOADCONST */
/* stack analysis loop (until fixpoint reached) **************************/
/* initialize loop over basic blocks */
b_count = jd->new_basicblockcount;
- bptr = jd->new_basicblocks;
+ sd.bptr = jd->new_basicblocks;
superblockend = true;
repeat = false;
- STACKRESET;
+ curstack = NULL; stackdepth = 0;
deadcode = true;
/* iterate over basic blocks *****************************************/
- while (--b_count >= 0) {
+ for (; --b_count >= 0; ++sd.bptr) {
+
#if defined(STACK_VERBOSE)
- printf("ANALYZING BLOCK L%03d\n", bptr->nr);
+ printf("----\nANALYZING BLOCK L%03d ", sd.bptr->nr);
+ if (sd.bptr->type == BBTYPE_EXH) printf("EXH\n");
+ else if (sd.bptr->type == BBTYPE_SBR) printf("SBR\n");
+ else printf("STD\n");
#endif
- if (bptr->flags == BBDELETED) {
+ if (sd.bptr->flags == BBDELETED) {
/* This block has been deleted - do nothing. */
+
+ continue;
}
- else if (superblockend && (bptr->flags < BBREACHED)) {
+
+ if (superblockend && (sd.bptr->flags < BBREACHED)) {
/* This block has not been reached so far, and we */
/* don't fall into it, so we'll have to iterate again. */
+
repeat = true;
+ continue;
+ }
+
+ if (sd.bptr->flags > BBREACHED) {
+ /* This block is already finished. */
+
+ superblockend = true;
+ continue;
}
- else if (bptr->flags <= BBREACHED) {
+
+ /* This block has to be analysed now. */
+
+ /* XXX The rest of this block is still indented one level too */
+ /* much in order to avoid a giant diff by changing that. */
+
if (superblockend) {
- /* We know that bptr->flags == BBREACHED. */
+ /* We know that sd.bptr->flags == BBREACHED. */
/* This block has been reached before. */
- stackdepth = bptr->indepth;
+
+ stackdepth = sd.bptr->indepth;
}
- else if (bptr->flags < BBREACHED) {
+ else if (sd.bptr->flags < BBREACHED) {
/* This block is reached for the first time now */
/* by falling through from the previous block. */
- COPYCURSTACK(copy);
- bptr->instack = copy;
- bptr->indepth = stackdepth;
+ /* Create the instack (propagated). */
+
+ stack_create_invars(&sd, sd.bptr, curstack, stackdepth);
}
else {
/* This block has been reached before. now we are */
/* falling into it from the previous block. */
/* Check that stack depth is well-defined. */
- CHECK_STACK_DEPTH(bptr->indepth, stackdepth);
+
+ if (!stack_check_invars(&sd, sd.bptr, curstack, stackdepth))
+ return false;
}
+ /* reset the new pointer for allocating stackslots */
+
+ sd.new = jd->new_stack;
+
+ /* create the instack of this block */
+
+ curstack = stack_create_instack(&sd);
+
/* set up local variables for analyzing this block */
- curstack = bptr->instack;
deadcode = false;
superblockend = false;
- bptr->flags = BBFINISHED;
- len = bptr->icount;
- iptr = /* XXX */ (new_instruction *) bptr->iinstr;
- b_index = bptr - jd->new_basicblocks;
+ len = sd.bptr->icount;
+ iptr = sd.bptr->iinstr;
+ b_index = sd.bptr - jd->new_basicblocks;
+
+ /* mark the block as analysed */
+
+ sd.bptr->flags = BBFINISHED;
/* reset variables for dependency checking */
- last_pei = -1;
- last_dupx = -1;
+ coalescing_boundary = sd.new;
for( i = 0; i < cd->maxlocals; i++)
- for( j = 0; j < 5; j++)
- last_store[5 * i + j] = -1;
-
- /* XXX store the start of the block's stack representation */
+ last_store_boundary[i] = sd.new;
- bptr->stack = new;
+ /* remember the start of this block's variables */
+
+ sd.bptr->varstart = sd.vartop;
+
+#if defined(STACK_VERBOSE)
+ printf("INVARS - indices:\t\n");
+ for (i=0; i<sd.bptr->indepth; ++i) {
+ printf("%d ", sd.bptr->invars[i]);
+ }
+ printf("\n\n");
+#endif
/* iterate over ICMDs ****************************************/
while (--len >= 0) {
+
#if defined(STACK_VERBOSE)
new_show_icmd(jd, iptr, false, SHOW_PARSE); printf("\n");
for( copy = curstack; copy; copy = copy->prev ) {
- printf("%d ", copy->type);
+ printf("%2d(%d", copy->varnum, copy->type);
+ if (IS_OUTVAR(copy))
+ printf("S");
+ if (IS_PREALLOC(copy))
+ printf("A");
+ printf(") ");
}
printf("\n");
#endif
if (bte && bte->opcode == opcode) {
iptr->opc = ICMD_BUILTIN;
- iptr->flags.bits = INS_FLAG_NOCHECK;
+ iptr->flags.bits = 0;
iptr->sx.s23.s3.bte = bte;
/* iptr->line is already set */
jd->isleafmethod = false;
case ICMD_NOP:
icmd_NOP:
CLR_SX;
- NEW_OP0_0;
+ OP0_0;
break;
case ICMD_CHECKNULL:
+ coalescing_boundary = sd.new;
COUNT(count_check_null);
USE_S1(TYPE_ADR);
CLR_SX;
break;
case ICMD_RET:
+ iptr->s1.varindex =
+ jd->local_map[iptr->s1.varindex * 5 + TYPE_ADR];
+
USE_S1_LOCAL(TYPE_ADR);
CLR_SX;
CLR_DST;
- IF_NO_INTRP( rd->locals[iptr->s1.localindex][TYPE_ADR].type = TYPE_ADR; );
+#if 0
+ IF_NO_INTRP( rd->locals[iptr->s1.localindex/*XXX invalid here*/][TYPE_ADR].type = TYPE_ADR; );
+#endif
superblockend = true;
break;
case ICMD_RETURN:
COUNT(count_pcmd_return);
CLR_SX;
- NEW_OP0_0;
+ OP0_0;
superblockend = true;
break;
icmd_iconst_tail:
iptr[1].opc = ICMD_NOP;
- NEW_OP1_1(TYPE_INT, TYPE_INT);
+ OP1_1(TYPE_INT, TYPE_INT);
COUNT(count_pcmd_op);
break;
switch (iptr[1].opc) {
case ICMD_IASTORE:
iptr->opc = ICMD_IASTORECONST;
+ iptr->flags.bits |= INS_FLAG_CHECK;
break;
case ICMD_BASTORE:
iptr->opc = ICMD_BASTORECONST;
+ iptr->flags.bits |= INS_FLAG_CHECK;
break;
case ICMD_CASTORE:
iptr->opc = ICMD_CASTORECONST;
+ iptr->flags.bits |= INS_FLAG_CHECK;
break;
case ICMD_SASTORE:
iptr->opc = ICMD_SASTORECONST;
+ iptr->flags.bits |= INS_FLAG_CHECK;
break;
}
/* copy the constant to s3 */
/* XXX constval -> astoreconstval? */
iptr->sx.s23.s3.constval = iptr->sx.val.i;
- NEW_OP2_0(TYPE_ADR, TYPE_INT);
+ OP2_0(TYPE_ADR, TYPE_INT);
COUNT(count_pcmd_op);
break;
switch (iptr[1].opc) {
case ICMD_PUTSTATIC:
iptr->opc = ICMD_PUTSTATICCONST;
- NEW_OP0_0;
+ OP0_0;
break;
case ICMD_PUTFIELD:
iptr->opc = ICMD_PUTFIELDCONST;
- NEW_OP1_0(TYPE_ADR);
+ OP1_0(TYPE_ADR);
break;
}
normal_ICONST:
/* normal case of an unoptimized ICONST */
- NEW_OP0_1(TYPE_INT);
+ OP0_1(TYPE_INT);
break;
/************************** LCONST OPTIMIZATIONS **************************/
icmd_lconst_tail:
/* instruction of type LONG -> LONG */
iptr[1].opc = ICMD_NOP;
- NEW_OP1_1(TYPE_LNG, TYPE_LNG);
+ OP1_1(TYPE_LNG, TYPE_LNG);
COUNT(count_pcmd_op);
break;
iptr[1].opc = ICMD_NOP;
iptr[2].opc = ICMD_NOP;
- NEW_OP1_BRANCH(TYPE_LNG);
+ OP1_BRANCH(TYPE_LNG);
BRANCH(tbptr, copy);
COUNT(count_pcmd_bra);
COUNT(count_pcmd_op);
iptr->sx.s23.s3.constval = iptr->sx.val.l;
iptr->opc = ICMD_LASTORECONST;
- NEW_OP2_0(TYPE_ADR, TYPE_INT);
+ iptr->flags.bits |= INS_FLAG_CHECK;
+ OP2_0(TYPE_ADR, TYPE_INT);
iptr[1].opc = ICMD_NOP;
COUNT(count_pcmd_op);
normal_LCONST:
/* the normal case of an unoptimized LCONST */
- NEW_OP0_1(TYPE_LNG);
+ OP0_1(TYPE_LNG);
break;
/************************ END OF LCONST OPTIMIZATIONS *********************/
case ICMD_FCONST:
COUNT(count_pcmd_load);
- NEW_OP0_1(TYPE_FLT);
+ OP0_1(TYPE_FLT);
break;
case ICMD_DCONST:
COUNT(count_pcmd_load);
- NEW_OP0_1(TYPE_DBL);
+ OP0_1(TYPE_DBL);
break;
/************************** ACONST OPTIMIZATIONS **************************/
case ICMD_ACONST:
+ coalescing_boundary = sd.new;
COUNT(count_pcmd_load);
#if SUPPORT_CONST_STORE
IF_INTRP( goto normal_ACONST; )
/* copy the constant (NULL) to s3 */
iptr->sx.s23.s3.constval = 0;
iptr->opc = ICMD_AASTORECONST;
- NEW_OP2_0(TYPE_ADR, TYPE_INT);
+ iptr->flags.bits |= INS_FLAG_CHECK;
+ OP2_0(TYPE_ADR, TYPE_INT);
iptr[1].opc = ICMD_NOP;
COUNT(count_pcmd_op);
normal_ACONST:
#endif /* SUPPORT_CONST_STORE */
- NEW_OP0_1(TYPE_ADR);
+ OP0_1(TYPE_ADR);
break;
case ICMD_DLOAD:
case ICMD_ALOAD:
COUNT(count_load_instruction);
- i = opcode - ICMD_ILOAD;
- IF_NO_INTRP( rd->locals[iptr->s1.localindex][i].type = i; )
- NEW_LOAD(i, iptr->s1.localindex);
+ i = opcode - ICMD_ILOAD; /* type */
+
+ iptr->s1.varindex =
+ jd->local_map[iptr->s1.varindex * 5 + i];
+
+ LOAD(i, iptr->s1.varindex);
break;
/* pop 2 push 1 */
case ICMD_FALOAD:
case ICMD_DALOAD:
case ICMD_AALOAD:
+ coalescing_boundary = sd.new;
+ iptr->flags.bits |= INS_FLAG_CHECK;
COUNT(count_check_null);
COUNT(count_check_bound);
COUNT(count_pcmd_mem);
- NEW_OP2_1(TYPE_ADR, TYPE_INT, opcode - ICMD_IALOAD);
+ OP2_1(TYPE_ADR, TYPE_INT, opcode - ICMD_IALOAD);
break;
case ICMD_IALOAD:
case ICMD_BALOAD:
case ICMD_CALOAD:
case ICMD_SALOAD:
+ coalescing_boundary = sd.new;
+ iptr->flags.bits |= INS_FLAG_CHECK;
COUNT(count_check_null);
COUNT(count_check_bound);
COUNT(count_pcmd_mem);
- NEW_OP2_1(TYPE_ADR, TYPE_INT, TYPE_INT);
+ OP2_1(TYPE_ADR, TYPE_INT, TYPE_INT);
break;
/* pop 0 push 0 iinc */
case ICMD_IINC:
STATISTICS_STACKDEPTH_DISTRIBUTION(count_store_depth);
- last_store[5 * iptr->s1.localindex + TYPE_INT] = bptr->icount - len - 1;
+ last_store_boundary[iptr->s1.varindex] = sd.new;
+
+ iptr->s1.varindex =
+ jd->local_map[iptr->s1.varindex * 5 + TYPE_INT];
copy = curstack;
i = stackdepth - 1;
while (copy) {
if ((copy->varkind == LOCALVAR) &&
- (copy->varnum == iptr->s1.localindex))
+ (copy->varnum == iptr->s1.varindex))
{
- copy->varkind = TEMPVAR;
- copy->varnum = i;
+ assert(IS_LOCALVAR(copy));
+ SET_TEMPVAR(copy);
}
i--;
copy = copy->prev;
}
- iptr->dst.localindex = iptr->s1.localindex;
+ iptr->dst.varindex = iptr->s1.varindex;
break;
/* pop 1 push 0 store */
case ICMD_FSTORE:
case ICMD_DSTORE:
case ICMD_ASTORE:
- REQUIRE_1;
+ REQUIRE(1);
i = opcode - ICMD_ISTORE; /* type */
- IF_NO_INTRP( rd->locals[iptr->dst.localindex][i].type = i; )
+ javaindex = iptr->dst.varindex;
+ j = iptr->dst.varindex =
+ jd->local_map[javaindex * 5 + i];
+
#if defined(ENABLE_STATISTICS)
if (opt_stat) {
count_pcmd_store++;
- i = new - curstack;
+ i = sd.new - curstack;
if (i >= 20)
count_store_length[20]++;
else
}
#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;
+ assert(IS_LOCALVAR(copy));
+ SET_TEMPVAR(copy);
}
i--;
copy = copy->prev;
}
+ /* if the variable is already coalesced, don't bother */
+
+ if (IS_OUTVAR(curstack)
+ || (curstack->varkind == LOCALVAR
+ && curstack->varnum != j))
+ goto store_tail;
+
+ /* there is no STORE Lj while curstack is live */
+
+ if (curstack < last_store_boundary[javaindex])
+ goto assume_conflict;
+
+ /* curstack must be after the coalescing boundary */
+
+ if (curstack < coalescing_boundary)
+ goto assume_conflict;
+
+ /* there is no DEF LOCALVAR(j) while curstack is live */
+
+ copy = sd.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 */
+ assert((curstack->varkind == TEMPVAR)
+ || (curstack->varkind == UNDEFVAR));
+ assert(!IS_LOCALVAR(curstack));
+ assert(!IS_OUTVAR(curstack));
+ assert(!IS_PREALLOC(curstack));
+
+ assert(curstack->creator);
+ assert(curstack->creator->dst.varindex == curstack->varnum);
+ RELEASE_INDEX(sd, curstack);
+ curstack->varkind = LOCALVAR;
+ curstack->varnum = j;
+ curstack->creator->dst.varindex = 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;
+ assert(IS_LOCALVAR(curstack));
+ SET_TEMPVAR(curstack);
}
- 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[javaindex] = sd.new;
- NEW_STORE(opcode - ICMD_ISTORE, iptr->dst.localindex);
+ STORE(opcode - ICMD_ISTORE, j);
break;
/* pop 3 push 0 */
case ICMD_AASTORE:
+ coalescing_boundary = sd.new;
+ iptr->flags.bits |= INS_FLAG_CHECK;
COUNT(count_check_null);
COUNT(count_check_bound);
COUNT(count_pcmd_mem);
copy = curstack;
while (copy) {
+ sd.var[copy->varnum].flags |= SAVEDVAR;
+ /* in case copy->varnum is/will be a LOCALVAR */
+ /* once and set back to a non LOCALVAR */
+ /* the correct SAVEDVAR flag has to be */
+ /* remembered in copy->flags, too */
copy->flags |= SAVEDVAR;
copy = copy->prev;
}
- NEW_OP3_0(TYPE_ADR, TYPE_INT, TYPE_ADR);
+ OP3_0(TYPE_ADR, TYPE_INT, TYPE_ADR);
break;
case ICMD_LASTORE:
case ICMD_FASTORE:
case ICMD_DASTORE:
+ coalescing_boundary = sd.new;
+ iptr->flags.bits |= INS_FLAG_CHECK;
COUNT(count_check_null);
COUNT(count_check_bound);
COUNT(count_pcmd_mem);
- NEW_OP3_0(TYPE_ADR, TYPE_INT, opcode - ICMD_IASTORE);
+ OP3_0(TYPE_ADR, TYPE_INT, opcode - ICMD_IASTORE);
break;
case ICMD_IASTORE:
case ICMD_BASTORE:
case ICMD_CASTORE:
case ICMD_SASTORE:
+ coalescing_boundary = sd.new;
+ iptr->flags.bits |= INS_FLAG_CHECK;
COUNT(count_check_null);
COUNT(count_check_bound);
COUNT(count_pcmd_mem);
- NEW_OP3_0(TYPE_ADR, TYPE_INT, TYPE_INT);
+ OP3_0(TYPE_ADR, TYPE_INT, TYPE_INT);
break;
/* pop 1 push 0 */
case ICMD_POP:
#ifdef ENABLE_VERIFIER
if (opt_verify) {
- REQUIRE_1;
+ REQUIRE(1);
if (IS_2_WORD_TYPE(curstack->type))
goto throw_stack_category_error;
}
#endif
- NEW_OP1_0_ANY;
+ OP1_0_ANY;
break;
case ICMD_IRETURN:
case ICMD_FRETURN:
case ICMD_DRETURN:
case ICMD_ARETURN:
+ coalescing_boundary = sd.new;
IF_JIT( md_return_alloc(jd, curstack); )
COUNT(count_pcmd_return);
- NEW_OP1_0(opcode - ICMD_IRETURN);
+ OP1_0(opcode - ICMD_IRETURN);
superblockend = true;
break;
case ICMD_ATHROW:
+ coalescing_boundary = sd.new;
COUNT(count_check_null);
- NEW_OP1_0(TYPE_ADR);
- STACKRESET;
+ OP1_0(TYPE_ADR);
+ curstack = NULL; stackdepth = 0;
superblockend = true;
break;
case ICMD_PUTSTATIC:
+ coalescing_boundary = sd.new;
COUNT(count_pcmd_mem);
- NEW_INSTRUCTION_GET_FIELDREF(iptr, fmiref);
- NEW_OP1_0(fmiref->parseddesc.fd->type);
+ INSTRUCTION_GET_FIELDREF(iptr, fmiref);
+ OP1_0(fmiref->parseddesc.fd->type);
break;
/* pop 1 push 0 branch */
case ICMD_IFNULL:
case ICMD_IFNONNULL:
COUNT(count_pcmd_bra);
- NEW_OP1_BRANCH(TYPE_ADR);
+ OP1_BRANCH(TYPE_ADR);
BRANCH(tbptr, copy);
break;
clearing the memory or from IF_ICMPxx
optimization. */
- NEW_OP1_BRANCH(TYPE_INT);
+ OP1_BRANCH(TYPE_INT);
/* iptr->sx.val.i = 0; */
BRANCH(tbptr, copy);
break;
case ICMD_GOTO:
COUNT(count_pcmd_bra);
- NEW_OP0_BRANCH;
+ OP0_BRANCH;
BRANCH(tbptr, copy);
superblockend = true;
break;
case ICMD_TABLESWITCH:
COUNT(count_pcmd_table);
- NEW_OP1_BRANCH(TYPE_INT);
+ OP1_BRANCH(TYPE_INT);
table = iptr->dst.table;
BRANCH_TARGET(*table, tbptr, copy);
case ICMD_LOOKUPSWITCH:
COUNT(count_pcmd_table);
- NEW_OP1_BRANCH(TYPE_INT);
+ OP1_BRANCH(TYPE_INT);
BRANCH_TARGET(iptr->sx.s23.s3.lookupdefault, tbptr, copy);
case ICMD_MONITORENTER:
case ICMD_MONITOREXIT:
+ coalescing_boundary = sd.new;
COUNT(count_check_null);
- NEW_OP1_0(TYPE_ADR);
+ OP1_0(TYPE_ADR);
break;
/* pop 2 push 0 branch */
case ICMD_IF_ICMPGT:
case ICMD_IF_ICMPLE:
COUNT(count_pcmd_bra);
- NEW_OP2_BRANCH(TYPE_INT, TYPE_INT);
+ OP2_BRANCH(TYPE_INT, TYPE_INT);
BRANCH(tbptr, copy);
break;
case ICMD_IF_ACMPEQ:
case ICMD_IF_ACMPNE:
COUNT(count_pcmd_bra);
- NEW_OP2_BRANCH(TYPE_ADR, TYPE_ADR);
+ OP2_BRANCH(TYPE_ADR, TYPE_ADR);
BRANCH(tbptr, copy);
break;
/* pop 2 push 0 */
case ICMD_PUTFIELD:
+ coalescing_boundary = sd.new;
COUNT(count_check_null);
COUNT(count_pcmd_mem);
- NEW_INSTRUCTION_GET_FIELDREF(iptr, fmiref);
- NEW_OP2_0(TYPE_ADR, fmiref->parseddesc.fd->type);
+ INSTRUCTION_GET_FIELDREF(iptr, fmiref);
+ OP2_0(TYPE_ADR, fmiref->parseddesc.fd->type);
break;
case ICMD_POP2:
- REQUIRE_1;
+ REQUIRE(1);
if (!IS_2_WORD_TYPE(curstack->type)) {
/* ..., cat1 */
#ifdef ENABLE_VERIFIER
if (opt_verify) {
- REQUIRE_2;
+ REQUIRE(2);
if (IS_2_WORD_TYPE(curstack->prev->type))
goto throw_stack_category_error;
}
#endif
- NEW_OP2_0_ANY_ANY; /* pop two slots */
+ OP2_0_ANY_ANY; /* pop two slots */
}
else {
iptr->opc = ICMD_POP;
- NEW_OP1_0_ANY; /* pop one (two-word) slot */
+ OP1_0_ANY; /* pop one (two-word) slot */
}
break;
case ICMD_DUP:
#ifdef ENABLE_VERIFIER
if (opt_verify) {
- REQUIRE_1;
+ REQUIRE(1);
if (IS_2_WORD_TYPE(curstack->type))
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);
- iptr->dst.var = curstack;
- stackdepth++;
+ src1 = curstack;
+
+ COPY_UP(src1);
+ coalescing_boundary = sd.new - 1;
break;
case ICMD_DUP2:
- last_dupx = bptr->icount - len - 1;
- REQUIRE_1;
+ REQUIRE(1);
if (IS_2_WORD_TYPE(curstack->type)) {
/* ..., cat2 */
iptr->opc = ICMD_DUP;
goto icmd_DUP;
}
else {
- REQUIRE_2;
+ REQUIRE(2);
/* ..., ????, cat1 */
#ifdef ENABLE_VERIFIER
if (opt_verify) {
goto throw_stack_category_error;
}
#endif
- iptr->dst.dupslots = DMNEW(stackptr, 2 + 2);
- iptr->dst.dupslots[0] = curstack->prev; /* XXX live through */
- iptr->dst.dupslots[1] = curstack; /* XXX live through */
-
- DUP_SLOT(iptr->dst.dupslots[0]);
- iptr->dst.dupslots[2+0] = curstack;
- DUP_SLOT(iptr->dst.dupslots[1]);
- iptr->dst.dupslots[2+1] = curstack;
- stackdepth += 2;
+ src1 = curstack->prev;
+ src2 = curstack;
+
+ COPY_UP(src1); iptr++; len--;
+ COPY_UP(src2);
+
+ coalescing_boundary = sd.new;
}
break;
case ICMD_DUP_X1:
#ifdef ENABLE_VERIFIER
if (opt_verify) {
- REQUIRE_2;
+ REQUIRE(2);
if (IS_2_WORD_TYPE(curstack->type) ||
IS_2_WORD_TYPE(curstack->prev->type))
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[0] = curstack->prev;
- iptr->dst.dupslots[1] = curstack;
+ src1 = curstack->prev;
+ src2 = curstack;
POPANY; POPANY;
+ stackdepth -= 2;
- DUP_SLOT(iptr->dst.dupslots[1]);
- iptr->dst.dupslots[2+0] = curstack;
- DUP_SLOT(iptr->dst.dupslots[0]);
- iptr->dst.dupslots[2+1] = curstack;
- DUP_SLOT(iptr->dst.dupslots[1]);
- iptr->dst.dupslots[2+2] = curstack;
- stackdepth++;
+ DUP_SLOT(src2); dst1 = curstack; stackdepth++;
+
+ MOVE_UP(src1); iptr++; len--;
+ MOVE_UP(src2); iptr++; len--;
+
+ COPY_DOWN(curstack, dst1);
+
+ coalescing_boundary = sd.new;
break;
case ICMD_DUP2_X1:
- last_dupx = bptr->icount - len - 1;
- REQUIRE_2;
+ REQUIRE(2);
if (IS_2_WORD_TYPE(curstack->type)) {
/* ..., ????, cat2 */
#ifdef ENABLE_VERIFIER
/* ..., ????, cat1 */
#ifdef ENABLE_VERIFIER
if (opt_verify) {
- REQUIRE_3;
+ REQUIRE(3);
if (IS_2_WORD_TYPE(curstack->prev->type)
|| IS_2_WORD_TYPE(curstack->prev->prev->type))
goto throw_stack_category_error;
#endif
icmd_DUP2_X1:
- iptr->dst.dupslots = DMNEW(stackptr, 3 + 5);
- iptr->dst.dupslots[0] = curstack->prev->prev;
- iptr->dst.dupslots[1] = curstack->prev;
- iptr->dst.dupslots[2] = curstack;
+ src1 = curstack->prev->prev;
+ src2 = curstack->prev;
+ src3 = curstack;
POPANY; POPANY; POPANY;
+ stackdepth -= 3;
+
+ DUP_SLOT(src2); dst1 = curstack; stackdepth++;
+ DUP_SLOT(src3); dst2 = curstack; stackdepth++;
- DUP_SLOT(iptr->dst.dupslots[1]);
- iptr->dst.dupslots[3+0] = curstack;
- DUP_SLOT(iptr->dst.dupslots[2]);
- iptr->dst.dupslots[3+1] = curstack;
- DUP_SLOT(iptr->dst.dupslots[0]);
- iptr->dst.dupslots[3+2] = curstack;
- DUP_SLOT(iptr->dst.dupslots[1]);
- iptr->dst.dupslots[3+3] = curstack;
- DUP_SLOT(iptr->dst.dupslots[2]);
- iptr->dst.dupslots[3+4] = curstack;
- stackdepth += 2;
+ MOVE_UP(src1); iptr++; len--;
+ MOVE_UP(src2); iptr++; len--;
+ MOVE_UP(src3); iptr++; len--;
+
+ COPY_DOWN(curstack, dst2); iptr++; len--;
+ COPY_DOWN(curstack->prev, dst1);
+
+ coalescing_boundary = sd.new;
}
break;
/* pop 3 push 4 dup */
case ICMD_DUP_X2:
- last_dupx = bptr->icount - len - 1;
- REQUIRE_2;
+ REQUIRE(2);
if (IS_2_WORD_TYPE(curstack->prev->type)) {
/* ..., cat2, ???? */
#ifdef ENABLE_VERIFIER
/* ..., cat1, ???? */
#ifdef ENABLE_VERIFIER
if (opt_verify) {
- REQUIRE_3;
+ REQUIRE(3);
if (IS_2_WORD_TYPE(curstack->type)
|| IS_2_WORD_TYPE(curstack->prev->prev->type))
goto throw_stack_category_error;
}
#endif
icmd_DUP_X2:
- iptr->dst.dupslots = DMNEW(stackptr, 3 + 4);
- iptr->dst.dupslots[0] = curstack->prev->prev;
- iptr->dst.dupslots[1] = curstack->prev;
- iptr->dst.dupslots[2] = curstack;
+ src1 = curstack->prev->prev;
+ src2 = curstack->prev;
+ src3 = curstack;
POPANY; POPANY; POPANY;
+ stackdepth -= 3;
- DUP_SLOT(iptr->dst.dupslots[2]);
- iptr->dst.dupslots[3+0] = curstack;
- DUP_SLOT(iptr->dst.dupslots[0]);
- iptr->dst.dupslots[3+1] = curstack;
- DUP_SLOT(iptr->dst.dupslots[1]);
- iptr->dst.dupslots[3+2] = curstack;
- DUP_SLOT(iptr->dst.dupslots[2]);
- iptr->dst.dupslots[3+3] = curstack;
- stackdepth++;
+ DUP_SLOT(src3); dst1 = curstack; stackdepth++;
+
+ MOVE_UP(src1); iptr++; len--;
+ MOVE_UP(src2); iptr++; len--;
+ MOVE_UP(src3); iptr++; len--;
+
+ COPY_DOWN(curstack, dst1);
+
+ coalescing_boundary = sd.new;
}
break;
case ICMD_DUP2_X2:
- last_dupx = bptr->icount - len - 1;
- REQUIRE_2;
+ REQUIRE(2);
if (IS_2_WORD_TYPE(curstack->type)) {
/* ..., ????, cat2 */
if (IS_2_WORD_TYPE(curstack->prev->type)) {
/* ..., cat1, cat2 */
#ifdef ENABLE_VERIFIER
if (opt_verify) {
- REQUIRE_3;
+ REQUIRE(3);
if (IS_2_WORD_TYPE(curstack->prev->prev->type))
goto throw_stack_category_error;
}
}
}
- REQUIRE_3;
+ REQUIRE(3);
/* ..., ????, ????, cat1 */
if (IS_2_WORD_TYPE(curstack->prev->prev->type)) {
/* ..., cat1, ????, cat1 */
#ifdef ENABLE_VERIFIER
if (opt_verify) {
- REQUIRE_4;
+ REQUIRE(4);
if (IS_2_WORD_TYPE(curstack->prev->type)
|| IS_2_WORD_TYPE(curstack->prev->prev->prev->type))
goto throw_stack_category_error;
}
#endif
- iptr->dst.dupslots = DMNEW(stackptr, 4 + 6);
- iptr->dst.dupslots[0] = curstack->prev->prev->prev;
- iptr->dst.dupslots[1] = curstack->prev->prev;
- iptr->dst.dupslots[2] = curstack->prev;
- iptr->dst.dupslots[3] = curstack;
+
+ src1 = curstack->prev->prev->prev;
+ src2 = curstack->prev->prev;
+ src3 = curstack->prev;
+ src4 = curstack;
POPANY; POPANY; POPANY; POPANY;
+ stackdepth -= 4;
+
+ DUP_SLOT(src3); dst1 = curstack; stackdepth++;
+ DUP_SLOT(src4); dst2 = curstack; stackdepth++;
- DUP_SLOT(iptr->dst.dupslots[2]);
- iptr->dst.dupslots[4+0] = curstack;
- DUP_SLOT(iptr->dst.dupslots[3]);
- iptr->dst.dupslots[4+1] = curstack;
- DUP_SLOT(iptr->dst.dupslots[0]);
- iptr->dst.dupslots[4+2] = curstack;
- DUP_SLOT(iptr->dst.dupslots[1]);
- iptr->dst.dupslots[4+3] = curstack;
- DUP_SLOT(iptr->dst.dupslots[2]);
- iptr->dst.dupslots[4+4] = curstack;
- DUP_SLOT(iptr->dst.dupslots[3]);
- iptr->dst.dupslots[4+5] = curstack;
- stackdepth += 2;
+ MOVE_UP(src1); iptr++; len--;
+ MOVE_UP(src2); iptr++; len--;
+ MOVE_UP(src3); iptr++; len--;
+ MOVE_UP(src4); iptr++; len--;
+
+ COPY_DOWN(curstack, dst2); iptr++; len--;
+ COPY_DOWN(curstack->prev, dst1);
+
+ coalescing_boundary = sd.new;
}
break;
/* pop 2 push 2 swap */
case ICMD_SWAP:
- last_dupx = bptr->icount - len - 1;
#ifdef ENABLE_VERIFIER
if (opt_verify) {
- REQUIRE_2;
+ REQUIRE(2);
if (IS_2_WORD_TYPE(curstack->type)
|| IS_2_WORD_TYPE(curstack->prev->type))
goto throw_stack_category_error;
}
#endif
- iptr->dst.dupslots = DMNEW(stackptr, 2 + 2);
- iptr->dst.dupslots[0] = curstack->prev;
- iptr->dst.dupslots[1] = curstack;
+
+ src1 = curstack->prev;
+ src2 = curstack;
POPANY; POPANY;
+ stackdepth -= 2;
+
+ MOVE_UP(src2); iptr++; len--;
+ MOVE_UP(src1);
- DUP_SLOT(iptr->dst.dupslots[1]);
- iptr->dst.dupslots[2+0] = curstack;
- DUP_SLOT(iptr->dst.dupslots[0]);
- iptr->dst.dupslots[2+1] = curstack;
+ coalescing_boundary = sd.new;
break;
/* pop 2 push 1 */
case ICMD_IDIV:
case ICMD_IREM:
+ coalescing_boundary = sd.new;
#if !SUPPORT_DIVISION
bte = iptr->sx.s23.s3.bte;
md = bte->md;
copy = curstack;
while (copy) {
+ sd.var[copy->varnum].flags |= SAVEDVAR;
copy->flags |= SAVEDVAR;
copy = copy->prev;
}
case ICMD_IOR:
case ICMD_IXOR:
COUNT(count_pcmd_op);
- NEW_OP2_1(TYPE_INT, TYPE_INT, TYPE_INT);
+ OP2_1(TYPE_INT, TYPE_INT, TYPE_INT);
break;
case ICMD_LDIV:
case ICMD_LREM:
+ coalescing_boundary = sd.new;
#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
bte = iptr->sx.s23.s3.bte;
md = bte->md;
copy = curstack;
while (copy) {
+ sd.var[copy->varnum].flags |= SAVEDVAR;
copy->flags |= SAVEDVAR;
copy = copy->prev;
}
case ICMD_LXOR:
#endif /* SUPPORT_LONG_LOGICAL */
COUNT(count_pcmd_op);
- NEW_OP2_1(TYPE_LNG, TYPE_LNG, TYPE_LNG);
+ OP2_1(TYPE_LNG, TYPE_LNG, TYPE_LNG);
break;
case ICMD_LSHL:
case ICMD_LSHR:
case ICMD_LUSHR:
COUNT(count_pcmd_op);
- NEW_OP2_1(TYPE_LNG, TYPE_INT, TYPE_LNG);
+ OP2_1(TYPE_LNG, TYPE_INT, TYPE_LNG);
break;
case ICMD_FADD:
case ICMD_FDIV:
case ICMD_FREM:
COUNT(count_pcmd_op);
- NEW_OP2_1(TYPE_FLT, TYPE_FLT, TYPE_FLT);
+ OP2_1(TYPE_FLT, TYPE_FLT, TYPE_FLT);
break;
case ICMD_DADD:
case ICMD_DDIV:
case ICMD_DREM:
COUNT(count_pcmd_op);
- NEW_OP2_1(TYPE_DBL, TYPE_DBL, TYPE_DBL);
+ OP2_1(TYPE_DBL, TYPE_DBL, TYPE_DBL);
break;
case ICMD_LCMP:
iptr->dst.insindex = iptr[1].dst.insindex;
iptr[1].opc = ICMD_NOP;
- NEW_OP2_BRANCH(TYPE_LNG, TYPE_LNG);
+ OP2_BRANCH(TYPE_LNG, TYPE_LNG);
BRANCH(tbptr, copy);
COUNT(count_pcmd_bra);
break;
normal_LCMP:
#endif /* SUPPORT_LONG_CMP_CONST */
- NEW_OP2_1(TYPE_LNG, TYPE_LNG, TYPE_INT);
+ OP2_1(TYPE_LNG, TYPE_LNG, TYPE_INT);
break;
/* XXX why is this deactivated? */
iptr->dst.insindex = iptr[1].dst.insindex;
iptr[1].opc = ICMD_NOP;
- NEW_OP2_BRANCH(TYPE_FLT, TYPE_FLT);
+ OP2_BRANCH(TYPE_FLT, TYPE_FLT);
BRANCH(tbptr, copy);
COUNT(count_pcmd_bra);
iptr->dst.insindex = iptr[1].dst.insindex;
iptr[1].opc = ICMD_NOP;
- NEW_OP2_BRANCH(TYPE_FLT, TYPE_FLT);
+ OP2_BRANCH(TYPE_FLT, TYPE_FLT);
BRANCH(tbptr, copy);
COUNT(count_pcmd_bra);
break;
normal_FCMPG:
- NEW_OP2_1(TYPE_FLT, TYPE_FLT, TYPE_INT);
+ OP2_1(TYPE_FLT, TYPE_FLT, TYPE_INT);
break;
case ICMD_DCMPL:
iptr->dst.insindex = iptr[1].dst.insindex;
iptr[1].opc = ICMD_NOP;
- NEW_OP2_BRANCH(TYPE_DBL, TYPE_DBL);
+ OP2_BRANCH(TYPE_DBL, TYPE_DBL);
BRANCH(tbptr, copy);
COUNT(count_pcmd_bra);
iptr->dst.insindex = iptr[1].dst.insindex;
iptr[1].opc = ICMD_NOP;
- NEW_OP2_BRANCH(TYPE_DBL, TYPE_DBL);
+ OP2_BRANCH(TYPE_DBL, TYPE_DBL);
BRANCH(tbptr, copy);
COUNT(count_pcmd_bra);
break;
normal_DCMPG:
- NEW_OP2_1(TYPE_DBL, TYPE_DBL, TYPE_INT);
+ OP2_1(TYPE_DBL, TYPE_DBL, TYPE_INT);
break;
#else
case ICMD_FCMPL:
case ICMD_FCMPG:
COUNT(count_pcmd_op);
- NEW_OP2_1(TYPE_FLT, TYPE_FLT, TYPE_INT);
+ OP2_1(TYPE_FLT, TYPE_FLT, TYPE_INT);
break;
case ICMD_DCMPL:
case ICMD_DCMPG:
COUNT(count_pcmd_op);
- NEW_OP2_1(TYPE_DBL, TYPE_DBL, TYPE_INT);
+ OP2_1(TYPE_DBL, TYPE_DBL, TYPE_INT);
break;
#endif
case ICMD_INT2CHAR:
case ICMD_INT2SHORT:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_INT, TYPE_INT);
+ OP1_1(TYPE_INT, TYPE_INT);
break;
case ICMD_LNEG:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_LNG, TYPE_LNG);
+ OP1_1(TYPE_LNG, TYPE_LNG);
break;
case ICMD_FNEG:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_FLT, TYPE_FLT);
+ OP1_1(TYPE_FLT, TYPE_FLT);
break;
case ICMD_DNEG:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_DBL, TYPE_DBL);
+ OP1_1(TYPE_DBL, TYPE_DBL);
break;
case ICMD_I2L:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_INT, TYPE_LNG);
+ OP1_1(TYPE_INT, TYPE_LNG);
break;
case ICMD_I2F:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_INT, TYPE_FLT);
+ OP1_1(TYPE_INT, TYPE_FLT);
break;
case ICMD_I2D:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_INT, TYPE_DBL);
+ OP1_1(TYPE_INT, TYPE_DBL);
break;
case ICMD_L2I:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_LNG, TYPE_INT);
+ OP1_1(TYPE_LNG, TYPE_INT);
break;
case ICMD_L2F:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_LNG, TYPE_FLT);
+ OP1_1(TYPE_LNG, TYPE_FLT);
break;
case ICMD_L2D:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_LNG, TYPE_DBL);
+ OP1_1(TYPE_LNG, TYPE_DBL);
break;
case ICMD_F2I:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_FLT, TYPE_INT);
+ OP1_1(TYPE_FLT, TYPE_INT);
break;
case ICMD_F2L:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_FLT, TYPE_LNG);
+ OP1_1(TYPE_FLT, TYPE_LNG);
break;
case ICMD_F2D:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_FLT, TYPE_DBL);
+ OP1_1(TYPE_FLT, TYPE_DBL);
break;
case ICMD_D2I:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_DBL, TYPE_INT);
+ OP1_1(TYPE_DBL, TYPE_INT);
break;
case ICMD_D2L:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_DBL, TYPE_LNG);
+ OP1_1(TYPE_DBL, TYPE_LNG);
break;
case ICMD_D2F:
COUNT(count_pcmd_op);
- NEW_OP1_1(TYPE_DBL, TYPE_FLT);
+ OP1_1(TYPE_DBL, TYPE_FLT);
break;
case ICMD_CHECKCAST:
+ coalescing_boundary = sd.new;
if (iptr->flags.bits & INS_FLAG_ARRAY) {
/* array type cast-check */
copy = curstack;
while (copy) {
+ sd.var[copy->varnum].flags |= SAVEDVAR;
copy->flags |= SAVEDVAR;
copy = copy->prev;
}
}
- NEW_OP1_1(TYPE_ADR, TYPE_ADR);
+ OP1_1(TYPE_ADR, TYPE_ADR);
break;
case ICMD_INSTANCEOF:
case ICMD_ARRAYLENGTH:
- NEW_OP1_1(TYPE_ADR, TYPE_INT);
+ coalescing_boundary = sd.new;
+ OP1_1(TYPE_ADR, TYPE_INT);
break;
case ICMD_NEWARRAY:
case ICMD_ANEWARRAY:
- NEW_OP1_1(TYPE_INT, TYPE_ADR);
+ coalescing_boundary = sd.new;
+ OP1_1(TYPE_INT, TYPE_ADR);
break;
case ICMD_GETFIELD:
+ coalescing_boundary = sd.new;
COUNT(count_check_null);
COUNT(count_pcmd_mem);
- NEW_INSTRUCTION_GET_FIELDREF(iptr, fmiref);
- NEW_OP1_1(TYPE_ADR, fmiref->parseddesc.fd->type);
+ INSTRUCTION_GET_FIELDREF(iptr, fmiref);
+ OP1_1(TYPE_ADR, fmiref->parseddesc.fd->type);
break;
/* pop 0 push 1 */
case ICMD_GETSTATIC:
+ coalescing_boundary = sd.new;
COUNT(count_pcmd_mem);
- NEW_INSTRUCTION_GET_FIELDREF(iptr, fmiref);
- NEW_OP0_1(fmiref->parseddesc.fd->type);
+ INSTRUCTION_GET_FIELDREF(iptr, fmiref);
+ OP0_1(fmiref->parseddesc.fd->type);
break;
case ICMD_NEW:
- NEW_OP0_1(TYPE_ADR);
+ coalescing_boundary = sd.new;
+ OP0_1(TYPE_ADR);
break;
case ICMD_JSR:
- NEW_OP0_1(TYPE_ADR);
+ OP0_1(TYPE_ADR);
BRANCH_TARGET(iptr->sx.s23.s3.jsrtarget, tbptr, copy);
/* We need to check for overflow right here because
* the pushed value is poped afterwards */
- NEW_CHECKOVERFLOW;
+ CHECKOVERFLOW;
/* calculate stack after return */
POPANY;
/* pop many push any */
case ICMD_BUILTIN:
-#if defined(USEBUILTINTABLE)
icmd_BUILTIN:
-#endif
bte = iptr->sx.s23.s3.bte;
md = bte->md;
goto _callhandling;
case ICMD_INVOKEVIRTUAL:
case ICMD_INVOKEINTERFACE:
COUNT(count_pcmd_met);
- NEW_INSTRUCTION_GET_METHODDESC(iptr, md);
+
+ /* Check for functions to replace with builtin
+ * functions. */
+
+ if (builtintable_replace_function(iptr))
+ goto icmd_BUILTIN;
+
+ INSTRUCTION_GET_METHODDESC(iptr, md);
/* XXX resurrect this COUNT? */
/* if (lm->flags & ACC_STATIC) */
/* {COUNT(count_check_null);} */
_callhandling:
- last_pei = bptr->icount - len - 1;
+ coalescing_boundary = sd.new;
i = md->paramcount;
/* XXX optimize for <= 2 args */
/* XXX not for ICMD_BUILTIN */
iptr->s1.argcount = stackdepth;
- iptr->sx.s23.s2.args = DMNEW(stackptr, stackdepth);
+ iptr->sx.s23.s2.args = DMNEW(s4, stackdepth);
copy = curstack;
for (i-- ; i >= 0; i--) {
- iptr->sx.s23.s2.args[i] = copy;
+ iptr->sx.s23.s2.args[i] = copy->varnum;
+
+ /* do not change STACKVARs or LOCALVARS to ARGVAR*/
+ /* -> won't help anyway */
+ if (!(IS_OUTVAR(copy) || IS_LOCALVAR(copy))) {
#if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
- /* If we pass float arguments in integer argument registers, we
- * are not allowed to precolor them here. Floats have to be moved
- * to this regs explicitly in codegen().
- * Only arguments that are passed by stack anyway can be precolored
- * (michi 2005/07/24) */
- if (!(copy->flags & SAVEDVAR) &&
- (!IS_FLT_DBL_TYPE(copy->type) || md->params[i].inmemory)) {
+ /* If we pass float arguments in integer argument registers, we
+ * are not allowed to precolor them here. Floats have to be moved
+ * to this regs explicitly in codegen().
+ * Only arguments that are passed by stack anyway can be precolored
+ * (michi 2005/07/24) */
+ if (!(sd.var[copy->varnum].flags & SAVEDVAR) &&
+ (!IS_FLT_DBL_TYPE(copy->type)
+ || md->params[i].inmemory)) {
#else
- if (!(copy->flags & SAVEDVAR)) {
+ if (!(sd.var[copy->varnum].flags & SAVEDVAR)) {
#endif
- copy->varkind = ARGVAR;
- copy->varnum = i;
+
+ SET_PREALLOC(copy);
#if defined(ENABLE_INTRP)
if (!opt_intrp) {
#endif
if (md->params[i].inmemory) {
- copy->flags = INMEMORY;
- copy->regoff = md->params[i].regoff;
+ sd.var[copy->varnum].regoff =
+ md->params[i].regoff;
+ sd.var[copy->varnum].flags |=
+ INMEMORY;
}
else {
- copy->flags = 0;
if (IS_FLT_DBL_TYPE(copy->type)) {
#if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
assert(0); /* XXX is this assert ok? */
#else
- copy->regoff =
- rd->argfltregs[md->params[i].regoff];
+ sd.var[copy->varnum].regoff =
+ rd->argfltregs[md->params[i].regoff];
#endif /* SUPPORT_PASS_FLOATARGS_IN_INTREGS */
}
else {
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
if (IS_2_WORD_TYPE(copy->type))
- copy->regoff = PACK_REGS(
- rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
- rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
+ sd.var[copy->varnum].regoff =
+ PACK_REGS( rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
+ rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
+
else
#endif /* SUPPORT_COMBINE_INTEGER_REGISTERS */
- copy->regoff =
- rd->argintregs[md->params[i].regoff];
+ sd.var[copy->varnum].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 */
+ /* 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;
+ SET_TEMPVAR(copy);
+ iptr->sx.s23.s2.args[i++] = copy->varnum;
+ sd.var[copy->varnum].flags |= SAVEDVAR;
copy = copy->prev;
}
/* push the return value */
if (md->returntype.type != TYPE_VOID) {
- NEW_DST(md->returntype.type, stackdepth);
+ GET_NEW_VAR(sd, new_index, md->returntype.type);
+ DST(md->returntype.type, new_index);
stackdepth++;
}
break;
break;
case ICMD_MULTIANEWARRAY:
+ coalescing_boundary = sd.new;
if (rd->argintreguse < 3)
rd->argintreguse = 3;
REQUIRE(i);
- iptr->sx.s23.s2.args = DMNEW(stackptr, i);
+ iptr->sx.s23.s2.args = DMNEW(s4, i);
#if defined(SPECIALMEMUSE)
# if defined(__DARWIN__)
- if (rd->memuse < (i + INT_ARG_CNT + LA_SIZE_IN_POINTERS))
+ 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_SIZE_IN_POINTERS + 3))
#endif
copy = curstack;
while (--i >= 0) {
- /* check INT type here? Currently typecheck does this. */
- iptr->sx.s23.s2.args[i] = copy;
- if (!(copy->flags & SAVEDVAR)) {
+ /* check INT type here? Currently typecheck does this. */
+ iptr->sx.s23.s2.args[i] = copy->varnum;
+ if (!(sd.var[copy->varnum].flags & SAVEDVAR)
+ && (!IS_OUTVAR(copy))
+ && (!IS_LOCALVAR(copy)) ) {
copy->varkind = ARGVAR;
- copy->varnum = i + INT_ARG_CNT;
- copy->flags |= INMEMORY;
+ sd.var[copy->varnum].flags |=
+ INMEMORY & PREALLOC;
#if defined(SPECIALMEMUSE)
# if defined(__DARWIN__)
- copy->regoff = i + LA_SIZE_IN_POINTERS + INT_ARG_CNT;
+ sd.var[copy->varnum].regoff = i +
+ LA_SIZE_IN_POINTERS + INT_ARG_CNT;
# else
- copy->regoff = i + LA_SIZE_IN_POINTERS + 3;
+ sd.var[copy->varnum].regoff = i +
+ LA_SIZE_IN_POINTERS + 3;
# endif
#else
# if defined(__I386__)
- copy->regoff = i + 3;
+ sd.var[copy->varnum].regoff = i + 3;
# elif defined(__MIPS__) && SIZEOF_VOID_P == 4
- copy->regoff = i + 2;
+ sd.var[copy->varnum].regoff = i + 2;
# else
- copy->regoff = i;
+ sd.var[copy->varnum].regoff = i;
# endif /* defined(__I386__) */
#endif /* defined(SPECIALMEMUSE) */
}
copy = copy->prev;
}
while (copy) {
- copy->flags |= SAVEDVAR;
+ sd.var[copy->varnum].flags |= SAVEDVAR;
copy = copy->prev;
}
while (--i >= 0) {
POPANY;
}
- NEW_DST(TYPE_ADR, stackdepth);
+ GET_NEW_VAR(sd, new_index, TYPE_ADR);
+ DST(TYPE_ADR, new_index);
stackdepth++;
break;
return false;
} /* switch */
- NEW_CHECKOVERFLOW;
+ CHECKOVERFLOW;
iptr++;
} /* while instructions */
- /* set out-stack of block */
-
- bptr->outstack = curstack;
- bptr->outdepth = stackdepth;
-
/* stack slots at basic block end become interfaces */
+ sd.bptr->outdepth = stackdepth;
+ sd.bptr->outvars = DMNEW(s4, stackdepth);
+
i = stackdepth - 1;
for (copy = curstack; copy; i--, copy = copy->prev) {
- if ((copy->varkind == STACKVAR) && (copy->varnum > i))
- copy->varkind = TEMPVAR;
+ varinfo *v;
+
+ /* with the new vars rd->interfaces will be removed */
+ /* and all in and outvars have to be STACKVARS! */
+ /* in the moment i.e. SWAP with in and out vars can */
+ /* create an unresolvable conflict */
+
+ SET_TEMPVAR(copy);
+
+ v = sd.var + copy->varnum;
+ v->flags |= OUTVAR;
+
+ if (jd->interface_map[i*5 + copy->type].flags == UNUSED) {
+ /* no interface var until now for this depth and */
+ /* type */
+ jd->interface_map[i*5 + copy->type].flags = v->flags;
+ }
else {
- copy->varkind = STACKVAR;
- copy->varnum = i;
+ jd->interface_map[i*5 + copy->type].flags |= v->flags;
}
- IF_NO_INTRP(
- rd->interfaces[i][copy->type].type = copy->type;
- rd->interfaces[i][copy->type].flags |= copy->flags;
- );
+
+ sd.bptr->outvars[i] = copy->varnum;
}
/* check if interface slots at basic block begin must be saved */
-
IF_NO_INTRP(
- i = bptr->indepth - 1;
- for (copy = bptr->instack; copy; i--, copy = copy->prev) {
- rd->interfaces[i][copy->type].type = copy->type;
- if (copy->varkind == STACKVAR) {
- if (copy->flags & SAVEDVAR)
- rd->interfaces[i][copy->type].flags |= SAVEDVAR;
+ for (i=0; i<sd.bptr->indepth; ++i) {
+ varinfo *v = sd.var + sd.bptr->invars[i];
+
+ if (jd->interface_map[i*5 + v->type].flags == UNUSED) {
+ /* no interface var until now for this depth and */
+ /* type */
+ jd->interface_map[i*5 + v->type].flags = v->flags;
+ }
+ else {
+ jd->interface_map[i*5 + v->type].flags |= v->flags;
}
}
);
- } /* if */
- else
- superblockend = true;
+ /* store the number of this block's variables */
+
+ sd.bptr->varcount = sd.vartop - sd.bptr->varstart;
+
+#if defined(STACK_VERBOSE)
+ printf("OUTVARS\n");
+ /* XXX print something useful here */
+ printf("\n");
+#endif
+
+ } /* for blocks */
- bptr++;
- } /* while blocks */
} while (repeat && !deadcode);
/* gather statistics *****************************************************/
count_javainstr += jd->new_instructioncount;
if (jd->new_stackcount > count_upper_bound_new_stack)
count_upper_bound_new_stack = jd->new_stackcount;
- if ((new - jd->new_stack) > count_max_new_stack)
- count_max_new_stack = (new - jd->new_stack);
+ if ((sd.new - jd->new_stack) > count_max_new_stack)
+ count_max_new_stack = (sd.new - jd->new_stack);
b_count = jd->new_basicblockcount;
- bptr = jd->new_basicblocks;
+ sd.bptr = jd->new_basicblocks;
while (--b_count >= 0) {
- if (bptr->flags > BBREACHED) {
- if (bptr->indepth >= 10)
+ if (sd.bptr->flags > BBREACHED) {
+ if (sd.bptr->indepth >= 10)
count_block_stack[10]++;
else
- count_block_stack[bptr->indepth]++;
- len = bptr->icount;
+ count_block_stack[sd.bptr->indepth]++;
+ len = sd.bptr->icount;
if (len < 10)
count_block_size_distribution[len]++;
else if (len <= 12)
else
count_block_size_distribution[17]++;
}
- bptr++;
+ sd.bptr++;
}
if (iteration_count == 1)
#endif
}
-bool stack_analyse(jitdata *jd)
-{
- methodinfo *m;
- codeinfo *code;
- codegendata *cd;
- registerdata *rd;
- int b_count;
- int b_index;
- int stackdepth;
- stackptr curstack;
- stackptr new;
- stackptr copy;
- int opcode, i, j, len, loops;
- int superblockend, repeat, deadcode;
- instruction *iptr;
- basicblock *bptr;
- basicblock *tbptr;
- s4 *s4ptr;
- void **tptr;
- s4 *last_store;/* instruction index of last XSTORE */
- /* [ local_index * 5 + type ] */
- s4 last_pei; /* instruction index of last possible exception */
- /* used for conflict resolution for copy */
- /* elimination (XLOAD, IINC, XSTORE) */
- s4 last_dupx;
-#if defined(ENABLE_VERIFIER)
- int expectedtype; /* used by CHECK_BASIC_TYPE */
-#endif
-
- builtintable_entry *bte;
- methoddesc *md;
-
- /* get required compiler data */
-
- m = jd->m;
- code = jd->code;
- cd = jd->cd;
- rd = jd->rd;
-
- last_store = DMNEW(s4 , cd->maxlocals * 5);
-
- new = m->stack;
- loops = 0;
- m->basicblocks[0].flags = BBREACHED;
- m->basicblocks[0].instack = 0;
- m->basicblocks[0].indepth = 0;
-
- for (i = 0; i < cd->exceptiontablelength; i++) {
- bptr = &m->basicblocks[m->basicblockindex[cd->exceptiontable[i].handlerpc]];
- bptr->flags = BBREACHED;
- bptr->type = BBTYPE_EXH;
- bptr->instack = new;
- bptr->indepth = 1;
- bptr->predecessorcount = CFG_UNKNOWN_PREDECESSORS;
- STACKRESET;
- NEWXSTACK;
- }
-
- do {
- loops++;
- b_count = m->basicblockcount;
- bptr = m->basicblocks;
- superblockend = true;
- repeat = false;
- STACKRESET;
- deadcode = true;
-
- while (--b_count >= 0) {
- if (bptr->flags == BBDELETED) {
- /* do nothing */
- }
- else if (superblockend && (bptr->flags < BBREACHED)) {
- repeat = true;
- }
- else if (bptr->flags <= BBREACHED) {
- if (superblockend) {
- stackdepth = bptr->indepth;
- }
- else if (bptr->flags < BBREACHED) {
- COPYCURSTACK(copy);
- bptr->instack = copy;
- bptr->indepth = stackdepth;
- }
- else {
- CHECK_STACK_DEPTH(bptr->indepth, stackdepth);
- }
-
- curstack = bptr->instack;
- deadcode = false;
- superblockend = false;
- bptr->flags = BBFINISHED;
- len = bptr->icount;
- iptr = bptr->iinstr;
- b_index = bptr - m->basicblocks;
-
- last_pei = -1;
- last_dupx = -1;
- for( i = 0; i < cd->maxlocals; i++)
- for( j = 0; j < 5; j++)
- last_store[5 * i + j] = -1;
-
- bptr->stack = new;
-
- 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
- bte = builtintable_get_automatic(opcode);
-
- if (bte && bte->opcode == opcode) {
- iptr->opc = ICMD_BUILTIN;
- iptr->op1 = false; /* don't check for exception */
- iptr->val.a = bte;
- jd->isleafmethod = false;
- goto builtin;
- }
-# if defined(ENABLE_INTRP)
- }
-# endif
-#endif /* defined(USEBUILTINTABLE) */
-
- /* this is the main switch */
-
- switch (opcode) {
-
- /* pop 0 push 0 */
-
- case ICMD_CHECKNULL:
- COUNT(count_check_null);
- case ICMD_NOP:
- SETDST;
- break;
-
- case ICMD_RET:
-#if defined(ENABLE_INTRP)
- if (!opt_intrp)
-#endif
- rd->locals[iptr->op1][TYPE_ADR].type = TYPE_ADR;
- case ICMD_RETURN:
- COUNT(count_pcmd_return);
- SETDST;
- superblockend = true;
- break;
-
- /* pop 0 push 1 const */
-
- case ICMD_ICONST:
- COUNT(count_pcmd_load);
- if (len > 0) {
- switch (iptr[1].opc) {
- case ICMD_IADD:
- iptr[0].opc = ICMD_IADDCONST;
- icmd_iconst_tail:
- iptr[1].opc = ICMD_NOP;
- OP1_1(TYPE_INT, TYPE_INT);
- COUNT(count_pcmd_op);
- break;
- case ICMD_ISUB:
- iptr[0].opc = ICMD_ISUBCONST;
- goto icmd_iconst_tail;
-#if SUPPORT_CONST_MUL
- case ICMD_IMUL:
- iptr[0].opc = ICMD_IMULCONST;
- goto icmd_iconst_tail;
-#else /* SUPPORT_CONST_MUL */
- case ICMD_IMUL:
- if (iptr[0].val.i == 0x00000002)
- iptr[0].val.i = 1;
- else if (iptr[0].val.i == 0x00000004)
- iptr[0].val.i = 2;
- else if (iptr[0].val.i == 0x00000008)
- iptr[0].val.i = 3;
- else if (iptr[0].val.i == 0x00000010)
- iptr[0].val.i = 4;
- else if (iptr[0].val.i == 0x00000020)
- iptr[0].val.i = 5;
- else if (iptr[0].val.i == 0x00000040)
- iptr[0].val.i = 6;
- else if (iptr[0].val.i == 0x00000080)
- iptr[0].val.i = 7;
- else if (iptr[0].val.i == 0x00000100)
- iptr[0].val.i = 8;
- else if (iptr[0].val.i == 0x00000200)
- iptr[0].val.i = 9;
- else if (iptr[0].val.i == 0x00000400)
- iptr[0].val.i = 10;
- else if (iptr[0].val.i == 0x00000800)
- iptr[0].val.i = 11;
- else if (iptr[0].val.i == 0x00001000)
- iptr[0].val.i = 12;
- else if (iptr[0].val.i == 0x00002000)
- iptr[0].val.i = 13;
- else if (iptr[0].val.i == 0x00004000)
- iptr[0].val.i = 14;
- else if (iptr[0].val.i == 0x00008000)
- iptr[0].val.i = 15;
- else if (iptr[0].val.i == 0x00010000)
- iptr[0].val.i = 16;
- else if (iptr[0].val.i == 0x00020000)
- iptr[0].val.i = 17;
- else if (iptr[0].val.i == 0x00040000)
- iptr[0].val.i = 18;
- else if (iptr[0].val.i == 0x00080000)
- iptr[0].val.i = 19;
- else if (iptr[0].val.i == 0x00100000)
- iptr[0].val.i = 20;
- else if (iptr[0].val.i == 0x00200000)
- iptr[0].val.i = 21;
- else if (iptr[0].val.i == 0x00400000)
- iptr[0].val.i = 22;
- else if (iptr[0].val.i == 0x00800000)
- iptr[0].val.i = 23;
- else if (iptr[0].val.i == 0x01000000)
- iptr[0].val.i = 24;
- else if (iptr[0].val.i == 0x02000000)
- iptr[0].val.i = 25;
- else if (iptr[0].val.i == 0x04000000)
- iptr[0].val.i = 26;
- else if (iptr[0].val.i == 0x08000000)
- iptr[0].val.i = 27;
- else if (iptr[0].val.i == 0x10000000)
- iptr[0].val.i = 28;
- else if (iptr[0].val.i == 0x20000000)
- iptr[0].val.i = 29;
- else if (iptr[0].val.i == 0x40000000)
- iptr[0].val.i = 30;
- else if (iptr[0].val.i == 0x80000000)
- iptr[0].val.i = 31;
- else {
- PUSHCONST(TYPE_INT);
- break;
- }
- iptr[0].opc = ICMD_IMULPOW2;
- goto icmd_iconst_tail;
-#endif /* SUPPORT_CONST_MUL */
- case ICMD_IDIV:
- if (iptr[0].val.i == 0x00000002)
- iptr[0].val.i = 1;
- else if (iptr[0].val.i == 0x00000004)
- iptr[0].val.i = 2;
- else if (iptr[0].val.i == 0x00000008)
- iptr[0].val.i = 3;
- else if (iptr[0].val.i == 0x00000010)
- iptr[0].val.i = 4;
- else if (iptr[0].val.i == 0x00000020)
- iptr[0].val.i = 5;
- else if (iptr[0].val.i == 0x00000040)
- iptr[0].val.i = 6;
- else if (iptr[0].val.i == 0x00000080)
- iptr[0].val.i = 7;
- else if (iptr[0].val.i == 0x00000100)
- iptr[0].val.i = 8;
- else if (iptr[0].val.i == 0x00000200)
- iptr[0].val.i = 9;
- else if (iptr[0].val.i == 0x00000400)
- iptr[0].val.i = 10;
- else if (iptr[0].val.i == 0x00000800)
- iptr[0].val.i = 11;
- else if (iptr[0].val.i == 0x00001000)
- iptr[0].val.i = 12;
- else if (iptr[0].val.i == 0x00002000)
- iptr[0].val.i = 13;
- else if (iptr[0].val.i == 0x00004000)
- iptr[0].val.i = 14;
- else if (iptr[0].val.i == 0x00008000)
- iptr[0].val.i = 15;
- else if (iptr[0].val.i == 0x00010000)
- iptr[0].val.i = 16;
- else if (iptr[0].val.i == 0x00020000)
- iptr[0].val.i = 17;
- else if (iptr[0].val.i == 0x00040000)
- iptr[0].val.i = 18;
- else if (iptr[0].val.i == 0x00080000)
- iptr[0].val.i = 19;
- else if (iptr[0].val.i == 0x00100000)
- iptr[0].val.i = 20;
- else if (iptr[0].val.i == 0x00200000)
- iptr[0].val.i = 21;
- else if (iptr[0].val.i == 0x00400000)
- iptr[0].val.i = 22;
- else if (iptr[0].val.i == 0x00800000)
- iptr[0].val.i = 23;
- else if (iptr[0].val.i == 0x01000000)
- iptr[0].val.i = 24;
- else if (iptr[0].val.i == 0x02000000)
- iptr[0].val.i = 25;
- else if (iptr[0].val.i == 0x04000000)
- iptr[0].val.i = 26;
- else if (iptr[0].val.i == 0x08000000)
- iptr[0].val.i = 27;
- else if (iptr[0].val.i == 0x10000000)
- iptr[0].val.i = 28;
- else if (iptr[0].val.i == 0x20000000)
- iptr[0].val.i = 29;
- else if (iptr[0].val.i == 0x40000000)
- iptr[0].val.i = 30;
- else if (iptr[0].val.i == 0x80000000)
- iptr[0].val.i = 31;
- else {
- PUSHCONST(TYPE_INT);
- break;
- }
- iptr[0].opc = ICMD_IDIVPOW2;
- goto icmd_iconst_tail;
- case ICMD_IREM:
- /*log_text("stack.c: ICMD_ICONST/ICMD_IREM");*/
- if ((iptr[0].val.i == 0x00000002) ||
- (iptr[0].val.i == 0x00000004) ||
- (iptr[0].val.i == 0x00000008) ||
- (iptr[0].val.i == 0x00000010) ||
- (iptr[0].val.i == 0x00000020) ||
- (iptr[0].val.i == 0x00000040) ||
- (iptr[0].val.i == 0x00000080) ||
- (iptr[0].val.i == 0x00000100) ||
- (iptr[0].val.i == 0x00000200) ||
- (iptr[0].val.i == 0x00000400) ||
- (iptr[0].val.i == 0x00000800) ||
- (iptr[0].val.i == 0x00001000) ||
- (iptr[0].val.i == 0x00002000) ||
- (iptr[0].val.i == 0x00004000) ||
- (iptr[0].val.i == 0x00008000) ||
- (iptr[0].val.i == 0x00010000) ||
- (iptr[0].val.i == 0x00020000) ||
- (iptr[0].val.i == 0x00040000) ||
- (iptr[0].val.i == 0x00080000) ||
- (iptr[0].val.i == 0x00100000) ||
- (iptr[0].val.i == 0x00200000) ||
- (iptr[0].val.i == 0x00400000) ||
- (iptr[0].val.i == 0x00800000) ||
- (iptr[0].val.i == 0x01000000) ||
- (iptr[0].val.i == 0x02000000) ||
- (iptr[0].val.i == 0x04000000) ||
- (iptr[0].val.i == 0x08000000) ||
- (iptr[0].val.i == 0x10000000) ||
- (iptr[0].val.i == 0x20000000) ||
- (iptr[0].val.i == 0x40000000) ||
- (iptr[0].val.i == 0x80000000)) {
- iptr[0].opc = ICMD_IREMPOW2;
- iptr[0].val.i -= 1;
- goto icmd_iconst_tail;
- }
- PUSHCONST(TYPE_INT);
- break;
-#if SUPPORT_CONST_LOGICAL
- case ICMD_IAND:
- iptr[0].opc = ICMD_IANDCONST;
- goto icmd_iconst_tail;
- case ICMD_IOR:
- iptr[0].opc = ICMD_IORCONST;
- goto icmd_iconst_tail;
- case ICMD_IXOR:
- iptr[0].opc = ICMD_IXORCONST;
- goto icmd_iconst_tail;
-#endif /* SUPPORT_CONST_LOGICAL */
- case ICMD_ISHL:
- iptr[0].opc = ICMD_ISHLCONST;
- goto icmd_iconst_tail;
- case ICMD_ISHR:
- iptr[0].opc = ICMD_ISHRCONST;
- goto icmd_iconst_tail;
- case ICMD_IUSHR:
- iptr[0].opc = ICMD_IUSHRCONST;
- goto icmd_iconst_tail;
-#if SUPPORT_LONG_SHIFT
- case ICMD_LSHL:
- iptr[0].opc = ICMD_LSHLCONST;
- goto icmd_lconst_tail;
- case ICMD_LSHR:
- iptr[0].opc = ICMD_LSHRCONST;
- goto icmd_lconst_tail;
- case ICMD_LUSHR:
- iptr[0].opc = ICMD_LUSHRCONST;
- goto icmd_lconst_tail;
-#endif /* SUPPORT_LONG_SHIFT */
- case ICMD_IF_ICMPEQ:
- iptr[1].opc = ICMD_IFEQ;
- icmd_if_icmp_tail:
-/* iptr[0].op1 = iptr[1].op1; */
- /* IF_ICMPxx is the last instruction in the
- basic block, just remove it. */
- iptr[0].opc = ICMD_NOP;
- iptr[1].val.i = iptr[0].val.i;
- SETDST;
-/* bptr->icount--; */
-/* len--; */
-#if 0
- OP1_0(TYPE_INT);
- tbptr = m->basicblocks +
- m->basicblockindex[iptr[1].op1];
-
- iptr[1].target = (void *) tbptr;
-
- MARKREACHED(tbptr, copy);
- COUNT(count_pcmd_bra);
-#endif
- break;
- case ICMD_IF_ICMPLT:
- iptr[1].opc = ICMD_IFLT;
- goto icmd_if_icmp_tail;
- case ICMD_IF_ICMPLE:
- iptr[1].opc = ICMD_IFLE;
- goto icmd_if_icmp_tail;
- case ICMD_IF_ICMPNE:
- iptr[1].opc = ICMD_IFNE;
- goto icmd_if_icmp_tail;
- case ICMD_IF_ICMPGT:
- iptr[1].opc = ICMD_IFGT;
- goto icmd_if_icmp_tail;
- case ICMD_IF_ICMPGE:
- iptr[1].opc = ICMD_IFGE;
- goto icmd_if_icmp_tail;
-
-#if SUPPORT_CONST_STORE
- case ICMD_IASTORE:
- case ICMD_BASTORE:
- case ICMD_CASTORE:
- case ICMD_SASTORE:
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
-# if SUPPORT_CONST_STORE_ZERO_ONLY
- if (iptr[0].val.i == 0) {
-# endif
- switch (iptr[1].opc) {
- case ICMD_IASTORE:
- iptr[0].opc = ICMD_IASTORECONST;
- break;
- case ICMD_BASTORE:
- iptr[0].opc = ICMD_BASTORECONST;
- break;
- case ICMD_CASTORE:
- iptr[0].opc = ICMD_CASTORECONST;
- break;
- case ICMD_SASTORE:
- iptr[0].opc = ICMD_SASTORECONST;
- break;
- }
-
- iptr[1].opc = ICMD_NOP;
- OPTT2_0(TYPE_INT, TYPE_ADR);
- COUNT(count_pcmd_op);
-# if SUPPORT_CONST_STORE_ZERO_ONLY
- }
- else
- PUSHCONST(TYPE_INT);
-# endif
-# if defined(ENABLE_INTRP)
- }
- else
- PUSHCONST(TYPE_INT);
-# endif
- break;
-
- case ICMD_PUTSTATIC:
- case ICMD_PUTFIELD:
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
-# if SUPPORT_CONST_STORE_ZERO_ONLY
- if (iptr[0].val.i == 0) {
-# endif
- switch (iptr[1].opc) {
- case ICMD_PUTSTATIC:
- iptr[0].opc = ICMD_PUTSTATICCONST;
- SETDST;
- break;
- case ICMD_PUTFIELD:
- iptr[0].opc = ICMD_PUTFIELDCONST;
- OP1_0(TYPE_ADR);
- break;
- }
-
- iptr[1].opc = ICMD_NOP;
- iptr[0].op1 = TYPE_INT;
- COUNT(count_pcmd_op);
-# if SUPPORT_CONST_STORE_ZERO_ONLY
- }
- else
- PUSHCONST(TYPE_INT);
-# endif
-# if defined(ENABLE_INTRP)
- }
- else
- PUSHCONST(TYPE_INT);
-# endif
- break;
-#endif /* SUPPORT_CONST_STORE */
- default:
- PUSHCONST(TYPE_INT);
- }
- }
- else
- PUSHCONST(TYPE_INT);
- break;
-
- case ICMD_LCONST:
- COUNT(count_pcmd_load);
- if (len > 0) {
- switch (iptr[1].opc) {
-#if SUPPORT_LONG_ADD
- case ICMD_LADD:
- iptr[0].opc = ICMD_LADDCONST;
- icmd_lconst_tail:
- iptr[1].opc = ICMD_NOP;
- OP1_1(TYPE_LNG,TYPE_LNG);
- COUNT(count_pcmd_op);
- break;
- case ICMD_LSUB:
- iptr[0].opc = ICMD_LSUBCONST;
- goto icmd_lconst_tail;
-#endif /* SUPPORT_LONG_ADD */
-#if SUPPORT_LONG_MUL && SUPPORT_CONST_MUL
- case ICMD_LMUL:
- iptr[0].opc = ICMD_LMULCONST;
- goto icmd_lconst_tail;
-#else /* SUPPORT_LONG_MUL && SUPPORT_CONST_MUL */
-# if SUPPORT_LONG_SHIFT
- case ICMD_LMUL:
- if (iptr[0].val.l == 0x00000002)
- iptr[0].val.i = 1;
- else if (iptr[0].val.l == 0x00000004)
- iptr[0].val.i = 2;
- else if (iptr[0].val.l == 0x00000008)
- iptr[0].val.i = 3;
- else if (iptr[0].val.l == 0x00000010)
- iptr[0].val.i = 4;
- else if (iptr[0].val.l == 0x00000020)
- iptr[0].val.i = 5;
- else if (iptr[0].val.l == 0x00000040)
- iptr[0].val.i = 6;
- else if (iptr[0].val.l == 0x00000080)
- iptr[0].val.i = 7;
- else if (iptr[0].val.l == 0x00000100)
- iptr[0].val.i = 8;
- else if (iptr[0].val.l == 0x00000200)
- iptr[0].val.i = 9;
- else if (iptr[0].val.l == 0x00000400)
- iptr[0].val.i = 10;
- else if (iptr[0].val.l == 0x00000800)
- iptr[0].val.i = 11;
- else if (iptr[0].val.l == 0x00001000)
- iptr[0].val.i = 12;
- else if (iptr[0].val.l == 0x00002000)
- iptr[0].val.i = 13;
- else if (iptr[0].val.l == 0x00004000)
- iptr[0].val.i = 14;
- else if (iptr[0].val.l == 0x00008000)
- iptr[0].val.i = 15;
- else if (iptr[0].val.l == 0x00010000)
- iptr[0].val.i = 16;
- else if (iptr[0].val.l == 0x00020000)
- iptr[0].val.i = 17;
- else if (iptr[0].val.l == 0x00040000)
- iptr[0].val.i = 18;
- else if (iptr[0].val.l == 0x00080000)
- iptr[0].val.i = 19;
- else if (iptr[0].val.l == 0x00100000)
- iptr[0].val.i = 20;
- else if (iptr[0].val.l == 0x00200000)
- iptr[0].val.i = 21;
- else if (iptr[0].val.l == 0x00400000)
- iptr[0].val.i = 22;
- else if (iptr[0].val.l == 0x00800000)
- iptr[0].val.i = 23;
- else if (iptr[0].val.l == 0x01000000)
- iptr[0].val.i = 24;
- else if (iptr[0].val.l == 0x02000000)
- iptr[0].val.i = 25;
- else if (iptr[0].val.l == 0x04000000)
- iptr[0].val.i = 26;
- else if (iptr[0].val.l == 0x08000000)
- iptr[0].val.i = 27;
- else if (iptr[0].val.l == 0x10000000)
- iptr[0].val.i = 28;
- else if (iptr[0].val.l == 0x20000000)
- iptr[0].val.i = 29;
- else if (iptr[0].val.l == 0x40000000)
- iptr[0].val.i = 30;
- else if (iptr[0].val.l == 0x80000000)
- iptr[0].val.i = 31;
- else {
- PUSHCONST(TYPE_LNG);
- break;
- }
- iptr[0].opc = ICMD_LMULPOW2;
- goto icmd_lconst_tail;
-# endif /* SUPPORT_LONG_SHIFT */
-#endif /* SUPPORT_LONG_MUL && SUPPORT_CONST_MUL */
-
-#if SUPPORT_LONG_DIV_POW2
- case ICMD_LDIV:
- if (iptr[0].val.l == 0x00000002)
- iptr[0].val.i = 1;
- else if (iptr[0].val.l == 0x00000004)
- iptr[0].val.i = 2;
- else if (iptr[0].val.l == 0x00000008)
- iptr[0].val.i = 3;
- else if (iptr[0].val.l == 0x00000010)
- iptr[0].val.i = 4;
- else if (iptr[0].val.l == 0x00000020)
- iptr[0].val.i = 5;
- else if (iptr[0].val.l == 0x00000040)
- iptr[0].val.i = 6;
- else if (iptr[0].val.l == 0x00000080)
- iptr[0].val.i = 7;
- else if (iptr[0].val.l == 0x00000100)
- iptr[0].val.i = 8;
- else if (iptr[0].val.l == 0x00000200)
- iptr[0].val.i = 9;
- else if (iptr[0].val.l == 0x00000400)
- iptr[0].val.i = 10;
- else if (iptr[0].val.l == 0x00000800)
- iptr[0].val.i = 11;
- else if (iptr[0].val.l == 0x00001000)
- iptr[0].val.i = 12;
- else if (iptr[0].val.l == 0x00002000)
- iptr[0].val.i = 13;
- else if (iptr[0].val.l == 0x00004000)
- iptr[0].val.i = 14;
- else if (iptr[0].val.l == 0x00008000)
- iptr[0].val.i = 15;
- else if (iptr[0].val.l == 0x00010000)
- iptr[0].val.i = 16;
- else if (iptr[0].val.l == 0x00020000)
- iptr[0].val.i = 17;
- else if (iptr[0].val.l == 0x00040000)
- iptr[0].val.i = 18;
- else if (iptr[0].val.l == 0x00080000)
- iptr[0].val.i = 19;
- else if (iptr[0].val.l == 0x00100000)
- iptr[0].val.i = 20;
- else if (iptr[0].val.l == 0x00200000)
- iptr[0].val.i = 21;
- else if (iptr[0].val.l == 0x00400000)
- iptr[0].val.i = 22;
- else if (iptr[0].val.l == 0x00800000)
- iptr[0].val.i = 23;
- else if (iptr[0].val.l == 0x01000000)
- iptr[0].val.i = 24;
- else if (iptr[0].val.l == 0x02000000)
- iptr[0].val.i = 25;
- else if (iptr[0].val.l == 0x04000000)
- iptr[0].val.i = 26;
- else if (iptr[0].val.l == 0x08000000)
- iptr[0].val.i = 27;
- else if (iptr[0].val.l == 0x10000000)
- iptr[0].val.i = 28;
- else if (iptr[0].val.l == 0x20000000)
- iptr[0].val.i = 29;
- else if (iptr[0].val.l == 0x40000000)
- iptr[0].val.i = 30;
- else if (iptr[0].val.l == 0x80000000)
- iptr[0].val.i = 31;
- else {
- PUSHCONST(TYPE_LNG);
- break;
- }
- iptr[0].opc = ICMD_LDIVPOW2;
- goto icmd_lconst_tail;
-#endif /* SUPPORT_LONG_DIV_POW2 */
-
-#if SUPPORT_LONG_REM_POW2
- case ICMD_LREM:
- if ((iptr[0].val.l == 0x00000002) ||
- (iptr[0].val.l == 0x00000004) ||
- (iptr[0].val.l == 0x00000008) ||
- (iptr[0].val.l == 0x00000010) ||
- (iptr[0].val.l == 0x00000020) ||
- (iptr[0].val.l == 0x00000040) ||
- (iptr[0].val.l == 0x00000080) ||
- (iptr[0].val.l == 0x00000100) ||
- (iptr[0].val.l == 0x00000200) ||
- (iptr[0].val.l == 0x00000400) ||
- (iptr[0].val.l == 0x00000800) ||
- (iptr[0].val.l == 0x00001000) ||
- (iptr[0].val.l == 0x00002000) ||
- (iptr[0].val.l == 0x00004000) ||
- (iptr[0].val.l == 0x00008000) ||
- (iptr[0].val.l == 0x00010000) ||
- (iptr[0].val.l == 0x00020000) ||
- (iptr[0].val.l == 0x00040000) ||
- (iptr[0].val.l == 0x00080000) ||
- (iptr[0].val.l == 0x00100000) ||
- (iptr[0].val.l == 0x00200000) ||
- (iptr[0].val.l == 0x00400000) ||
- (iptr[0].val.l == 0x00800000) ||
- (iptr[0].val.l == 0x01000000) ||
- (iptr[0].val.l == 0x02000000) ||
- (iptr[0].val.l == 0x04000000) ||
- (iptr[0].val.l == 0x08000000) ||
- (iptr[0].val.l == 0x10000000) ||
- (iptr[0].val.l == 0x20000000) ||
- (iptr[0].val.l == 0x40000000) ||
- (iptr[0].val.l == 0x80000000)) {
- iptr[0].opc = ICMD_LREMPOW2;
- iptr[0].val.l -= 1;
- goto icmd_lconst_tail;
- }
- PUSHCONST(TYPE_LNG);
- break;
-#endif /* SUPPORT_LONG_REM_POW2 */
-
-#if SUPPORT_LONG_LOGICAL && SUPPORT_CONST_LOGICAL
-
- case ICMD_LAND:
- iptr[0].opc = ICMD_LANDCONST;
- goto icmd_lconst_tail;
- case ICMD_LOR:
- iptr[0].opc = ICMD_LORCONST;
- goto icmd_lconst_tail;
- case ICMD_LXOR:
- iptr[0].opc = ICMD_LXORCONST;
- goto icmd_lconst_tail;
-#endif /* SUPPORT_LONG_LOGICAL && SUPPORT_CONST_LOGICAL */
-
-#if SUPPORT_LONG_CMP_CONST
- case ICMD_LCMP:
- if ((len > 1) && (iptr[2].val.i == 0)) {
- switch (iptr[2].opc) {
- case ICMD_IFEQ:
- iptr[0].opc = ICMD_IF_LEQ;
- icmd_lconst_lcmp_tail:
- iptr[0].op1 = iptr[2].op1;
- iptr[1].opc = ICMD_NOP;
- iptr[2].opc = ICMD_NOP;
-
-/* bptr->icount -= 2; */
-/* len -= 2; */
-
- OP1_0(TYPE_LNG);
- tbptr = m->basicblocks +
- m->basicblockindex[iptr[0].op1];
-
- iptr[0].target = (void *) tbptr;
-
- MARKREACHED(tbptr, copy);
- COUNT(count_pcmd_bra);
- COUNT(count_pcmd_op);
- break;
- case ICMD_IFNE:
- iptr[0].opc = ICMD_IF_LNE;
- goto icmd_lconst_lcmp_tail;
- case ICMD_IFLT:
- iptr[0].opc = ICMD_IF_LLT;
- goto icmd_lconst_lcmp_tail;
- case ICMD_IFGT:
- iptr[0].opc = ICMD_IF_LGT;
- goto icmd_lconst_lcmp_tail;
- case ICMD_IFLE:
- iptr[0].opc = ICMD_IF_LLE;
- goto icmd_lconst_lcmp_tail;
- case ICMD_IFGE:
- iptr[0].opc = ICMD_IF_LGE;
- goto icmd_lconst_lcmp_tail;
- default:
- PUSHCONST(TYPE_LNG);
- } /* switch (iptr[2].opc) */
- } /* if (iptr[2].val.i == 0) */
- else
- PUSHCONST(TYPE_LNG);
- break;
-#endif /* SUPPORT_LONG_CMP_CONST */
-
-#if SUPPORT_CONST_STORE
- case ICMD_LASTORE:
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
-# if SUPPORT_CONST_STORE_ZERO_ONLY
- if (iptr[0].val.l == 0) {
-# endif
- iptr[0].opc = ICMD_LASTORECONST;
- iptr[1].opc = ICMD_NOP;
- OPTT2_0(TYPE_INT, TYPE_ADR);
- COUNT(count_pcmd_op);
-# if SUPPORT_CONST_STORE_ZERO_ONLY
- }
- else
- PUSHCONST(TYPE_LNG);
-# endif
-# if defined(ENABLE_INTRP)
- }
- else
- PUSHCONST(TYPE_LNG);
-# endif
- break;
-
- case ICMD_PUTSTATIC:
- case ICMD_PUTFIELD:
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
-# if SUPPORT_CONST_STORE_ZERO_ONLY
- if (iptr[0].val.l == 0) {
-# endif
- switch (iptr[1].opc) {
- case ICMD_PUTSTATIC:
- iptr[0].opc = ICMD_PUTSTATICCONST;
- SETDST;
- break;
- case ICMD_PUTFIELD:
- iptr[0].opc = ICMD_PUTFIELDCONST;
- OP1_0(TYPE_ADR);
- break;
- }
-
- iptr[1].opc = ICMD_NOP;
- iptr[0].op1 = TYPE_LNG;
- COUNT(count_pcmd_op);
-# if SUPPORT_CONST_STORE_ZERO_ONLY
- }
- else
- PUSHCONST(TYPE_LNG);
-# endif
-# if defined(ENABLE_INTRP)
- }
- else
- PUSHCONST(TYPE_LNG);
-# endif
- break;
-#endif /* SUPPORT_CONST_STORE */
- default:
- PUSHCONST(TYPE_LNG);
- }
- }
- else
- PUSHCONST(TYPE_LNG);
- break;
-
- case ICMD_FCONST:
- COUNT(count_pcmd_load);
- PUSHCONST(TYPE_FLT);
- break;
-
- case ICMD_DCONST:
- COUNT(count_pcmd_load);
- PUSHCONST(TYPE_DBL);
- break;
-
- case ICMD_ACONST:
- COUNT(count_pcmd_load);
-#if SUPPORT_CONST_STORE
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
- /* We can only optimize if the ACONST is resolved
- * and there is an instruction after it. */
-
- if ((len > 0) && INSTRUCTION_IS_RESOLVED(iptr))
- {
- switch (iptr[1].opc) {
- case ICMD_AASTORE:
- /* We can only optimize for NULL values
- * here because otherwise a checkcast is
- * required. */
- if (iptr->val.a != NULL)
- goto aconst_no_transform;
-
- iptr[0].opc = ICMD_AASTORECONST;
- OPTT2_0(TYPE_INT, TYPE_ADR);
-
- iptr[1].opc = ICMD_NOP;
- COUNT(count_pcmd_op);
- break;
-
- case ICMD_PUTSTATIC:
- case ICMD_PUTFIELD:
-# if SUPPORT_CONST_STORE_ZERO_ONLY
- if (iptr->val.a == 0) {
-# endif
-
- switch (iptr[1].opc) {
- case ICMD_PUTSTATIC:
- iptr[0].opc = ICMD_PUTSTATICCONST;
- iptr[0].op1 = TYPE_ADR;
- SETDST;
- break;
- case ICMD_PUTFIELD:
- iptr[0].opc = ICMD_PUTFIELDCONST;
- iptr[0].op1 = TYPE_ADR;
- OP1_0(TYPE_ADR);
- break;
- }
-
- iptr[1].opc = ICMD_NOP;
- COUNT(count_pcmd_op);
-
-# if SUPPORT_CONST_STORE_ZERO_ONLY
- }
- else
- /* no transformation */
- PUSHCONST(TYPE_ADR);
-# endif
- break;
-
- default:
- aconst_no_transform:
- /* no transformation */
- PUSHCONST(TYPE_ADR);
- }
- }
- else {
- /* no transformation */
- PUSHCONST(TYPE_ADR);
- }
-# if defined(ENABLE_INTRP)
- }
- else
- PUSHCONST(TYPE_ADR);
-# endif
-#else /* SUPPORT_CONST_STORE */
- PUSHCONST(TYPE_ADR);
-#endif /* SUPPORT_CONST_STORE */
- break;
-
- /* pop 0 push 1 load */
-
- case ICMD_ILOAD:
- case ICMD_LLOAD:
- case ICMD_FLOAD:
- case ICMD_DLOAD:
- case ICMD_ALOAD:
- COUNT(count_load_instruction);
- i = opcode - ICMD_ILOAD;
-#if defined(ENABLE_INTRP)
- if (!opt_intrp)
-#endif
- rd->locals[iptr->op1][i].type = i;
- LOAD(i, LOCALVAR, iptr->op1);
- break;
-
- /* pop 2 push 1 */
-
- case ICMD_LALOAD:
- case ICMD_IALOAD:
- case ICMD_FALOAD:
- case ICMD_DALOAD:
- case ICMD_AALOAD:
- COUNT(count_check_null);
- COUNT(count_check_bound);
- COUNT(count_pcmd_mem);
- OP2IAT_1(opcode - ICMD_IALOAD);
- break;
-
- case ICMD_BALOAD:
- case ICMD_CALOAD:
- case ICMD_SALOAD:
- COUNT(count_check_null);
- COUNT(count_check_bound);
- COUNT(count_pcmd_mem);
- OP2IAT_1(TYPE_INT);
- break;
-
- /* pop 0 push 0 iinc */
-
- case ICMD_IINC:
-#if defined(ENABLE_STATISTICS)
- if (opt_stat) {
- i = stackdepth;
- if (i >= 10)
- count_store_depth[10]++;
- else
- count_store_depth[i]++;
- }
-#endif
- last_store[5 * iptr->op1 + TYPE_INT] = bptr->icount - len - 1;
-
- copy = curstack;
- i = stackdepth - 1;
- while (copy) {
- if ((copy->varkind == LOCALVAR) &&
- (copy->varnum == iptr->op1)) {
- copy->varkind = TEMPVAR;
- copy->varnum = i;
- }
- i--;
- copy = copy->prev;
- }
-
- SETDST;
- break;
-
- /* pop 1 push 0 store */
-
- case ICMD_ISTORE:
- case ICMD_LSTORE:
- case ICMD_FSTORE:
- case ICMD_DSTORE:
- case ICMD_ASTORE:
- REQUIRE_1;
-
- i = opcode - ICMD_ISTORE;
-#if defined(ENABLE_INTRP)
- if (!opt_intrp)
-#endif
- rd->locals[iptr->op1][i].type = i;
-#if defined(ENABLE_STATISTICS)
- if (opt_stat) {
- count_pcmd_store++;
- i = new - curstack;
- if (i >= 20)
- count_store_length[20]++;
- else
- count_store_length[i]++;
- i = stackdepth - 1;
- if (i >= 10)
- count_store_depth[10]++;
- else
- count_store_depth[i]++;
- }
-#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->op1)) {
- copy->varkind = TEMPVAR;
- copy->varnum = i;
- }
- i--;
- copy = copy->prev;
- }
-
- /* do not change instack Stackslots */
- /* it won't improve performance if we copy the interface */
- /* at the BB begin or here, and lsra relies that no */
- /* instack stackslot is marked LOCALVAR */
- if (curstack->varkind == STACKVAR)
- goto _possible_conflict;
-
- /* check for a DUPX,SWAP while the lifetime of curstack */
- /* and as creator curstack */
- if (last_dupx != -1) {
- /* we have to look at the dst stack of DUPX */
- /* == src Stack of PEI */
- copy = bptr->iinstr[last_dupx].dst;
- /*
- if (last_pei == 0)
- copy = bptr->instack;
- else
- copy = bptr->iinstr[last_pei-1].dst;
- */
- if ((copy != NULL) && (curstack <= copy)) {
- /* curstack alive at or created by DUPX */
-
- /* TODO:.... */
- /* now look, if there is a LOCALVAR at anyone of */
- /* the src stacklots used by DUPX */
-
- goto _possible_conflict;
- }
- }
-
- /* check for a PEI while the lifetime of curstack */
- if (last_pei != -1) {
- /* && there are exception handler in this method */
- /* when this is checked prevent ARGVAR from */
- /* overwriting LOCALVAR!!! */
-
- /* we have to look at the stack _before_ the PEI! */
- /* == src Stack of PEI */
- if (last_pei == 0)
- copy = bptr->instack;
- else
- copy = bptr->iinstr[last_pei-1].dst;
- if ((copy != NULL) && (curstack <= copy)) {
- /* curstack alive at PEI */
- goto _possible_conflict;
- }
- }
-
- /* check if there is a possible conflicting XSTORE */
- if (last_store[5 * iptr->op1 + opcode - ICMD_ISTORE] != -1) {
- /* we have to look at the stack _before_ the XSTORE! */
- /* == src Stack of XSTORE */
- if (last_store[5 * iptr->op1 + opcode - ICMD_ISTORE] == 0)
- copy = bptr->instack;
- else
- copy = bptr->iinstr[last_store[5 * iptr->op1 + opcode - ICMD_ISTORE] - 1].dst;
- if ((copy != NULL) && (curstack <= copy)) {
- /* curstack alive at Last Store */
- goto _possible_conflict;
- }
- }
-
- /* check if there is a conflict with a XLOAD */
- /* this is done indirectly by looking if a Stackslot is */
- /* marked LOCALVAR and is live while curstack is live */
- /* see figure 5.3 */
-
- /* First check "above" stackslots of the instack */
- copy = curstack + 1;
- for(;(copy <= bptr->instack); copy++)
- if ((copy->varkind == LOCALVAR) && (copy->varnum == iptr->op1)) {
- goto _possible_conflict;
- }
-
- /* "intra" Basic Block Stackslots are allocated above */
- /* bptr->stack (see doc/stack.txt), so if curstack + 1 */
- /* is an instack, copy could point now to the stackslots */
- /* of an inbetween analysed Basic Block */
- if (copy < bptr->stack)
- copy = bptr->stack;
- while (copy < new) {
- if ((copy->varkind == LOCALVAR) && (copy->varnum == iptr->op1)) {
- goto _possible_conflict;
- }
- copy++;
- }
- /* If Stackslot is already marked as LOCALVAR, do not */
- /* change it! Conflict resolution works only, if xLOAD */
- /* has priority! */
- if (curstack->varkind == LOCALVAR)
- goto _possible_conflict;
- /* no conflict - mark the Stackslot as LOCALVAR */
- curstack->varkind = LOCALVAR;
- curstack->varnum = iptr->op1;
-
- goto _local_join;
- _possible_conflict:
- if ((curstack->varkind == LOCALVAR)
- && (curstack->varnum == iptr->op1)) {
- curstack->varkind = TEMPVAR;
- curstack->varnum = stackdepth-1;
- }
- _local_join:
- last_store[5 * iptr->op1 + opcode - ICMD_ISTORE] = bptr->icount - len - 1;
-
- STORE(opcode - ICMD_ISTORE);
- break;
-
- /* pop 3 push 0 */
-
- case ICMD_AASTORE:
- COUNT(count_check_null);
- COUNT(count_check_bound);
- COUNT(count_pcmd_mem);
-
- bte = builtintable_get_internal(BUILTIN_canstore);
- md = bte->md;
-
- if (md->memuse > rd->memuse)
- rd->memuse = md->memuse;
- if (md->argintreguse > rd->argintreguse)
- rd->argintreguse = md->argintreguse;
-
- /* make all stack variables saved */
-
- copy = curstack;
- while (copy) {
- copy->flags |= SAVEDVAR;
- copy = copy->prev;
- }
-
- OP3TIA_0(TYPE_ADR);
- break;
-
- case ICMD_IASTORE:
- case ICMD_LASTORE:
- case ICMD_FASTORE:
- case ICMD_DASTORE:
- COUNT(count_check_null);
- COUNT(count_check_bound);
- COUNT(count_pcmd_mem);
- OP3TIA_0(opcode - ICMD_IASTORE);
- break;
-
- case ICMD_BASTORE:
- case ICMD_CASTORE:
- case ICMD_SASTORE:
- COUNT(count_check_null);
- COUNT(count_check_bound);
- COUNT(count_pcmd_mem);
- OP3TIA_0(TYPE_INT);
- break;
-
- /* pop 1 push 0 */
-
- case ICMD_POP:
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- REQUIRE_1;
- if (IS_2_WORD_TYPE(curstack->type))
- goto throw_stack_category_error;
- }
-#endif
- OP1_0ANY;
- break;
-
- case ICMD_IRETURN:
- case ICMD_LRETURN:
- case ICMD_FRETURN:
- case ICMD_DRETURN:
- case ICMD_ARETURN:
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp)
-# endif
- md_return_alloc(jd, curstack);
-#endif
- COUNT(count_pcmd_return);
- OP1_0(opcode - ICMD_IRETURN);
- superblockend = true;
- break;
-
- case ICMD_ATHROW:
- COUNT(count_check_null);
- OP1_0(TYPE_ADR);
- STACKRESET;
- SETDST;
- superblockend = true;
- break;
-
- case ICMD_PUTSTATIC:
- COUNT(count_pcmd_mem);
- OP1_0(iptr->op1);
- break;
-
- /* pop 1 push 0 branch */
-
- case ICMD_IFNULL:
- case ICMD_IFNONNULL:
- COUNT(count_pcmd_bra);
- OP1_0(TYPE_ADR);
- tbptr = m->basicblocks + m->basicblockindex[iptr->op1];
-
- iptr[0].target = (void *) tbptr;
-
- MARKREACHED(tbptr, copy);
- break;
-
- case ICMD_IFEQ:
- case ICMD_IFNE:
- case ICMD_IFLT:
- case ICMD_IFGE:
- case ICMD_IFGT:
- case ICMD_IFLE:
- COUNT(count_pcmd_bra);
-
- /* iptr->val.i is set implicitly in parse by
- clearing the memory or from IF_ICMPxx
- optimization. */
-
- OP1_0(TYPE_INT);
-/* iptr->val.i = 0; */
- tbptr = m->basicblocks + m->basicblockindex[iptr->op1];
-
- iptr[0].target = (void *) tbptr;
-
- MARKREACHED(tbptr, copy);
- break;
-
- /* pop 0 push 0 branch */
-
- case ICMD_GOTO:
- COUNT(count_pcmd_bra);
- tbptr = m->basicblocks + m->basicblockindex[iptr->op1];
-
- iptr[0].target = (void *) tbptr;
-
- MARKREACHED(tbptr, copy);
- SETDST;
- superblockend = true;
- break;
-
- /* pop 1 push 0 table branch */
-
- case ICMD_TABLESWITCH:
- COUNT(count_pcmd_table);
- OP1_0(TYPE_INT);
- s4ptr = iptr->val.a;
- tbptr = m->basicblocks + m->basicblockindex[*s4ptr++];
- MARKREACHED(tbptr, copy);
- i = *s4ptr++; /* low */
- i = *s4ptr++ - i + 1; /* high */
-
- tptr = DMNEW(void*, i+1);
- iptr->target = (void *) tptr;
-
- tptr[0] = (void *) tbptr;
- tptr++;
-
- while (--i >= 0) {
- tbptr = m->basicblocks + m->basicblockindex[*s4ptr++];
-
- tptr[0] = (void *) tbptr;
- tptr++;
-
- MARKREACHED(tbptr, copy);
- }
- SETDST;
- superblockend = true;
- break;
-
- /* pop 1 push 0 table branch */
-
- case ICMD_LOOKUPSWITCH:
- COUNT(count_pcmd_table);
- OP1_0(TYPE_INT);
- s4ptr = iptr->val.a;
- tbptr = m->basicblocks + m->basicblockindex[*s4ptr++];
- MARKREACHED(tbptr, copy);
- i = *s4ptr++; /* count */
-
- tptr = DMNEW(void*, i+1);
- iptr->target = (void *) tptr;
-
- tptr[0] = (void *) tbptr;
- tptr++;
-
- while (--i >= 0) {
- tbptr = m->basicblocks + m->basicblockindex[s4ptr[1]];
-
- tptr[0] = (void *) tbptr;
- tptr++;
-
- MARKREACHED(tbptr, copy);
- s4ptr += 2;
- }
- SETDST;
- superblockend = true;
- break;
-
- case ICMD_MONITORENTER:
- COUNT(count_check_null);
- case ICMD_MONITOREXIT:
- OP1_0(TYPE_ADR);
- break;
-
- /* pop 2 push 0 branch */
-
- case ICMD_IF_ICMPEQ:
- case ICMD_IF_ICMPNE:
- case ICMD_IF_ICMPLT:
- case ICMD_IF_ICMPGE:
- case ICMD_IF_ICMPGT:
- case ICMD_IF_ICMPLE:
- COUNT(count_pcmd_bra);
- OP2_0(TYPE_INT);
- tbptr = m->basicblocks + m->basicblockindex[iptr->op1];
-
- iptr[0].target = (void *) tbptr;
-
- MARKREACHED(tbptr, copy);
- break;
-
- case ICMD_IF_ACMPEQ:
- case ICMD_IF_ACMPNE:
- COUNT(count_pcmd_bra);
- OP2_0(TYPE_ADR);
- tbptr = m->basicblocks + m->basicblockindex[iptr->op1];
-
- iptr[0].target = (void *) tbptr;
-
- MARKREACHED(tbptr, copy);
- break;
-
- /* pop 2 push 0 */
-
- case ICMD_PUTFIELD:
- COUNT(count_check_null);
- COUNT(count_pcmd_mem);
- OPTT2_0(iptr->op1,TYPE_ADR);
- break;
-
- case ICMD_POP2:
- REQUIRE_1;
- if (!IS_2_WORD_TYPE(curstack->type)) {
- /* ..., cat1 */
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- REQUIRE_2;
- if (IS_2_WORD_TYPE(curstack->prev->type))
- goto throw_stack_category_error;
- }
-#endif
- OP1_0ANY; /* second pop */
- }
- else
- iptr->opc = ICMD_POP;
- OP1_0ANY;
- break;
-
- /* pop 0 push 1 dup */
-
- case ICMD_DUP:
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- REQUIRE_1;
- if (IS_2_WORD_TYPE(curstack->type))
- goto throw_stack_category_error;
- }
-#endif
- last_dupx = bptr->icount - len - 1;
- COUNT(count_dup_instruction);
- DUP;
- break;
-
- case ICMD_DUP2:
- last_dupx = bptr->icount - len - 1;
- REQUIRE_1;
- if (IS_2_WORD_TYPE(curstack->type)) {
- /* ..., cat2 */
- iptr->opc = ICMD_DUP;
- DUP;
- }
- else {
- REQUIRE_2;
- /* ..., ????, cat1 */
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- if (IS_2_WORD_TYPE(curstack->prev->type))
- goto throw_stack_category_error;
- }
-#endif
- copy = curstack;
- NEWSTACK(copy->prev->type, copy->prev->varkind,
- copy->prev->varnum);
- NEWSTACK(copy->type, copy->varkind,
- copy->varnum);
- SETDST;
- stackdepth += 2;
- }
- break;
-
- /* pop 2 push 3 dup */
-
- case ICMD_DUP_X1:
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- REQUIRE_2;
- if (IS_2_WORD_TYPE(curstack->type) ||
- IS_2_WORD_TYPE(curstack->prev->type))
- goto throw_stack_category_error;
- }
-#endif
- last_dupx = bptr->icount - len - 1;
- DUP_X1;
- break;
-
- case ICMD_DUP2_X1:
- last_dupx = bptr->icount - len - 1;
- REQUIRE_2;
- if (IS_2_WORD_TYPE(curstack->type)) {
- /* ..., ????, cat2 */
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- if (IS_2_WORD_TYPE(curstack->prev->type))
- goto throw_stack_category_error;
- }
-#endif
- iptr->opc = ICMD_DUP_X1;
- DUP_X1;
- }
- else {
- /* ..., ????, cat1 */
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- REQUIRE_3;
- if (IS_2_WORD_TYPE(curstack->prev->type)
- || IS_2_WORD_TYPE(curstack->prev->prev->type))
- goto throw_stack_category_error;
- }
-#endif
- DUP2_X1;
- }
- 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, ???? */
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- if (IS_2_WORD_TYPE(curstack->type))
- goto throw_stack_category_error;
- }
-#endif
- iptr->opc = ICMD_DUP_X1;
- DUP_X1;
- }
- else {
- /* ..., cat1, ???? */
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- REQUIRE_3;
- if (IS_2_WORD_TYPE(curstack->type)
- || IS_2_WORD_TYPE(curstack->prev->prev->type))
- goto throw_stack_category_error;
- }
-#endif
- DUP_X2;
- }
- break;
-
- case ICMD_DUP2_X2:
- last_dupx = bptr->icount - len - 1;
- REQUIRE_2;
- if (IS_2_WORD_TYPE(curstack->type)) {
- /* ..., ????, cat2 */
- if (IS_2_WORD_TYPE(curstack->prev->type)) {
- /* ..., cat2, cat2 */
- iptr->opc = ICMD_DUP_X1;
- DUP_X1;
- }
- else {
- /* ..., cat1, cat2 */
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- REQUIRE_3;
- if (IS_2_WORD_TYPE(curstack->prev->prev->type))
- goto throw_stack_category_error;
- }
-#endif
- iptr->opc = ICMD_DUP_X2;
- DUP_X2;
- }
- }
- else {
- REQUIRE_3;
- /* ..., ????, ????, cat1 */
- if (IS_2_WORD_TYPE(curstack->prev->prev->type)) {
- /* ..., cat2, ????, cat1 */
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- if (IS_2_WORD_TYPE(curstack->prev->type))
- goto throw_stack_category_error;
- }
-#endif
- iptr->opc = ICMD_DUP2_X1;
- DUP2_X1;
- }
- else {
- /* ..., cat1, ????, cat1 */
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- REQUIRE_4;
- if (IS_2_WORD_TYPE(curstack->prev->type)
- || IS_2_WORD_TYPE(curstack->prev->prev->prev->type))
- goto throw_stack_category_error;
- }
-#endif
- DUP2_X2;
- }
- }
- break;
-
- /* pop 2 push 2 swap */
-
- case ICMD_SWAP:
- last_dupx = bptr->icount - len - 1;
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- REQUIRE_2;
- if (IS_2_WORD_TYPE(curstack->type)
- || IS_2_WORD_TYPE(curstack->prev->type))
- goto throw_stack_category_error;
- }
-#endif
- SWAP;
- break;
-
- /* pop 2 push 1 */
-
- case ICMD_IDIV:
- case ICMD_IREM:
-#if !SUPPORT_DIVISION
- bte = (builtintable_entry *) iptr->val.a;
- md = bte->md;
- i = iptr->op1;
-
- if (md->memuse > rd->memuse)
- rd->memuse = md->memuse;
- if (md->argintreguse > rd->argintreguse)
- rd->argintreguse = md->argintreguse;
-
- /* make all stack variables saved */
-
- copy = curstack;
- while (copy) {
- copy->flags |= SAVEDVAR;
- copy = copy->prev;
- }
-
- /* fall through */
-#endif /* !SUPPORT_DIVISION */
-
- case ICMD_ISHL:
- case ICMD_ISHR:
- case ICMD_IUSHR:
- case ICMD_IADD:
- case ICMD_ISUB:
- case ICMD_IMUL:
- case ICMD_IAND:
- case ICMD_IOR:
- case ICMD_IXOR:
- COUNT(count_pcmd_op);
- OP2_1(TYPE_INT);
- break;
-
- case ICMD_LDIV:
- case ICMD_LREM:
-#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
- bte = (builtintable_entry *) iptr->val.a;
- md = bte->md;
- i = iptr->op1;
-
- if (md->memuse > rd->memuse)
- rd->memuse = md->memuse;
- if (md->argintreguse > rd->argintreguse)
- rd->argintreguse = md->argintreguse;
-
- /* make all stack variables saved */
-
- copy = curstack;
- while (copy) {
- copy->flags |= SAVEDVAR;
- copy = copy->prev;
- }
-
- /* fall through */
-#endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
-
- case ICMD_LMUL:
- case ICMD_LADD:
- case ICMD_LSUB:
-#if SUPPORT_LONG_LOGICAL
- case ICMD_LAND:
- case ICMD_LOR:
- case ICMD_LXOR:
-#endif /* SUPPORT_LONG_LOGICAL */
- COUNT(count_pcmd_op);
- OP2_1(TYPE_LNG);
- break;
-
- case ICMD_LSHL:
- case ICMD_LSHR:
- case ICMD_LUSHR:
- COUNT(count_pcmd_op);
- OP2IT_1(TYPE_LNG);
- break;
-
- case ICMD_FADD:
- case ICMD_FSUB:
- case ICMD_FMUL:
- case ICMD_FDIV:
- case ICMD_FREM:
- COUNT(count_pcmd_op);
- OP2_1(TYPE_FLT);
- break;
-
- case ICMD_DADD:
- case ICMD_DSUB:
- case ICMD_DMUL:
- case ICMD_DDIV:
- case ICMD_DREM:
- COUNT(count_pcmd_op);
- OP2_1(TYPE_DBL);
- break;
-
- case ICMD_LCMP:
- COUNT(count_pcmd_op);
-#if SUPPORT_LONG_CMP_CONST
- if ((len > 0) && (iptr[1].val.i == 0)) {
- switch (iptr[1].opc) {
- case ICMD_IFEQ:
- iptr[0].opc = ICMD_IF_LCMPEQ;
- icmd_lcmp_if_tail:
- iptr[0].op1 = iptr[1].op1;
- iptr[1].opc = ICMD_NOP;
-/* len--; */
-/* bptr->icount--; */
-
- OP2_0(TYPE_LNG);
- tbptr = m->basicblocks +
- m->basicblockindex[iptr[0].op1];
-
- iptr[0].target = (void *) tbptr;
-
- MARKREACHED(tbptr, copy);
- COUNT(count_pcmd_bra);
- break;
- case ICMD_IFNE:
- iptr[0].opc = ICMD_IF_LCMPNE;
- goto icmd_lcmp_if_tail;
- case ICMD_IFLT:
- iptr[0].opc = ICMD_IF_LCMPLT;
- goto icmd_lcmp_if_tail;
- case ICMD_IFGT:
- iptr[0].opc = ICMD_IF_LCMPGT;
- goto icmd_lcmp_if_tail;
- case ICMD_IFLE:
- iptr[0].opc = ICMD_IF_LCMPLE;
- goto icmd_lcmp_if_tail;
- case ICMD_IFGE:
- iptr[0].opc = ICMD_IF_LCMPGE;
- goto icmd_lcmp_if_tail;
- default:
- OPTT2_1(TYPE_LNG, TYPE_INT);
- }
- }
- else
-#endif /* SUPPORT_LONG_CMP_CONST */
- OPTT2_1(TYPE_LNG, TYPE_INT);
- break;
-
-#if 0
- case ICMD_FCMPL:
- COUNT(count_pcmd_op);
- if ((len > 0) && (iptr[1].val.i == 0)) {
- switch (iptr[1].opc) {
- case ICMD_IFEQ:
- iptr[0].opc = ICMD_IF_FCMPEQ;
- icmd_if_fcmpl_tail:
- iptr[0].op1 = iptr[1].op1;
- iptr[1].opc = ICMD_NOP;
-
- OP2_0(TYPE_FLT);
- tbptr = m->basicblocks +
- m->basicblockindex[iptr[0].op1];
-
- iptr[0].target = (void *) tbptr;
-
- MARKREACHED(tbptr, copy);
- COUNT(count_pcmd_bra);
- break;
- case ICMD_IFNE:
- iptr[0].opc = ICMD_IF_FCMPNE;
- goto icmd_if_fcmpl_tail;
- case ICMD_IFLT:
- iptr[0].opc = ICMD_IF_FCMPL_LT;
- goto icmd_if_fcmpl_tail;
- case ICMD_IFGT:
- iptr[0].opc = ICMD_IF_FCMPL_GT;
- goto icmd_if_fcmpl_tail;
- case ICMD_IFLE:
- iptr[0].opc = ICMD_IF_FCMPL_LE;
- goto icmd_if_fcmpl_tail;
- case ICMD_IFGE:
- iptr[0].opc = ICMD_IF_FCMPL_GE;
- goto icmd_if_fcmpl_tail;
- default:
- OPTT2_1(TYPE_FLT, TYPE_INT);
- }
- }
- else
- OPTT2_1(TYPE_FLT, TYPE_INT);
- break;
-
- case ICMD_FCMPG:
- COUNT(count_pcmd_op);
- if ((len > 0) && (iptr[1].val.i == 0)) {
- switch (iptr[1].opc) {
- case ICMD_IFEQ:
- iptr[0].opc = ICMD_IF_FCMPEQ;
- icmd_if_fcmpg_tail:
- iptr[0].op1 = iptr[1].op1;
- iptr[1].opc = ICMD_NOP;
-
- OP2_0(TYPE_FLT);
- tbptr = m->basicblocks +
- m->basicblockindex[iptr[0].op1];
-
- iptr[0].target = (void *) tbptr;
-
- MARKREACHED(tbptr, copy);
- COUNT(count_pcmd_bra);
- break;
- case ICMD_IFNE:
- iptr[0].opc = ICMD_IF_FCMPNE;
- goto icmd_if_fcmpg_tail;
- case ICMD_IFLT:
- iptr[0].opc = ICMD_IF_FCMPG_LT;
- goto icmd_if_fcmpg_tail;
- case ICMD_IFGT:
- iptr[0].opc = ICMD_IF_FCMPG_GT;
- goto icmd_if_fcmpg_tail;
- case ICMD_IFLE:
- iptr[0].opc = ICMD_IF_FCMPG_LE;
- goto icmd_if_fcmpg_tail;
- case ICMD_IFGE:
- iptr[0].opc = ICMD_IF_FCMPG_GE;
- goto icmd_if_fcmpg_tail;
- default:
- OPTT2_1(TYPE_FLT, TYPE_INT);
- }
- }
- else
- OPTT2_1(TYPE_FLT, TYPE_INT);
- break;
-
- case ICMD_DCMPL:
- COUNT(count_pcmd_op);
- if ((len > 0) && (iptr[1].val.i == 0)) {
- switch (iptr[1].opc) {
- case ICMD_IFEQ:
- iptr[0].opc = ICMD_IF_DCMPEQ;
- icmd_if_dcmpl_tail:
- iptr[0].op1 = iptr[1].op1;
- iptr[1].opc = ICMD_NOP;
-
- OP2_0(TYPE_DBL);
- tbptr = m->basicblocks +
- m->basicblockindex[iptr[0].op1];
-
- iptr[0].target = (void *) tbptr;
-
- MARKREACHED(tbptr, copy);
- COUNT(count_pcmd_bra);
- break;
- case ICMD_IFNE:
- iptr[0].opc = ICMD_IF_DCMPNE;
- goto icmd_if_dcmpl_tail;
- case ICMD_IFLT:
- iptr[0].opc = ICMD_IF_DCMPL_LT;
- goto icmd_if_dcmpl_tail;
- case ICMD_IFGT:
- iptr[0].opc = ICMD_IF_DCMPL_GT;
- goto icmd_if_dcmpl_tail;
- case ICMD_IFLE:
- iptr[0].opc = ICMD_IF_DCMPL_LE;
- goto icmd_if_dcmpl_tail;
- case ICMD_IFGE:
- iptr[0].opc = ICMD_IF_DCMPL_GE;
- goto icmd_if_dcmpl_tail;
- default:
- OPTT2_1(TYPE_DBL, TYPE_INT);
- }
- }
- else
- OPTT2_1(TYPE_DBL, TYPE_INT);
- break;
-
- case ICMD_DCMPG:
- COUNT(count_pcmd_op);
- if ((len > 0) && (iptr[1].val.i == 0)) {
- switch (iptr[1].opc) {
- case ICMD_IFEQ:
- iptr[0].opc = ICMD_IF_DCMPEQ;
- icmd_if_dcmpg_tail:
- iptr[0].op1 = iptr[1].op1;
- iptr[1].opc = ICMD_NOP;
-
- OP2_0(TYPE_DBL);
- tbptr = m->basicblocks +
- m->basicblockindex[iptr[0].op1];
-
- iptr[0].target = (void *) tbptr;
-
- MARKREACHED(tbptr, copy);
- COUNT(count_pcmd_bra);
- break;
- case ICMD_IFNE:
- iptr[0].opc = ICMD_IF_DCMPNE;
- goto icmd_if_dcmpg_tail;
- case ICMD_IFLT:
- iptr[0].opc = ICMD_IF_DCMPG_LT;
- goto icmd_if_dcmpg_tail;
- case ICMD_IFGT:
- iptr[0].opc = ICMD_IF_DCMPG_GT;
- goto icmd_if_dcmpg_tail;
- case ICMD_IFLE:
- iptr[0].opc = ICMD_IF_DCMPG_LE;
- goto icmd_if_dcmpg_tail;
- case ICMD_IFGE:
- iptr[0].opc = ICMD_IF_DCMPG_GE;
- goto icmd_if_dcmpg_tail;
- default:
- OPTT2_1(TYPE_DBL, TYPE_INT);
- }
- }
- else
- OPTT2_1(TYPE_DBL, TYPE_INT);
- break;
-#else
- case ICMD_FCMPL:
- case ICMD_FCMPG:
- COUNT(count_pcmd_op);
- OPTT2_1(TYPE_FLT, TYPE_INT);
- break;
-
- case ICMD_DCMPL:
- case ICMD_DCMPG:
- COUNT(count_pcmd_op);
- OPTT2_1(TYPE_DBL, TYPE_INT);
- break;
-#endif
-
- /* pop 1 push 1 */
-
- case ICMD_INEG:
- case ICMD_INT2BYTE:
- case ICMD_INT2CHAR:
- case ICMD_INT2SHORT:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_INT, TYPE_INT);
- break;
- case ICMD_LNEG:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_LNG, TYPE_LNG);
- break;
- case ICMD_FNEG:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_FLT, TYPE_FLT);
- break;
- case ICMD_DNEG:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_DBL, TYPE_DBL);
- break;
-
- case ICMD_I2L:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_INT, TYPE_LNG);
- break;
- case ICMD_I2F:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_INT, TYPE_FLT);
- break;
- case ICMD_I2D:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_INT, TYPE_DBL);
- break;
- case ICMD_L2I:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_LNG, TYPE_INT);
- break;
- case ICMD_L2F:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_LNG, TYPE_FLT);
- break;
- case ICMD_L2D:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_LNG, TYPE_DBL);
- break;
- case ICMD_F2I:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_FLT, TYPE_INT);
- break;
- case ICMD_F2L:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_FLT, TYPE_LNG);
- break;
- case ICMD_F2D:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_FLT, TYPE_DBL);
- break;
- case ICMD_D2I:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_DBL, TYPE_INT);
- break;
- case ICMD_D2L:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_DBL, TYPE_LNG);
- break;
- case ICMD_D2F:
- COUNT(count_pcmd_op);
- OP1_1(TYPE_DBL, TYPE_FLT);
- break;
-
- case ICMD_CHECKCAST:
- if (iptr->op1 == 0) {
- /* array type cast-check */
-
- bte = builtintable_get_internal(BUILTIN_arraycheckcast);
- md = bte->md;
-
- if (md->memuse > rd->memuse)
- rd->memuse = md->memuse;
- if (md->argintreguse > rd->argintreguse)
- rd->argintreguse = md->argintreguse;
-
- /* make all stack variables saved */
-
- copy = curstack;
- while (copy) {
- copy->flags |= SAVEDVAR;
- copy = copy->prev;
- }
- }
- OP1_1(TYPE_ADR, TYPE_ADR);
- break;
-
- case ICMD_INSTANCEOF:
- case ICMD_ARRAYLENGTH:
- OP1_1(TYPE_ADR, TYPE_INT);
- break;
-
- case ICMD_NEWARRAY:
- case ICMD_ANEWARRAY:
- OP1_1(TYPE_INT, TYPE_ADR);
- break;
-
- case ICMD_GETFIELD:
- COUNT(count_check_null);
- COUNT(count_pcmd_mem);
- OP1_1(TYPE_ADR, iptr->op1);
- break;
-
- /* pop 0 push 1 */
-
- case ICMD_GETSTATIC:
- COUNT(count_pcmd_mem);
- OP0_1(iptr->op1);
- break;
-
- case ICMD_NEW:
- OP0_1(TYPE_ADR);
- break;
-
- case ICMD_JSR:
- OP0_1(TYPE_ADR);
- tbptr = m->basicblocks + m->basicblockindex[iptr->op1];
-
- iptr[0].target = (void *) tbptr;
-
- /* This is a dirty hack. The typechecker
- * needs it because the OP1_0ANY below
- * overwrites iptr->dst.
- */
- iptr->val.a = (void *) iptr->dst;
-
- tbptr->type = BBTYPE_SBR;
-
- /* We need to check for overflow right here because
- * the pushed value is poped after MARKREACHED. */
- CHECKOVERFLOW;
- MARKREACHED(tbptr, copy);
- OP1_0ANY;
- break;
-
- /* pop many push any */
-
- case ICMD_BUILTIN:
-#if defined(USEBUILTINTABLE)
- builtin:
-#endif
- bte = (builtintable_entry *) iptr->val.a;
- md = bte->md;
- goto _callhandling;
-
- case ICMD_INVOKESTATIC:
- case ICMD_INVOKESPECIAL:
- case ICMD_INVOKEVIRTUAL:
- case ICMD_INVOKEINTERFACE:
- COUNT(count_pcmd_met);
- INSTRUCTION_GET_METHODDESC(iptr,md);
-/* if (lm->flags & ACC_STATIC) */
-/* {COUNT(count_check_null);} */
-
- _callhandling:
-
-/* last_pei = bptr->icount - len - 1; */
-
- i = md->paramcount;
-
- if (md->memuse > rd->memuse)
- rd->memuse = md->memuse;
- if (md->argintreguse > rd->argintreguse)
- rd->argintreguse = md->argintreguse;
- if (md->argfltreguse > rd->argfltreguse)
- rd->argfltreguse = md->argfltreguse;
-
- REQUIRE(i);
-
- copy = curstack;
- for (i-- ; i >= 0; i--) {
-#if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
- /* If we pass float arguments in integer argument registers, we
- * are not allowed to precolor them here. Floats have to be moved
- * to this regs explicitly in codegen().
- * Only arguments that are passed by stack anyway can be precolored
- * (michi 2005/07/24) */
- if (!(copy->flags & SAVEDVAR) &&
- (!IS_FLT_DBL_TYPE(copy->type) || md->params[i].inmemory)) {
-#else
- if (!(copy->flags & SAVEDVAR)) {
-#endif
- copy->varkind = ARGVAR;
- copy->varnum = i;
-
-#if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-#endif
- if (md->params[i].inmemory) {
- copy->flags = INMEMORY;
- copy->regoff = md->params[i].regoff;
- }
- else {
- copy->flags = 0;
- if (IS_FLT_DBL_TYPE(copy->type))
-#if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
- assert(0); /* XXX is this assert ok? */
-#else
- copy->regoff =
- rd->argfltregs[md->params[i].regoff];
-#endif
- else {
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (IS_2_WORD_TYPE(copy->type))
- copy->regoff = PACK_REGS(
- rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
- rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
- else
-#endif
- copy->regoff =
- rd->argintregs[md->params[i].regoff];
- }
- }
-#if defined(ENABLE_INTRP)
- }
-#endif
- }
- copy = copy->prev;
- }
-
- while (copy) {
- copy->flags |= SAVEDVAR;
- copy = copy->prev;
- }
-
- i = md->paramcount;
- POPMANY(i);
- if (md->returntype.type != TYPE_VOID)
- OP0_1(md->returntype.type);
- break;
-
- case ICMD_INLINE_START:
- case ICMD_INLINE_END:
- SETDST;
- break;
-
- case ICMD_MULTIANEWARRAY:
- if (rd->argintreguse < 3)
- rd->argintreguse = 3;
-
- i = iptr->op1;
-
- REQUIRE(i);
-#if defined(SPECIALMEMUSE)
-# if defined(__DARWIN__)
- 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_SIZE_IN_POINTERS + 3))
- rd->memuse = i + LA_SIZE_IN_POINTERS + 3;
-# endif
-#else
-# if defined(__I386__)
- if (rd->memuse < i + 3)
- rd->memuse = i + 3; /* n integer args spilled on stack */
-# elif defined(__MIPS__) && SIZEOF_VOID_P == 4
- if (rd->memuse < i + 2)
- rd->memuse = i + 2; /* 4*4 bytes callee save space */
-# else
- if (rd->memuse < i)
- rd->memuse = i; /* n integer args spilled on stack */
-# endif /* defined(__I386__) */
-#endif
- copy = curstack;
- while (--i >= 0) {
- /* check INT type here? Currently typecheck does this. */
- if (!(copy->flags & SAVEDVAR)) {
- copy->varkind = ARGVAR;
- copy->varnum = i + INT_ARG_CNT;
- copy->flags |= INMEMORY;
-#if defined(SPECIALMEMUSE)
-# if defined(__DARWIN__)
- copy->regoff = i + LA_SIZE_IN_POINTERS + INT_ARG_CNT;
-# else
- copy->regoff = i + LA_SIZE_IN_POINTERS + 3;
-# endif
-#else
-# if defined(__I386__)
- copy->regoff = i + 3;
-# elif defined(__MIPS__) && SIZEOF_VOID_P == 4
- copy->regoff = i + 2;
-# else
- copy->regoff = i;
-# endif /* defined(__I386__) */
-#endif /* defined(SPECIALMEMUSE) */
- }
- copy = copy->prev;
- }
- while (copy) {
- copy->flags |= SAVEDVAR;
- copy = copy->prev;
- }
- i = iptr->op1;
- POPMANY(i);
- OP0_1(TYPE_ADR);
- break;
-
- default:
- *exceptionptr =
- new_internalerror("Unknown ICMD %d", opcode);
- return false;
- } /* switch */
-
- CHECKOVERFLOW;
- iptr++;
- } /* while instructions */
-
- /* set out-stack of block */
-
- bptr->outstack = curstack;
- bptr->outdepth = stackdepth;
-
- /* stack slots at basic block end become interfaces */
-
- i = stackdepth - 1;
- for (copy = curstack; copy; i--, copy = copy->prev) {
- if ((copy->varkind == STACKVAR) && (copy->varnum > i))
- copy->varkind = TEMPVAR;
- else {
- copy->varkind = STACKVAR;
- copy->varnum = i;
- }
- IF_NO_INTRP(
- rd->interfaces[i][copy->type].type = copy->type;
- rd->interfaces[i][copy->type].flags |= copy->flags;
- );
- }
-
- /* check if interface slots at basic block begin must be saved */
-
- IF_NO_INTRP(
- i = bptr->indepth - 1;
- for (copy = bptr->instack; copy; i--, copy = copy->prev) {
- rd->interfaces[i][copy->type].type = copy->type;
- if (copy->varkind == STACKVAR) {
- if (copy->flags & SAVEDVAR)
- rd->interfaces[i][copy->type].flags |= SAVEDVAR;
- }
- }
- );
-
- } /* if */
- else
- superblockend = true;
-
- bptr++;
- } /* while blocks */
- } while (repeat && !deadcode);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat) {
- if (m->basicblockcount > count_max_basic_blocks)
- count_max_basic_blocks = m->basicblockcount;
- count_basic_blocks += m->basicblockcount;
- if (m->instructioncount > count_max_javainstr) count_max_javainstr = m->instructioncount;
- count_javainstr += m->instructioncount;
- if (m->stackcount > count_upper_bound_new_stack)
- count_upper_bound_new_stack = m->stackcount;
- if ((new - m->stack) > count_max_new_stack)
- count_max_new_stack = (new - m->stack);
-
- b_count = m->basicblockcount;
- bptr = m->basicblocks;
- while (--b_count >= 0) {
- if (bptr->flags > BBREACHED) {
- if (bptr->indepth >= 10)
- count_block_stack[10]++;
- else
- count_block_stack[bptr->indepth]++;
- len = bptr->icount;
- if (len < 10)
- count_block_size_distribution[len]++;
- else if (len <= 12)
- count_block_size_distribution[10]++;
- else if (len <= 14)
- count_block_size_distribution[11]++;
- else if (len <= 16)
- count_block_size_distribution[12]++;
- else if (len <= 18)
- count_block_size_distribution[13]++;
- else if (len <= 20)
- count_block_size_distribution[14]++;
- else if (len <= 25)
- count_block_size_distribution[15]++;
- else if (len <= 30)
- count_block_size_distribution[16]++;
- else
- count_block_size_distribution[17]++;
- }
- bptr++;
- }
-
- if (loops == 1)
- count_analyse_iterations[0]++;
- else if (loops == 2)
- count_analyse_iterations[1]++;
- else if (loops == 3)
- count_analyse_iterations[2]++;
- else if (loops == 4)
- count_analyse_iterations[3]++;
- else
- count_analyse_iterations[4]++;
-
- if (m->basicblockcount <= 5)
- count_method_bb_distribution[0]++;
- else if (m->basicblockcount <= 10)
- count_method_bb_distribution[1]++;
- else if (m->basicblockcount <= 15)
- count_method_bb_distribution[2]++;
- else if (m->basicblockcount <= 20)
- count_method_bb_distribution[3]++;
- else if (m->basicblockcount <= 30)
- count_method_bb_distribution[4]++;
- else if (m->basicblockcount <= 40)
- count_method_bb_distribution[5]++;
- else if (m->basicblockcount <= 50)
- count_method_bb_distribution[6]++;
- else if (m->basicblockcount <= 75)
- count_method_bb_distribution[7]++;
- else
- count_method_bb_distribution[8]++;
- }
-#endif /* defined(ENABLE_STATISTICS) */
-
- /* everything's ok */
-
- return true;
-
-#if defined(ENABLE_VERIFIER)
-
-throw_stack_underflow:
- exceptions_throw_verifyerror(m, "Unable to pop operand off an empty stack");
- return false;
-
-throw_stack_overflow:
- exceptions_throw_verifyerror(m, "Stack size too large");
- return false;
-
-throw_stack_depth_error:
- exceptions_throw_verifyerror(m,"Stack depth mismatch");
- return false;
-
-throw_stack_type_error:
- exceptions_throw_verifyerror_for_stack(m, expectedtype);
- return false;
-
-throw_stack_category_error:
- exceptions_throw_verifyerror(m, "Attempt to split long or double on the stack");
- return false;
-
-#endif
-}
-
-
/*
* These are local overrides for various environment variables in Emacs.