Christian Thalinger
Christian Ullrich
- $Id: stack.c 4690 2006-03-27 11:37:46Z twisti $
+ $Id: stack.c 5481 2006-09-12 21:23:56Z edwin $
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
+#include <limits.h>
#include "vm/types.h"
#include "vm/resolve.h"
#include "vm/statistics.h"
#include "vm/stringlocal.h"
+#include "vm/jit/cfg.h"
#include "vm/jit/codegen-common.h"
-#include "vm/jit/disass.h"
+#include "vm/jit/abi.h"
+#include "vm/jit/show.h"
+
+#if defined(ENABLE_DISASSEMBLER)
+# include "vm/jit/disass.h"
+#endif
+
#include "vm/jit/jit.h"
-#include "vm/jit/reg.h"
#include "vm/jit/stack.h"
-#include "vm/jit/allocator/lsra.h"
+#if defined(ENABLE_LSRA)
+# include "vm/jit/allocator/lsra.h"
+#endif
-/* global variables ***********************************************************/
+/*#define STACK_VERBOSE*/
-#if defined(USE_THREADS)
-static java_objectheader *lock_show_icmd;
-#endif
/* macro for saving #ifdefs ***************************************************/
#if defined(ENABLE_INTRP)
+#define IF_INTRP(x) if (opt_intrp) { x }
#define IF_NO_INTRP(x) if (!opt_intrp) { x }
#else
+#define IF_INTRP(x)
#define IF_NO_INTRP(x) { x }
#endif
+#if defined(ENABLE_INTRP)
+#if defined(ENABLE_JIT)
+#define IF_JIT(x) if (!opt_intrp) { x }
+#else
+#define IF_JIT(x)
+#endif
+#else /* !defined(ENABLE_INTRP) */
+#define IF_JIT(x) { x }
+#endif /* defined(ENABLE_INTRP) */
+
+#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)
+#else /* !defined(ENABLE_STATISTICS) */
+#define STATISTICS_STACKDEPTH_DISTRIBUTION(distr)
+#endif
+
+/* stackdata_t *****************************************************************
+
+ This struct holds internal data during stack analysis.
+
+*******************************************************************************/
+
+typedef struct stackdata_t stackdata_t;
+
+struct stackdata_t {
+ basicblock *bptr; /* the current basic block being analysed */
+ stackptr new; /* next free stackelement */
+ s4 vartop; /* next free variable index */
+ s4 localcount; /* number of locals (at the start of var) */
+ s4 varcount; /* total number of variables allocated */
+ varinfo *var; /* variable array (same as jd->var) */
+ methodinfo *m; /* the method being analysed */
+ jitdata *jd; /* current jitdata */
+ basicblock *last_real_block; /* the last block before the empty one */
+ bool repeat; /* if true, iterate the analysis again */
+ exceptiontable **handlers; /* exception handlers for the current block */
+ exceptiontable *extableend; /* points to the last exception entry */
+ stackelement exstack; /* instack for exception handlers */
+};
+
+
+/* macros for allocating/releasing variable indices *****************/
+
+#define GET_NEW_INDEX(sd, new_varindex) \
+ do { \
+ assert((sd).vartop < (sd).varcount); \
+ (new_varindex) = ((sd).vartop)++; \
+ } while (0)
+
+/* Not implemented now - could 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))
+
+
+/* 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.varindex = -1)
+
+#define USE_S1(type1) \
+ do { \
+ REQUIRE(1); \
+ CHECK_BASIC_TYPE(type1, curstack->type); \
+ iptr->s1.varindex = curstack->varnum; \
+ } while (0)
+
+#define USE_S1_ANY \
+ do { \
+ REQUIRE(1); \
+ iptr->s1.varindex = curstack->varnum; \
+ } while (0)
+
+#define USE_S1_S2(type1, type2) \
+ do { \
+ REQUIRE(2); \
+ CHECK_BASIC_TYPE(type1, curstack->prev->type); \
+ CHECK_BASIC_TYPE(type2, curstack->type); \
+ 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.varindex = curstack->varnum; \
+ iptr->s1.varindex = curstack->prev->varnum; \
+ } while (0)
+
+#define USE_S1_S2_S3(type1, type2, type3) \
+ do { \
+ 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.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) \
+ do { \
+ USE_S1(type1); \
+ if (curstack->varkind == UNDEFVAR) \
+ curstack->varkind = TEMPVAR; \
+ curstack = curstack->prev; \
+ } while (0)
+
+#define POP_S1_ANY \
+ do { \
+ USE_S1_ANY; \
+ if (curstack->varkind == UNDEFVAR) \
+ curstack->varkind = TEMPVAR; \
+ curstack = curstack->prev; \
+ } while (0)
+
+#define POP_S1_S2(type1, type2) \
+ do { \
+ USE_S1_S2(type1, type2); \
+ if (curstack->varkind == UNDEFVAR) \
+ curstack->varkind = TEMPVAR; \
+ if (curstack->prev->varkind == UNDEFVAR) \
+ curstack->prev->varkind = TEMPVAR; \
+ curstack = curstack->prev->prev; \
+ } while (0)
+
+#define POP_S1_S2_ANY_ANY \
+ do { \
+ USE_S1_S2_ANY_ANY; \
+ if (curstack->varkind == UNDEFVAR) \
+ curstack->varkind = TEMPVAR; \
+ if (curstack->prev->varkind == UNDEFVAR) \
+ curstack->prev->varkind = TEMPVAR; \
+ curstack = curstack->prev->prev; \
+ } while (0)
+
+#define POP_S1_S2_S3(type1, type2, type3) \
+ do { \
+ USE_S1_S2_S3(type1, type2, type3); \
+ if (curstack->varkind == UNDEFVAR) \
+ curstack->varkind = TEMPVAR; \
+ if (curstack->prev->varkind == UNDEFVAR) \
+ curstack->prev->varkind = TEMPVAR; \
+ if (curstack->prev->prev->varkind == UNDEFVAR) \
+ curstack->prev->prev->varkind = TEMPVAR; \
+ curstack = curstack->prev->prev->prev; \
+ } while (0)
+
+#define CLR_SX \
+ (iptr->sx.val.l = 0)
+
+
+/* macros for setting the destination operand ***********************/
+
+#define CLR_DST \
+ (iptr->dst.varindex = -1)
+
+#define DST(typed, index) \
+ do { \
+ NEWSTACKn((typed),(index)); \
+ curstack->creator = iptr; \
+ iptr->dst.varindex = (index); \
+ } while (0)
+
+#define DST_LOCALVAR(typed, index) \
+ do { \
+ NEWSTACK((typed), LOCALVAR, (index)); \
+ curstack->creator = iptr; \
+ iptr->dst.varindex = (index); \
+ } while (0)
+
+
+/* macro for propagating constant values ****************************/
+
+#define COPY_VAL_AND_TYPE(sd, sindex, dindex) \
+ do { \
+ (sd).var[(dindex)].type = (sd).var[(sindex)].type; \
+ (sd).var[(dindex)].vv = (sd).var[(sindex)].vv; \
+ } while (0) \
+
+
+/* stack modelling macros *******************************************/
+
+#define OP0_1(typed) \
+ do { \
+ CLR_S1; \
+ GET_NEW_VAR(sd, new_index, (typed)); \
+ DST(typed, new_index); \
+ stackdepth++; \
+ } while (0)
+
+#define OP1_0_ANY \
+ do { \
+ POP_S1_ANY; \
+ CLR_DST; \
+ stackdepth--; \
+ } while (0)
+
+#define OP1_BRANCH(type1) \
+ do { \
+ POP_S1(type1); \
+ stackdepth--; \
+ } while (0)
+
+#define OP1_1(type1, typed) \
+ do { \
+ POP_S1(type1); \
+ 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 OP0_0 \
+ do { \
+ CLR_S1; \
+ CLR_DST; \
+ } while (0)
+
+#define OP0_BRANCH \
+ do { \
+ CLR_S1; \
+ } while (0)
+
+#define OP1_0(type1) \
+ do { \
+ POP_S1(type1); \
+ CLR_DST; \
+ stackdepth--; \
+ } while (0)
+
+#define OP2_0(type1, type2) \
+ do { \
+ POP_S1_S2(type1, type2); \
+ CLR_DST; \
+ stackdepth -= 2; \
+ } while (0)
+
+#define OP2_BRANCH(type1, type2) \
+ do { \
+ POP_S1_S2(type1, type2); \
+ stackdepth -= 2; \
+ } while (0)
+
+#define OP2_0_ANY_ANY \
+ do { \
+ POP_S1_S2_ANY_ANY; \
+ CLR_DST; \
+ stackdepth -= 2; \
+ } while (0)
+
+#define OP3_0(type1, type2, type3) \
+ do { \
+ POP_S1_S2_S3(type1, type2, type3); \
+ CLR_DST; \
+ stackdepth -= 3; \
+ } while (0)
+
+#define LOAD(type1, index) \
+ do { \
+ DST_LOCALVAR(type1, index); \
+ stackdepth++; \
+ } while (0)
+
+#define STORE(type1, index) \
+ do { \
+ POP_S1(type1); \
+ stackdepth--; \
+ } while (0)
+
+
+/* macros for DUP elimination ***************************************/
+
+/* XXX replace NEW_VAR with NEW_INDEX */
+#define DUP_SLOT(sp) \
+ do { \
+ GET_NEW_VAR(sd, new_index, (sp)->type); \
+ COPY_VAL_AND_TYPE(sd, (sp)->varnum, new_index); \
+ 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 *********************/
+
+#define BRANCH_TARGET(bt, tempbptr) \
+ do { \
+ tempbptr = BLOCK_OF((bt).insindex); \
+ tempbptr = stack_mark_reached(&sd, tempbptr, curstack, \
+ stackdepth); \
+ if (tempbptr == NULL) \
+ return false; \
+ (bt).block = tempbptr; \
+ } while (0)
+
+#define BRANCH(tempbptr) \
+ BRANCH_TARGET(iptr->dst, tempbptr)
+
+
+/* forward declarations *******************************************************/
+
+static void stack_create_invars(stackdata_t *sd, basicblock *b,
+ stackptr curstack, int stackdepth);
+static void stack_create_invars_from_outvars(stackdata_t *sd, basicblock *b);
+
+#if defined(STACK_VERBOSE)
+static void stack_verbose_show_varinfo(stackdata_t *sd, varinfo *v);
+static void stack_verbose_show_variable(stackdata_t *sd, s4 index);
+static void stack_verbose_show_block(stackdata_t *sd, basicblock *bptr);
+static void stack_verbose_block_enter(stackdata_t *sd, bool reanalyse);
+static void stack_verbose_block_exit(stackdata_t *sd, bool superblockend);
+#endif
+
+
/* stack_init ******************************************************************
Initialized the stack analysis subsystem (called by jit_init).
bool stack_init(void)
{
-#if defined(USE_THREADS)
- /* initialize the show lock */
+ return true;
+}
- lock_show_icmd = NEW(java_objectheader);
-# if defined(NATIVE_THREADS)
- initObjectLock(lock_show_icmd);
-# endif
-#endif
+/* stack_grow_variable_array ***************************************************
- /* everything's ok */
+ Grow the variable array so the given number of additional variables fits in.
- return true;
+ IN:
+ sd...........stack analysis data
+ num..........number of additional variables
+
+*******************************************************************************/
+
+static void stack_grow_variable_array(stackdata_t *sd, s4 num)
+{
+ s4 newcount;
+
+ assert(num >= 0);
+
+ if (num == 0)
+ return;
+
+ /* XXX avoid too many reallocations */
+ newcount = sd->varcount + num;
+
+ sd->var = DMREALLOC(sd->var, varinfo, sd->varcount, newcount);
+ sd->varcount = newcount;
+ sd->jd->var = sd->var;
+ sd->jd->varcount = newcount;
}
-/**********************************************************************/
-/* analyse_stack */
-/**********************************************************************/
-
-/* 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.
- */
+/* stack_append_block **********************************************************
+
+ Append the given block after the last real block of the method (before
+ the pseudo-block at the end).
+
+ IN:
+ sd...........stack analysis data
+ b............the block to append
-methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
+*******************************************************************************/
+
+static void stack_append_block(stackdata_t *sd, basicblock *b)
{
- 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 */
+#if defined(STACK_VERBOSE)
+ printf("APPENDING BLOCK L%0d\n", b->nr);
#endif
- builtintable_entry *bte;
- unresolved_method *um;
- methoddesc *md;
+ b->next = sd->last_real_block->next;
+ sd->last_real_block->next = b;
+ sd->last_real_block = b;
+ sd->jd->new_basicblockcount++;
+}
-#if defined(ENABLE_LSRA)
- m->maxlifetimes = 0;
+
+/* stack_clone_block ***********************************************************
+
+ Create a copy of the given block and insert it at the end of the method.
+
+ CAUTION: This function does not copy the any variables or the instruction
+ list. It _does_, however, reserve space for the block's invars in the
+ variable array.
+
+ IN:
+ sd...........stack analysis data
+ b............the block to clone
+
+ RETURN VALUE:
+ a pointer to the copy
+
+*******************************************************************************/
+
+static basicblock * stack_clone_block(stackdata_t *sd, basicblock *b)
+{
+ basicblock *clone;
+
+ clone = DNEW(basicblock);
+ *clone = *b;
+
+ clone->iinstr = NULL;
+ clone->inlocals = NULL;
+ clone->invars = NULL;
+
+ clone->original = (b->original) ? b->original : b;
+ clone->copied_to = clone->original->copied_to;
+ clone->original->copied_to = clone;
+ clone->nr = sd->m->c_debug_nr++;
+ clone->next = NULL;
+ clone->flags = BBREACHED;
+
+ stack_append_block(sd, clone);
+
+ /* allocate space for the invars of the clone */
+
+ stack_grow_variable_array(sd, b->indepth);
+
+#if defined(STACK_VERBOSE)
+ printf("cloning block L%03d ------> L%03d\n", b->nr, clone->nr);
#endif
- 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->pre_count = 10000;
- STACKRESET;
- NEWXSTACK;
+ return clone;
+}
+
+
+/* stack_create_invars *********************************************************
+
+ Create the invars for the given basic block. Also make a copy of the locals.
+
+ 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;
+ v->vv = sd->var[sp->varnum].vv;
+#if defined(STACK_VERBOSE) && 0
+ printf("\tinvar[%d]: %d\n", i, sd->var[b->invars[i]]);
+#endif
}
-#if CONDITIONAL_LOADCONST
- b_count = m->basicblockcount;
- bptr = m->basicblocks;
- while (--b_count >= 0) {
- if (bptr->icount != 0) {
- iptr = bptr->iinstr + bptr->icount - 1;
- switch (iptr->opc) {
- case ICMD_RET:
- case ICMD_RETURN:
- case ICMD_IRETURN:
- case ICMD_LRETURN:
- case ICMD_FRETURN:
- case ICMD_DRETURN:
- case ICMD_ARETURN:
- case ICMD_ATHROW:
- break;
+ /* copy the current state of the local variables */
- case ICMD_IFEQ:
- case ICMD_IFNE:
- case ICMD_IFLT:
- case ICMD_IFGE:
- case ICMD_IFGT:
- case ICMD_IFLE:
+ v = DMNEW(varinfo, sd->localcount);
+ b->inlocals = v;
+ for (i=0; i<sd->localcount; ++i)
+ *v++ = sd->var[i];
+}
- 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:
+/* stack_create_invars_from_outvars ********************************************
- case ICMD_IF_ACMPEQ:
- case ICMD_IF_ACMPNE:
- bptr[1].pre_count++;
- case ICMD_GOTO:
- m->basicblocks[m->basicblockindex[iptr->op1]].pre_count++;
- break;
+ Create the invars for the given basic block. Also make a copy of the locals.
+ Types are propagated from the outvars of the current block.
- case ICMD_TABLESWITCH:
- s4ptr = iptr->val.a;
- m->basicblocks[m->basicblockindex[*s4ptr++]].pre_count++;
- i = *s4ptr++; /* low */
- i = *s4ptr++ - i + 1; /* high */
- while (--i >= 0) {
- m->basicblocks[m->basicblockindex[*s4ptr++]].pre_count++;
- }
- break;
-
- case ICMD_LOOKUPSWITCH:
- s4ptr = iptr->val.a;
- m->basicblocks[m->basicblockindex[*s4ptr++]].pre_count++;
- i = *s4ptr++; /* count */
- while (--i >= 0) {
- m->basicblocks[m->basicblockindex[s4ptr[1]]].pre_count++;
- s4ptr += 2;
- }
- break;
- default:
- bptr[1].pre_count++;
- break;
- }
+ IN:
+ sd...........stack analysis data
+ b............block to create the invars for
+
+*******************************************************************************/
+
+static void stack_create_invars_from_outvars(stackdata_t *sd, basicblock *b)
+{
+ int i;
+ int n;
+ varinfo *sv, *dv;
+
+ n = sd->bptr->outdepth;
+ assert(sd->vartop + n <= sd->varcount);
+
+ b->indepth = n;
+ b->invars = DMNEW(s4, n);
+
+ if (n) {
+ dv = sd->var + sd->vartop;
+
+ /* allocate the invars */
+
+ for (i=0; i<n; ++i, ++dv) {
+ sv = sd->var + sd->bptr->outvars[i];
+ b->invars[i] = sd->vartop++;
+ dv->type = sv->type;
+ dv->flags = OUTVAR;
+ dv->vv = sv->vv;
}
- bptr++;
}
-#endif /* CONDITIONAL_LOADCONST */
+ /* copy the current state of the local variables */
- do {
- loops++;
- b_count = m->basicblockcount;
- bptr = m->basicblocks;
- superblockend = true;
- repeat = false;
- STACKRESET;
- deadcode = true;
+ dv = DMNEW(varinfo, sd->localcount);
+ b->inlocals = dv;
+ for (i=0; i<sd->localcount; ++i)
+ *dv++ = sd->var[i];
+}
- 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;
+/* stack_check_invars **********************************************************
- 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;
+ Check the current stack against the invars of the given basic block.
+ Depth and types must match.
- bptr->stack = new;
+ IN:
+ sd...........stack analysis data
+ b............block which invars to check against
+ curstack.....current stack top
+ stackdepth...current stack depth
- while (--len >= 0) {
- opcode = iptr->opc;
+ RETURN VALUE:
+ the destinaton block
+ NULL.........a VerifyError has been thrown
-#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;
- m->isleafmethod = false;
- goto builtin;
- }
-# if defined(ENABLE_INTRP)
- }
-# endif
-#endif /* defined(USEBUILTINTABLE) */
-
- switch (opcode) {
+static basicblock * stack_check_invars(stackdata_t *sd, basicblock *b,
+ stackptr curstack, int stackdepth)
+{
+ int i;
+ stackptr sp;
+ basicblock *orig;
+ bool separable;
- /* pop 0 push 0 */
+#if defined(STACK_VERBOSE)
+ printf("stack_check_invars(L%03d)\n", b->nr);
+#endif
- case ICMD_CHECKNULL:
- COUNT(count_check_null);
- case ICMD_NOP:
+ /* find original of b */
+ if (b->original)
+ b = b->original;
+ orig = b;
- case ICMD_IFEQ_ICONST:
- case ICMD_IFNE_ICONST:
- case ICMD_IFLT_ICONST:
- case ICMD_IFGE_ICONST:
- case ICMD_IFGT_ICONST:
- case ICMD_IFLE_ICONST:
- case ICMD_ELSE_ICONST:
- SETDST;
- break;
+#if defined(STACK_VERBOSE)
+ printf("original is L%03d\n", orig->nr);
+#endif
- case ICMD_RET:
-#if defined(ENABLE_INTRP)
- if (!opt_intrp)
+ i = orig->indepth;
+
+ if (i != stackdepth) {
+ exceptions_throw_verifyerror(sd->m, "Stack depth mismatch");
+ return NULL;
+ }
+
+ do {
+ separable = false;
+
+#if defined(STACK_VERBOSE)
+ printf("checking against ");
+ stack_verbose_show_block(sd, b); printf("\n");
#endif
- rd->locals[iptr->op1][TYPE_ADR].type = TYPE_ADR;
- case ICMD_RETURN:
- COUNT(count_pcmd_return);
- SETDST;
- superblockend = true;
+
+ sp = curstack;
+ for (i = orig->indepth; i--; sp = sp->prev) {
+ if (sd->var[b->invars[i]].type != sp->type) {
+ exceptions_throw_verifyerror_for_stack(sd->m,
+ sd->var[b->invars[i]].type);
+ return NULL;
+ }
+
+ if (sp->type == TYPE_RET) {
+ if (sd->var[b->invars[i]].vv.retaddr != sd->var[sp->varnum].vv.retaddr) {
+ separable = true;
+ break;
+ }
+ }
+ }
+
+ if (b->inlocals) {
+ for (i=0; i<sd->localcount; ++i) {
+ if (sd->var[i].type == TYPE_RET && b->inlocals[i].type == TYPE_RET) {
+ if (sd->var[i].vv.retaddr != b->inlocals[i].vv.retaddr) {
+ separable = 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[0].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[1].opc = ICMD_NOP; */
- bptr->icount--;
- len--;
+ if (!separable) {
+ /* XXX mark mixed type variables void */
+ /* XXX cascading collapse? */
+#if defined(STACK_VERBOSE)
+ printf("------> using L%03d\n", b->nr);
+#endif
+ return b;
+ }
+ } while ((b = b->copied_to) != NULL);
- OP1_0(TYPE_INT);
- tbptr = m->basicblocks + m->basicblockindex[iptr->op1];
+ b = stack_clone_block(sd, orig);
+ if (!b)
+ return NULL;
- iptr[0].target = (void *) tbptr;
+ stack_create_invars(sd, b, curstack, stackdepth);
+ return b;
+}
- MARKREACHED(tbptr, copy);
- COUNT(count_pcmd_bra);
- break;
- case ICMD_IF_ICMPLT:
- iptr[0].opc = ICMD_IFLT;
- goto icmd_if_icmp_tail;
- case ICMD_IF_ICMPLE:
- iptr[0].opc = ICMD_IFLE;
- goto icmd_if_icmp_tail;
- case ICMD_IF_ICMPNE:
- iptr[0].opc = ICMD_IFNE;
- goto icmd_if_icmp_tail;
- case ICMD_IF_ICMPGT:
- iptr[0].opc = ICMD_IFGT;
- goto icmd_if_icmp_tail;
- case ICMD_IF_ICMPGE:
- iptr[0].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 /* SUPPORT_CONST_STORE_ZERO_ONLY */
- 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;
- }
+/* stack_check_invars_from_outvars *********************************************
- 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 /* SUPPORT_CONST_STORE_ZERO_ONLY */
-# if defined(ENABLE_INTRP)
- }
- else
- PUSHCONST(TYPE_INT);
-# endif
- break;
+ Check the outvars of the current block against the invars of the given block.
+ Depth and types must match.
- 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 /* SUPPORT_CONST_STORE_ZERO_ONLY */
- 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;
- }
+ IN:
+ sd...........stack analysis data
+ b............block which invars to check against
- 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 /* SUPPORT_CONST_STORE_ZERO_ONLY */
-# if defined(ENABLE_INTRP)
- }
- else
- PUSHCONST(TYPE_INT);
-# endif
- break;
-#endif /* SUPPORT_CONST_STORE */
- default:
- PUSHCONST(TYPE_INT);
- }
- }
- else
- PUSHCONST(TYPE_INT);
- break;
+ RETURN VALUE:
+ the destinaton block
+ NULL.........a VerifyError has been thrown
- 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
- 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;
- 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_DIV */
-#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 */
+static basicblock * stack_check_invars_from_outvars(stackdata_t *sd, basicblock *b)
+{
+ int i;
+ int n;
+ varinfo *sv, *dv;
+ basicblock *orig;
+ bool separable;
+
+#if defined(STACK_VERBOSE)
+ printf("stack_check_invars_from_outvars(L%03d)\n", b->nr);
+#endif
-#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;
- bptr->icount -= 2;
- len -= 2;
- /* iptr[1].opc = ICMD_NOP;
- iptr[2].opc = ICMD_NOP; */
- OP1_0(TYPE_LNG);
- tbptr = m->basicblocks + m->basicblockindex[iptr->op1];
+ /* find original of b */
+ if (b->original)
+ b = b->original;
+ orig = b;
- iptr[0].target = (void *) tbptr;
+#if defined(STACK_VERBOSE)
+ printf("original is L%03d\n", orig->nr);
+#endif
- 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 */
+ i = orig->indepth;
+ n = sd->bptr->outdepth;
-#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 /* SUPPORT_CONST_STORE_ZERO_ONLY */
- 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 /* SUPPORT_CONST_STORE_ZERO_ONLY */
-# if defined(ENABLE_INTRP)
- }
- else
- PUSHCONST(TYPE_LNG);
-# endif
- break;
+ if (i != n) {
+ exceptions_throw_verifyerror(sd->m, "Stack depth mismatch");
+ return NULL;
+ }
- 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 /* SUPPORT_CONST_STORE_ZERO_ONLY */
- 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;
- }
+ do {
+ separable = false;
- 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 /* SUPPORT_CONST_STORE_ZERO_ONLY */
-# if defined(ENABLE_INTRP)
- }
- else
- PUSHCONST(TYPE_LNG);
-# endif
- break;
-#endif /* SUPPORT_CONST_STORE */
- default:
- PUSHCONST(TYPE_LNG);
- }
- }
- else
- PUSHCONST(TYPE_LNG);
- break;
+#if defined(STACK_VERBOSE)
+ printf("checking against ");
+ stack_verbose_show_block(sd, b); printf("\n");
+#endif
- case ICMD_FCONST:
- COUNT(count_pcmd_load);
- PUSHCONST(TYPE_FLT);
+ if (n) {
+ dv = sd->var + b->invars[0];
+
+ for (i=0; i<n; ++i, ++dv) {
+ sv = sd->var + sd->bptr->outvars[i];
+ if (sv->type != dv->type) {
+ exceptions_throw_verifyerror_for_stack(sd->m, dv->type);
+ return NULL;
+ }
+
+ if (dv->type == TYPE_RET) {
+ if (sv->vv.retaddr != dv->vv.retaddr) {
+ separable = true;
break;
+ }
+ }
+ }
+ }
- case ICMD_DCONST:
- COUNT(count_pcmd_load);
- PUSHCONST(TYPE_DBL);
+ if (b->inlocals) {
+ for (i=0; i<sd->localcount; ++i) {
+ if (sd->var[i].type == TYPE_RET && b->inlocals[i].type == TYPE_RET) {
+ if (sd->var[i].vv.retaddr != b->inlocals[i].vv.retaddr) {
+ separable = true;
break;
+ }
+ }
+ }
+ }
- case ICMD_ACONST:
- COUNT(count_pcmd_load);
-#if SUPPORT_CONST_STORE
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
- if ((len > 0) && (iptr->val.a == 0)) {
- switch (iptr[1].opc) {
- case ICMD_AASTORE:
- case ICMD_PUTSTATIC:
- case ICMD_PUTFIELD:
- switch (iptr[1].opc) {
- case ICMD_AASTORE:
- iptr[0].opc = ICMD_AASTORECONST;
- OPTT2_0(TYPE_INT, TYPE_ADR);
- break;
- 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;
- }
+ if (!separable) {
+ /* XXX mark mixed type variables void */
+ /* XXX cascading collapse? */
+#if defined(STACK_VERBOSE)
+ printf("------> using L%03d\n", b->nr);
+#endif
+ return b;
+ }
+ } while ((b = b->copied_to) != NULL);
- iptr[1].opc = ICMD_NOP;
- COUNT(count_pcmd_op);
- break;
+ b = stack_clone_block(sd, orig);
+ if (!b)
+ return NULL;
- default:
- PUSHCONST(TYPE_ADR);
- }
+ stack_create_invars_from_outvars(sd, b);
+ return b;
+}
- }
- else
- 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;
+/* stack_create_instack ********************************************************
- /* pop 2 push 1 */
+ Create the instack of the current basic block.
- 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;
+ IN:
+ sd...........stack analysis data
- 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;
+ RETURN VALUE:
+ the current stack top at the start of the basic block.
- /* 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;
+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;
- 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;
+ /* return the top of the created stack */
+ return sd->new - 1;
+}
- /* pop 1 push 0 store */
- case ICMD_ISTORE:
- case ICMD_LSTORE:
- case ICMD_FSTORE:
- case ICMD_DSTORE:
- case ICMD_ASTORE:
- REQUIRE_1;
+/* stack_mark_reached **********************************************************
- i = opcode - ICMD_ISTORE;
-#if defined(ENABLE_INTRP)
- if (!opt_intrp)
+ Mark the given block reached and propagate the current stack and locals to
+ it. This function specializes the target block, if necessary, and returns
+ a pointer to the specialized target.
+
+ IN:
+ sd...........stack analysis data
+ b............the block to reach
+ curstack.....the current stack top
+ stackdepth...the current stack depth
+
+ RETURN VALUE:
+ a pointer to (a specialized version of) the target
+ NULL.........a VerifyError has been thrown
+
+*******************************************************************************/
+
+static basicblock *stack_mark_reached(stackdata_t *sd, basicblock *b, stackptr curstack, int stackdepth)
+{
+#if defined(STACK_VERBOSE)
+ printf("stack_mark_reached(L%03d from L%03d)\n", b->nr, sd->bptr->nr);
#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]++;
- }
+ /* 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 invars. */
+
+#if defined(STACK_VERBOSE)
+ printf("reached L%03d for the first time\n", b->nr);
#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;
- }
- }
+ stack_create_invars(sd, b, curstack, stackdepth);
- /* 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;
- }
- }
+ b->flags = BBREACHED;
- /* 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 */
+ return b;
+ }
+ else {
+ /* b has been reached before. Check that its invars match. */
- /* 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;
+ return stack_check_invars(sd, b, curstack, stackdepth);
+ }
+}
- STORE(opcode - ICMD_ISTORE);
- break;
- /* pop 3 push 0 */
+/* stack_mark_reached_from_outvars *********************************************
- case ICMD_AASTORE:
- COUNT(count_check_null);
- COUNT(count_check_bound);
- COUNT(count_pcmd_mem);
+ Mark the given block reached and propagate the outvars of the current block
+ and the current locals to it. This function specializes the target block,
+ if necessary, and returns a pointer to the specialized target.
- bte = builtintable_get_internal(BUILTIN_canstore);
- md = bte->md;
+ IN:
+ sd...........stack analysis data
+ b............the block to reach
- if (md->memuse > rd->memuse)
- rd->memuse = md->memuse;
- if (md->argintreguse > rd->argintreguse)
- rd->argintreguse = md->argintreguse;
+ RETURN VALUE:
+ a pointer to (a specialized version of) the target
+ NULL.........a VerifyError has been thrown
- /* make all stack variables saved */
+*******************************************************************************/
- copy = curstack;
- while (copy) {
- copy->flags |= SAVEDVAR;
- copy = copy->prev;
- }
+static basicblock *stack_mark_reached_from_outvars(stackdata_t *sd, basicblock *b)
+{
+#if defined(STACK_VERBOSE)
+ printf("stack_mark_reached_from_outvars(L%03d from L%03d)\n", b->nr, sd->bptr->nr);
+#endif
+ /* mark targets of backward branches */
+ if (b <= sd->bptr)
+ b->bitflags |= BBFLAG_REPLACEMENT;
- OP3TIA_0(TYPE_ADR);
- break;
+ if (b->flags < BBREACHED) {
+ /* b is reached for the first time. Create its invars. */
- 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;
+#if defined(STACK_VERBOSE)
+ printf("reached L%03d for the first time\n", b->nr);
+#endif
- 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;
+ stack_create_invars_from_outvars(sd, b);
- /* pop 1 push 0 */
+ b->flags = BBREACHED;
- 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;
+ return b;
+ }
+ else {
+ /* b has been reached before. Check that its invars match. */
- 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(m, rd, opcode - ICMD_IRETURN,
- curstack);
+ return stack_check_invars_from_outvars(sd, b);
+ }
+}
+
+
+/* stack_reach_next_block ******************************************************
+
+ Mark the following block reached and propagate the outvars of the current block
+ and the current locals to it. This function specializes the target block,
+ if necessary, and returns a pointer to the specialized target.
+
+ IN:
+ sd...........stack analysis data
+
+ RETURN VALUE:
+ a pointer to (a specialized version of) the following block
+ NULL.........a VerifyError has been thrown
+
+*******************************************************************************/
+
+static bool stack_reach_next_block(stackdata_t *sd)
+{
+ basicblock *tbptr;
+ instruction *iptr;
+
+ tbptr = (sd->bptr->original) ? sd->bptr->original : sd->bptr;
+ tbptr = stack_mark_reached_from_outvars(sd, tbptr->next);
+ if (!tbptr)
+ return false;
+
+ if (tbptr != sd->bptr->next) {
+#if defined(STACK_VERBOSE)
+ printf("NEXT IS NON-CONSEQUITIVE L%03d\n", tbptr->nr);
#endif
- COUNT(count_pcmd_return);
- OP1_0(opcode - ICMD_IRETURN);
- superblockend = true;
- break;
+ iptr = sd->bptr->iinstr + sd->bptr->icount - 1;
+ assert(iptr->opc == ICMD_NOP);
+ iptr->opc = ICMD_GOTO;
+ iptr->dst.block = tbptr;
- case ICMD_ATHROW:
- COUNT(count_check_null);
- OP1_0(TYPE_ADR);
- STACKRESET;
- SETDST;
- superblockend = true;
- break;
+ if (tbptr->flags < BBFINISHED)
+ sd->repeat = true; /* XXX check if we really need to repeat */
+ }
- case ICMD_PUTSTATIC:
- COUNT(count_pcmd_mem);
- OP1_0(iptr->op1);
- break;
+ return true;
+}
- /* 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];
+/* stack_reach_handlers ********************************************************
- iptr[0].target = (void *) tbptr;
+ Reach the exception handlers for the current block.
- MARKREACHED(tbptr, copy);
- break;
+ IN:
+ sd...........stack analysis data
- case ICMD_IFEQ:
- case ICMD_IFNE:
- case ICMD_IFLT:
- case ICMD_IFGE:
- case ICMD_IFGT:
- case ICMD_IFLE:
- COUNT(count_pcmd_bra);
-#if CONDITIONAL_LOADCONST
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
- tbptr = m->basicblocks + b_index;
- if ((b_count >= 3) &&
- ((b_index + 2) == m->basicblockindex[iptr[0].op1]) &&
- (tbptr[1].pre_count == 1) &&
- (tbptr[1].iinstr[0].opc == ICMD_ICONST) &&
- (tbptr[1].iinstr[1].opc == ICMD_GOTO) &&
- ((b_index + 3) == m->basicblockindex[tbptr[1].iinstr[1].op1]) &&
- (tbptr[2].pre_count == 1) &&
- (tbptr[2].iinstr[0].opc == ICMD_ICONST) &&
- (tbptr[2].icount==1)) {
- /*printf("tbptr[2].icount=%d\n",tbptr[2].icount);*/
- OP1_1(TYPE_INT, TYPE_INT);
- switch (iptr[0].opc) {
- case ICMD_IFEQ:
- iptr[0].opc = ICMD_IFNE_ICONST;
- break;
- case ICMD_IFNE:
- iptr[0].opc = ICMD_IFEQ_ICONST;
- break;
- case ICMD_IFLT:
- iptr[0].opc = ICMD_IFGE_ICONST;
- break;
- case ICMD_IFGE:
- iptr[0].opc = ICMD_IFLT_ICONST;
- break;
- case ICMD_IFGT:
- iptr[0].opc = ICMD_IFLE_ICONST;
- break;
- case ICMD_IFLE:
- iptr[0].opc = ICMD_IFGT_ICONST;
- break;
- }
-#if 1
- iptr[0].val.i = iptr[1].val.i;
- iptr[1].opc = ICMD_ELSE_ICONST;
- iptr[1].val.i = iptr[3].val.i;
- iptr[2].opc = ICMD_NOP;
- iptr[3].opc = ICMD_NOP;
-#else
- /* HACK: save compare value in iptr[1].op1 */
- iptr[1].op1 = iptr[0].val.i;
- iptr[0].val.i = tbptr[1].iinstr[0].val.i;
- iptr[1].opc = ICMD_ELSE_ICONST;
- iptr[1].val.i = tbptr[2].iinstr[0].val.i;
- tbptr[1].iinstr[0].opc = ICMD_NOP;
- tbptr[1].iinstr[1].opc = ICMD_NOP;
- tbptr[2].iinstr[0].opc = ICMD_NOP;
+ RETURN VALUE:
+ true.........everything ok
+ false........a VerifyError has been thrown
+
+*******************************************************************************/
+
+static bool stack_reach_handlers(stackdata_t *sd)
+{
+ s4 i;
+ basicblock *tbptr;
+
+#if defined(STACK_VERBOSE)
+ printf("reaching exception handlers...\n");
#endif
- tbptr[1].flags = BBDELETED;
- tbptr[2].flags = BBDELETED;
- tbptr[1].icount = 0;
- tbptr[2].icount = 0;
- if (tbptr[3].pre_count == 2) {
- len += tbptr[3].icount + 3;
- bptr->icount += tbptr[3].icount + 3;
- tbptr[3].flags = BBDELETED;
- tbptr[3].icount = 0;
- b_index++;
- }
- else {
- bptr->icount++;
- len ++;
- }
- b_index += 2;
- break;
- }
-# if defined(ENABLE_INTRP)
- }
-# endif
-#endif /* CONDITIONAL_LOADCONST */
+ for (i=0; sd->handlers[i]; ++i) {
+ tbptr = sd->handlers[i]->handler;
- OP1_0(TYPE_INT);
- iptr->val.i = 0;
- tbptr = m->basicblocks + m->basicblockindex[iptr->op1];
+ tbptr->type = BBTYPE_EXH;
+ tbptr->predecessorcount = CFG_UNKNOWN_PREDECESSORS;
- iptr[0].target = (void *) tbptr;
+ /* reach (and specialize) the handler block */
- MARKREACHED(tbptr, copy);
- break;
+ tbptr = stack_mark_reached(sd, tbptr, &(sd->exstack), 1);
- /* pop 0 push 0 branch */
+ if (tbptr == NULL)
+ return false;
- case ICMD_GOTO:
- COUNT(count_pcmd_bra);
- tbptr = m->basicblocks + m->basicblockindex[iptr->op1];
+ sd->handlers[i]->handler = tbptr;
+ }
- iptr[0].target = (void *) tbptr;
+ return true;
+}
- MARKREACHED(tbptr, copy);
- SETDST;
- superblockend = true;
- break;
- /* pop 1 push 0 table branch */
+/* stack_reanalyse_block ******************************************************
- 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 */
+ Re-analyse the current block. This is called if either the block itself
+ has already been analysed before, or the current block is a clone of an
+ already analysed block, and this clone is reached for the first time.
+ In the latter case, this function does all that is necessary for fully
+ cloning the block (cloning the instruction list and variables, etc.).
- tptr = DMNEW(void*, i+1);
- iptr->target = (void *) tptr;
+ IN:
+ sd...........stack analysis data
- tptr[0] = (void *) tbptr;
- tptr++;
+ RETURN VALUE:
+ true.........everything ok
+ false........a VerifyError has been thrown
- while (--i >= 0) {
- tbptr = m->basicblocks + m->basicblockindex[*s4ptr++];
+*******************************************************************************/
- tptr[0] = (void *) tbptr;
- tptr++;
+#define RELOCATE(index) \
+ do { \
+ if ((index) >= blockvarstart) \
+ (index) += blockvarshift; \
+ else if ((index) >= invarstart) \
+ (index) += invarshift; \
+ } while (0)
- MARKREACHED(tbptr, copy);
- }
- SETDST;
- superblockend = true;
- break;
-
- /* pop 1 push 0 table branch */
+bool stack_reanalyse_block(stackdata_t *sd)
+{
+ instruction *iptr;
+ basicblock *b;
+ basicblock *orig;
+ s4 len;
+ s4 invarstart;
+ s4 blockvarstart;
+ s4 invarshift;
+ s4 blockvarshift;
+ s4 i, j;
+ s4 *argp;
+ branch_target_t *table;
+ lookup_target_t *lookup;
+ bool superblockend;
+ bool maythrow;
+ bool cloneinstructions;
+ exceptiontable *ex;
- 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 */
+#if defined(STACK_VERBOSE)
+ stack_verbose_block_enter(sd, true);
+#endif
- tptr = DMNEW(void*, i+1);
- iptr->target = (void *) tptr;
+ b = sd->bptr;
- tptr[0] = (void *) tbptr;
- tptr++;
+ if (!b->iinstr) {
+ orig = b->original;
+ assert(orig != NULL);
- while (--i >= 0) {
- tbptr = m->basicblocks + m->basicblockindex[s4ptr[1]];
+ /* clone the instruction list */
- tptr[0] = (void *) tbptr;
- tptr++;
-
- MARKREACHED(tbptr, copy);
- s4ptr += 2;
- }
- SETDST;
- superblockend = true;
- break;
+ cloneinstructions = true;
- case ICMD_MONITORENTER:
- COUNT(count_check_null);
- case ICMD_MONITOREXIT:
- OP1_0(TYPE_ADR);
- break;
+ assert(orig->iinstr);
+ len = orig->icount;
+ iptr = DMNEW(instruction, len + 1);
- /* pop 2 push 0 branch */
+ MCOPY(iptr, orig->iinstr, instruction, len);
+ iptr[len].opc = ICMD_NOP;
+ b->iinstr = iptr;
+ b->icount = ++len;
- 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;
+ /* allocate space for the clone's block variables */
- MARKREACHED(tbptr, copy);
- break;
+ stack_grow_variable_array(sd, orig->varcount);
- case ICMD_IF_ACMPEQ:
- case ICMD_IF_ACMPNE:
- COUNT(count_pcmd_bra);
- OP2_0(TYPE_ADR);
- tbptr = m->basicblocks + m->basicblockindex[iptr->op1];
+ /* we already have the invars set */
- iptr[0].target = (void *) tbptr;
+ assert(b->indepth == orig->indepth);
- MARKREACHED(tbptr, copy);
- break;
+ /* calculate relocation shifts for invars and block variables */
- /* pop 2 push 0 */
+ if (orig->indepth) {
+ invarstart = orig->invars[0];
+ invarshift = b->invars[0] - invarstart;
+ }
+ else {
+ invarstart = INT_MAX;
+ invarshift = 0;
+ }
+ blockvarstart = orig->varstart;
+ blockvarshift = sd->vartop - blockvarstart;
- case ICMD_PUTFIELD:
- COUNT(count_check_null);
- COUNT(count_pcmd_mem);
- OPTT2_0(iptr->op1,TYPE_ADR);
- break;
+ /* copy block variables */
- 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;
+ b->varstart = sd->vartop;
+ b->varcount = orig->varcount;
+ sd->vartop += b->varcount;
+ MCOPY(sd->var + b->varstart, sd->var + orig->varstart, varinfo, b->varcount);
- /* 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;
+ /* copy outvars */
- 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;
+ b->outdepth = orig->outdepth;
+ b->outvars = DMNEW(s4, orig->outdepth);
+ MCOPY(b->outvars, orig->outvars, s4, orig->outdepth);
- /* 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;
+ /* clone exception handlers */
- 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;
+ for (i=0; sd->handlers[i]; ++i) {
+ ex = DNEW(exceptiontable);
+ ex->handler = sd->handlers[i]->handler;
+ ex->start = b;
+ ex->end = b; /* XXX hack, see end of new_stack_analyse */
+ ex->catchtype = sd->handlers[i]->catchtype;
+ ex->down = NULL;
- /* 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;
- }
+ assert(sd->extableend->down == NULL);
+ sd->extableend->down = ex;
+ sd->extableend = ex;
+ sd->jd->cd->exceptiontablelength++;
+
+ sd->handlers[i] = ex;
+ }
+ }
+ else {
+ cloneinstructions = false;
+ invarshift = 0;
+ blockvarshift = 0;
+ invarstart = sd->vartop;
+ blockvarstart = sd->vartop;
+ iptr = b->iinstr;
+ }
+
+ if (b->original) {
+ /* find exception handlers for the cloned block */
+ len = 0;
+ ex = sd->jd->cd->exceptiontable;
+ for (; ex != NULL; ex = ex->down) {
+ /* XXX the cloned exception handlers have identical */
+ /* start end end blocks. */
+ if ((ex->start == b) && (ex->end == b)) {
+ sd->handlers[len++] = ex;
+ }
+ }
+ sd->handlers[len] = NULL;
+ }
+
+#if defined(STACK_VERBOSE)
+ printf("invarstart = %d, blockvarstart = %d\n", invarstart, blockvarstart);
+ printf("invarshift = %d, blockvarshift = %d\n", invarshift, blockvarshift);
#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;
- }
+
+ /* mark block as finished */
+
+ b->flags = BBFINISHED;
+
+ /* initialize locals at the start of this block */
+
+ if (b->inlocals)
+ MCOPY(sd->var, b->inlocals, varinfo, sd->localcount);
+
+ /* reach exception handlers for this block */
+
+ if (!stack_reach_handlers(sd))
+ return false;
+
+ superblockend = false;
+
+ for (len = b->icount; len--; iptr++) {
+#if defined(STACK_VERBOSE)
+ new_show_icmd(sd->jd, iptr, false, SHOW_STACK);
+ printf("\n");
#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;
+ maythrow = false;
+
+ switch (iptr->opc) {
+ case ICMD_RET:
+ j = iptr->s1.varindex;
+
+ if (sd->var[j].type != TYPE_RET) {
+ exceptions_throw_verifyerror(sd->m, "RET with non-returnAddress value");
+ return false;
+ }
+
+ iptr->dst.block = stack_mark_reached_from_outvars(sd, sd->var[j].vv.retaddr);
+ superblockend = true;
+ break;
+
+ case ICMD_JSR:
+ iptr->sx.s23.s3.jsrtarget.block = stack_mark_reached_from_outvars(sd, iptr->sx.s23.s3.jsrtarget.block);
+ superblockend = true;
+ break;
+
+ case ICMD_RETURN:
+ superblockend = true;
+ break;
+
+ case ICMD_CHECKNULL:
+ case ICMD_PUTSTATICCONST:
+ maythrow = true;
+ break;
+
+ case ICMD_NOP:
+ case ICMD_IINC:
+ case ICMD_INLINE_START:
+ case ICMD_INLINE_END:
+ case ICMD_INLINE_GOTO:
+ break;
+
+ case ICMD_GOTO:
+ iptr->dst.block = stack_mark_reached_from_outvars(sd, iptr->dst.block);
+ superblockend = true;
+ break;
+
+ /* pop 0 push 1 const */
+
+ case ICMD_ACONST:
+ maythrow = true;
+ case ICMD_ICONST:
+ case ICMD_LCONST:
+ case ICMD_FCONST:
+ case ICMD_DCONST:
+
+ /* pop 0 push 1 load */
+
+ case ICMD_ILOAD:
+ case ICMD_LLOAD:
+ case ICMD_FLOAD:
+ case ICMD_DLOAD:
+ case ICMD_ALOAD:
+ RELOCATE(iptr->dst.varindex);
+ break;
+
+ /* pop 2 push 1 */
+
+ case ICMD_IALOAD:
+ case ICMD_LALOAD:
+ case ICMD_FALOAD:
+ case ICMD_DALOAD:
+ case ICMD_AALOAD:
+ case ICMD_BALOAD:
+ case ICMD_CALOAD:
+ case ICMD_SALOAD:
+ RELOCATE(iptr->sx.s23.s2.varindex);
+ RELOCATE(iptr->s1.varindex);
+ RELOCATE(iptr->dst.varindex);
+ maythrow = true;
+ break;
+
+ /* pop 3 push 0 */
+
+ case ICMD_IASTORE:
+ case ICMD_LASTORE:
+ case ICMD_FASTORE:
+ case ICMD_DASTORE:
+ case ICMD_AASTORE:
+ case ICMD_BASTORE:
+ case ICMD_CASTORE:
+ case ICMD_SASTORE:
+ RELOCATE(iptr->sx.s23.s3.varindex);
+ RELOCATE(iptr->sx.s23.s2.varindex);
+ RELOCATE(iptr->s1.varindex);
+ maythrow = true;
+ break;
+
+ /* pop 1 push 0 store */
+
+ case ICMD_ISTORE:
+ case ICMD_LSTORE:
+ case ICMD_FSTORE:
+ case ICMD_DSTORE:
+ case ICMD_ASTORE:
+ RELOCATE(iptr->s1.varindex);
+
+ j = iptr->dst.varindex;
+ COPY_VAL_AND_TYPE(*sd, iptr->s1.varindex, j);
+ break;
+
+ /* pop 1 push 0 */
+
+ case ICMD_ARETURN:
+ case ICMD_ATHROW:
+ maythrow = true;
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_FRETURN:
+ case ICMD_DRETURN:
+ RELOCATE(iptr->s1.varindex);
+ superblockend = true;
+ break;
+
+ case ICMD_PUTSTATIC:
+ case ICMD_PUTFIELDCONST:
+ maythrow = true;
+ case ICMD_POP:
+ RELOCATE(iptr->s1.varindex);
+ break;
+
+ /* pop 1 push 0 branch */
+
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
+
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
+
+ case ICMD_IF_LEQ:
+ case ICMD_IF_LNE:
+ case ICMD_IF_LLT:
+ case ICMD_IF_LGE:
+ case ICMD_IF_LGT:
+ case ICMD_IF_LLE:
+ RELOCATE(iptr->s1.varindex);
+ iptr->dst.block = stack_mark_reached_from_outvars(sd, iptr->dst.block);
+ break;
+
+ /* pop 1 push 0 table branch */
+
+ case ICMD_TABLESWITCH:
+ i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1 + 1;
+
+ if (cloneinstructions) {
+ table = DMNEW(branch_target_t, i);
+ MCOPY(table, iptr->dst.table, branch_target_t, i);
+ iptr->dst.table = table;
+ }
+ else {
+ table = iptr->dst.table;
+ }
+
+ RELOCATE(iptr->s1.varindex);
+ while (i--) {
+ table->block = stack_mark_reached_from_outvars(sd, table->block);
+ table++;
+ }
+ superblockend = true;
+ break;
+
+ case ICMD_LOOKUPSWITCH:
+ i = iptr->sx.s23.s2.lookupcount;
+ if (cloneinstructions) {
+ lookup = DMNEW(lookup_target_t, i);
+ MCOPY(lookup, iptr->dst.lookup, lookup_target_t, i);
+ iptr->dst.lookup = lookup;
+ }
+ else {
+ lookup = iptr->dst.lookup;
+ }
+ RELOCATE(iptr->s1.varindex);
+ while (i--) {
+ lookup->target.block = stack_mark_reached_from_outvars(sd, lookup->target.block);
+ lookup++;
+ }
+ iptr->sx.s23.s3.lookupdefault.block = stack_mark_reached_from_outvars(sd, iptr->sx.s23.s3.lookupdefault.block);
+ superblockend = true;
+ break;
+
+ case ICMD_MONITORENTER:
+ case ICMD_MONITOREXIT:
+ RELOCATE(iptr->s1.varindex);
+ maythrow = true;
+ 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:
+
+ case ICMD_IF_LCMPEQ:
+ case ICMD_IF_LCMPNE:
+ case ICMD_IF_LCMPLT:
+ case ICMD_IF_LCMPGE:
+ case ICMD_IF_LCMPGT:
+ case ICMD_IF_LCMPLE:
+
+ case ICMD_IF_FCMPEQ:
+ case ICMD_IF_FCMPNE:
+
+ case ICMD_IF_FCMPL_LT:
+ case ICMD_IF_FCMPL_GE:
+ case ICMD_IF_FCMPL_GT:
+ case ICMD_IF_FCMPL_LE:
+
+ case ICMD_IF_FCMPG_LT:
+ case ICMD_IF_FCMPG_GE:
+ case ICMD_IF_FCMPG_GT:
+ case ICMD_IF_FCMPG_LE:
+
+ case ICMD_IF_DCMPEQ:
+ case ICMD_IF_DCMPNE:
+
+ case ICMD_IF_DCMPL_LT:
+ case ICMD_IF_DCMPL_GE:
+ case ICMD_IF_DCMPL_GT:
+ case ICMD_IF_DCMPL_LE:
+
+ case ICMD_IF_DCMPG_LT:
+ case ICMD_IF_DCMPG_GE:
+ case ICMD_IF_DCMPG_GT:
+ case ICMD_IF_DCMPG_LE:
+
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+ RELOCATE(iptr->sx.s23.s2.varindex);
+ RELOCATE(iptr->s1.varindex);
+ iptr->dst.block = stack_mark_reached_from_outvars(sd, iptr->dst.block);
+ break;
+
+ /* pop 2 push 0 */
+
+ case ICMD_PUTFIELD:
+ case ICMD_IASTORECONST:
+ case ICMD_LASTORECONST:
+ case ICMD_AASTORECONST:
+ case ICMD_BASTORECONST:
+ case ICMD_CASTORECONST:
+ case ICMD_SASTORECONST:
+ maythrow = true;
+ case ICMD_POP2:
+ RELOCATE(iptr->sx.s23.s2.varindex);
+ RELOCATE(iptr->s1.varindex);
+ break;
+
+ /* pop 0 push 1 copy */
+
+ case ICMD_COPY:
+ case ICMD_MOVE:
+ RELOCATE(iptr->dst.varindex);
+ RELOCATE(iptr->s1.varindex);
+ COPY_VAL_AND_TYPE(*sd, iptr->s1.varindex, iptr->dst.varindex);
+ break;
+
+ /* pop 2 push 1 */
+
+ case ICMD_IDIV:
+ case ICMD_IREM:
+ case ICMD_LDIV:
+ case ICMD_LREM:
+ maythrow = true;
+ case ICMD_IADD:
+ case ICMD_ISUB:
+ case ICMD_IMUL:
+ case ICMD_ISHL:
+ case ICMD_ISHR:
+ case ICMD_IUSHR:
+ case ICMD_IAND:
+ case ICMD_IOR:
+ case ICMD_IXOR:
+ case ICMD_LADD:
+ case ICMD_LSUB:
+ case ICMD_LMUL:
+ case ICMD_LOR:
+ case ICMD_LAND:
+ case ICMD_LXOR:
+ case ICMD_LSHL:
+ case ICMD_LSHR:
+ case ICMD_LUSHR:
+ case ICMD_FADD:
+ case ICMD_FSUB:
+ case ICMD_FMUL:
+ case ICMD_FDIV:
+ case ICMD_FREM:
+ case ICMD_DADD:
+ case ICMD_DSUB:
+ case ICMD_DMUL:
+ case ICMD_DDIV:
+ case ICMD_DREM:
+ case ICMD_LCMP:
+ case ICMD_FCMPL:
+ case ICMD_FCMPG:
+ case ICMD_DCMPL:
+ case ICMD_DCMPG:
+ RELOCATE(iptr->sx.s23.s2.varindex);
+ RELOCATE(iptr->s1.varindex);
+ RELOCATE(iptr->dst.varindex);
+ break;
+
+ /* pop 1 push 1 */
+
+ case ICMD_CHECKCAST:
+ case ICMD_ARRAYLENGTH:
+ case ICMD_INSTANCEOF:
+ case ICMD_NEWARRAY:
+ case ICMD_ANEWARRAY:
+ maythrow = true;
+ case ICMD_GETFIELD:
+ case ICMD_IADDCONST:
+ case ICMD_ISUBCONST:
+ case ICMD_IMULCONST:
+ case ICMD_IMULPOW2:
+ case ICMD_IDIVPOW2:
+ case ICMD_IREMPOW2:
+ case ICMD_IANDCONST:
+ case ICMD_IORCONST:
+ case ICMD_IXORCONST:
+ case ICMD_ISHLCONST:
+ case ICMD_ISHRCONST:
+ case ICMD_IUSHRCONST:
+ case ICMD_LADDCONST:
+ case ICMD_LSUBCONST:
+ case ICMD_LMULCONST:
+ case ICMD_LMULPOW2:
+ case ICMD_LDIVPOW2:
+ case ICMD_LREMPOW2:
+ case ICMD_LANDCONST:
+ case ICMD_LORCONST:
+ case ICMD_LXORCONST:
+ case ICMD_LSHLCONST:
+ case ICMD_LSHRCONST:
+ case ICMD_LUSHRCONST:
+ case ICMD_INEG:
+ case ICMD_INT2BYTE:
+ case ICMD_INT2CHAR:
+ case ICMD_INT2SHORT:
+ case ICMD_LNEG:
+ case ICMD_FNEG:
+ case ICMD_DNEG:
+ case ICMD_I2L:
+ case ICMD_I2F:
+ case ICMD_I2D:
+ case ICMD_L2I:
+ case ICMD_L2F:
+ case ICMD_L2D:
+ case ICMD_F2I:
+ case ICMD_F2L:
+ case ICMD_F2D:
+ case ICMD_D2I:
+ case ICMD_D2L:
+ case ICMD_D2F:
+ RELOCATE(iptr->s1.varindex);
+ RELOCATE(iptr->dst.varindex);
+ break;
+
+ /* pop 0 push 1 */
+
+ case ICMD_GETSTATIC:
+ case ICMD_NEW:
+ maythrow = true;
+ RELOCATE(iptr->dst.varindex);
+ break;
+
+ /* pop many push any */
+
+ case ICMD_INVOKESTATIC:
+ case ICMD_INVOKESPECIAL:
+ case ICMD_INVOKEVIRTUAL:
+ case ICMD_INVOKEINTERFACE:
+ case ICMD_BUILTIN:
+ case ICMD_MULTIANEWARRAY:
+ i = iptr->s1.argcount;
+ if (cloneinstructions) {
+ argp = DMNEW(s4, i);
+ MCOPY(argp, iptr->sx.s23.s2.args, s4, i);
+ iptr->sx.s23.s2.args = argp;
+ }
+ else {
+ argp = iptr->sx.s23.s2.args;
+ }
+
+ maythrow = true;
+ while (--i >= 0) {
+ RELOCATE(*argp);
+ argp++;
+ }
+ RELOCATE(iptr->dst.varindex);
+ break;
+
+ default:
+ *exceptionptr =
+ new_internalerror("Unknown ICMD %d during stack re-analysis",
+ iptr->opc);
+ return false;
+ } /* switch */
+
+#if defined(STACK_VERBOSE)
+ new_show_icmd(sd->jd, iptr, false, SHOW_STACK);
+ printf("\n");
+#endif
+ }
+
+ /* relocate outvars */
+
+ for (i=0; i<b->outdepth; ++i) {
+ RELOCATE(b->outvars[i]);
+ }
+
+#if defined(STACK_VERBOSE)
+ stack_verbose_block_exit(sd, superblockend);
+#endif
+
+ /* propagate to the next block */
+
+ if (!superblockend)
+ if (!stack_reach_next_block(sd))
+ 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)
+{
+ methodinfo *m; /* method being analyzed */
+ codeinfo *code;
+ codegendata *cd;
+ registerdata *rd;
+ stackdata_t sd;
+ int b_index; /* basic block index */
+ int stackdepth;
+ stackptr curstack; /* current stack top */
+ 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 deadcode; /* true if no live code has been reached */
+ instruction *iptr; /* the current instruction */
+ basicblock *tbptr;
+ basicblock *original;
+ exceptiontable *ex;
+
+ 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)
+ int expectedtype; /* used by CHECK_BASIC_TYPE */
+#endif
+ builtintable_entry *bte;
+ methoddesc *md;
+ constant_FMIref *fmiref;
+#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);
+#endif
+
+ /* get required compiler data - initialization */
+
+ m = jd->m;
+ code = jd->code;
+ cd = jd->cd;
+ rd = jd->rd;
+
+ /* initialize the stackdata_t struct */
+
+ sd.m = m;
+ sd.jd = jd;
+ sd.varcount = jd->varcount;
+ sd.vartop = jd->vartop;
+ sd.localcount = jd->localcount;
+ sd.var = jd->var;
+ sd.handlers = DMNEW(exceptiontable *, cd->exceptiontablelength + 1);
+ sd.exstack.type = TYPE_ADR;
+ sd.exstack.prev = NULL;
+ sd.exstack.varnum = 0; /* XXX do we need a real variable index here? */
+
+#if defined(ENABLE_LSRA)
+ m->maxlifetimes = 0;
+#endif
+
+#if defined(ENABLE_STATISTICS)
+ iteration_count = 0;
+#endif
+
+ /* find the last real basic block */
+
+ sd.last_real_block = NULL;
+ tbptr = jd->new_basicblocks;
+ while (tbptr->next) {
+ sd.last_real_block = tbptr;
+ tbptr = tbptr->next;
+ }
+ assert(sd.last_real_block);
+
+ /* find the last exception handler */
+
+ if (cd->exceptiontablelength)
+ sd.extableend = cd->exceptiontable + cd->exceptiontablelength - 1;
+ else
+ sd.extableend = NULL;
+
+ /* init jd->interface_map */
+
+ 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 */
+
+ jd->new_basicblocks[0].flags = BBREACHED;
+ jd->new_basicblocks[0].invars = NULL;
+ jd->new_basicblocks[0].indepth = 0;
+
+ /* stack analysis loop (until fixpoint reached) **************************/
+
+ do {
+#if defined(ENABLE_STATISTICS)
+ iteration_count++;
+#endif
+
+ /* initialize loop over basic blocks */
+
+ sd.bptr = jd->new_basicblocks;
+ superblockend = true;
+ sd.repeat = false;
+ curstack = NULL; stackdepth = 0;
+ deadcode = true;
+
+ /* iterate over basic blocks *****************************************/
+
+ for (; sd.bptr; sd.bptr = sd.bptr->next) {
+
+ if (sd.bptr->flags == BBDELETED) {
+ /* This block has been deleted - do nothing. */
+
+ continue;
+ }
+
+ 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. */
+
+ sd.repeat = true;
+ continue;
+ }
+
+ if (sd.bptr->flags > BBREACHED) {
+ /* This block is already finished. */
+
+ superblockend = true;
+ continue;
+ }
+
+ if (sd.bptr->original && sd.bptr->original->flags < BBFINISHED) {
+ /* This block is a clone and the original has not been */
+ /* analysed, yet. Analyse it on the next iteration. */
+
+ sd.repeat = true;
+ continue;
+ }
+
+ /* 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. */
+
+ /* We know that sd.bptr->flags == BBREACHED. */
+ /* This block has been reached before. */
+
+ assert(sd.bptr->flags == BBREACHED);
+ stackdepth = sd.bptr->indepth;
+
+ /* find exception handlers for this block */
+
+ /* determine the active exception handlers for this block */
+ /* XXX could use a faster algorithm with sorted lists or */
+ /* something? */
+
+ original = (sd.bptr->original) ? sd.bptr->original : sd.bptr;
+
+ len = 0;
+ ex = cd->exceptiontable;
+ for (; ex != NULL; ex = ex->down) {
+ if ((ex->start <= original) && (ex->end > original)) {
+ sd.handlers[len++] = ex;
+ }
+ }
+ sd.handlers[len] = NULL;
+
+
+ /* reanalyse cloned block */
+
+ if (sd.bptr->original) {
+ if (!stack_reanalyse_block(&sd))
+ return false;
+ continue;
+ }
+
+ /* reset the new pointer for allocating stackslots */
+
+ sd.new = jd->new_stack;
+
+ /* create the instack of this block */
+
+ curstack = stack_create_instack(&sd);
+
+ /* initialize locals at the start of this block */
+
+ if (sd.bptr->inlocals)
+ MCOPY(sd.var, sd.bptr->inlocals, varinfo, sd.localcount);
+
+ /* set up local variables for analyzing this block */
+
+ deadcode = false;
+ superblockend = false;
+ 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 */
+
+ coalescing_boundary = sd.new;
+ for( i = 0; i < cd->maxlocals; i++)
+ last_store_boundary[i] = sd.new;
+
+ /* remember the start of this block's variables */
+
+ sd.bptr->varstart = sd.vartop;
+
+#if defined(STACK_VERBOSE)
+ stack_verbose_block_enter(&sd, false);
+#endif
+
+ /* reach exception handlers for this block */
+
+ if (!stack_reach_handlers(&sd))
+ return false;
+
+ /* 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("%2d(%d", copy->varnum, copy->type);
+ if (IS_OUTVAR(copy))
+ printf("S");
+ if (IS_PREALLOC(copy))
+ printf("A");
+ printf(") ");
+ }
+ printf("\n");
+#endif
+
+ /* fetch the current opcode */
+
+ opcode = iptr->opc;
+
+ /* automatically replace some ICMDs with builtins */
+
+#if defined(USEBUILTINTABLE)
+ IF_NO_INTRP(
+ bte = builtintable_get_automatic(opcode);
+
+ if (bte && bte->opcode == opcode) {
+ iptr->opc = ICMD_BUILTIN;
+ iptr->flags.bits = 0;
+ iptr->sx.s23.s3.bte = bte;
+ /* iptr->line is already set */
+ jd->isleafmethod = false;
+ goto icmd_BUILTIN;
+ }
+ );
+#endif /* defined(USEBUILTINTABLE) */
+
+ /* main opcode switch *************************************/
+
+ switch (opcode) {
+
+ /* pop 0 push 0 */
+
+ case ICMD_NOP:
+icmd_NOP:
+ CLR_SX;
+ OP0_0;
+ break;
+
+ case ICMD_CHECKNULL:
+ coalescing_boundary = sd.new;
+ COUNT(count_check_null);
+ USE_S1(TYPE_ADR);
+ CLR_SX;
+ CLR_DST; /* XXX live through? */
+ break;
+
+ case ICMD_RET:
+ j = iptr->s1.varindex =
+ jd->local_map[iptr->s1.varindex * 5 + TYPE_ADR];
+
+ if (sd.var[j].type != TYPE_RET) {
+ exceptions_throw_verifyerror(m, "RET with non-returnAddress value");
+ return false;
+ }
+
+ CLR_SX;
+
+ iptr->dst.block = stack_mark_reached(&sd, sd.var[j].vv.retaddr, curstack, stackdepth);
+#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;
+ OP0_0;
+ superblockend = true;
+ break;
+
+
+ /* pop 0 push 1 const */
+
+ /************************** ICONST OPTIMIZATIONS **************************/
+
+ case ICMD_ICONST:
+ COUNT(count_pcmd_load);
+ if (len == 0)
+ goto normal_ICONST;
+
+ switch (iptr[1].opc) {
+ case ICMD_IADD:
+ iptr->opc = ICMD_IADDCONST;
+ /* FALLTHROUGH */
+
+ icmd_iconst_tail:
+ iptr[1].opc = ICMD_NOP;
+ OP1_1(TYPE_INT, TYPE_INT);
+ COUNT(count_pcmd_op);
+ break;
+
+ case ICMD_ISUB:
+ iptr->opc = ICMD_ISUBCONST;
+ goto icmd_iconst_tail;
+#if SUPPORT_CONST_MUL
+ case ICMD_IMUL:
+ iptr->opc = ICMD_IMULCONST;
+ goto icmd_iconst_tail;
+#else /* SUPPORT_CONST_MUL */
+ case ICMD_IMUL:
+ if (iptr->sx.val.i == 0x00000002)
+ iptr->sx.val.i = 1;
+ else if (iptr->sx.val.i == 0x00000004)
+ iptr->sx.val.i = 2;
+ else if (iptr->sx.val.i == 0x00000008)
+ iptr->sx.val.i = 3;
+ else if (iptr->sx.val.i == 0x00000010)
+ iptr->sx.val.i = 4;
+ else if (iptr->sx.val.i == 0x00000020)
+ iptr->sx.val.i = 5;
+ else if (iptr->sx.val.i == 0x00000040)
+ iptr->sx.val.i = 6;
+ else if (iptr->sx.val.i == 0x00000080)
+ iptr->sx.val.i = 7;
+ else if (iptr->sx.val.i == 0x00000100)
+ iptr->sx.val.i = 8;
+ else if (iptr->sx.val.i == 0x00000200)
+ iptr->sx.val.i = 9;
+ else if (iptr->sx.val.i == 0x00000400)
+ iptr->sx.val.i = 10;
+ else if (iptr->sx.val.i == 0x00000800)
+ iptr->sx.val.i = 11;
+ else if (iptr->sx.val.i == 0x00001000)
+ iptr->sx.val.i = 12;
+ else if (iptr->sx.val.i == 0x00002000)
+ iptr->sx.val.i = 13;
+ else if (iptr->sx.val.i == 0x00004000)
+ iptr->sx.val.i = 14;
+ else if (iptr->sx.val.i == 0x00008000)
+ iptr->sx.val.i = 15;
+ else if (iptr->sx.val.i == 0x00010000)
+ iptr->sx.val.i = 16;
+ else if (iptr->sx.val.i == 0x00020000)
+ iptr->sx.val.i = 17;
+ else if (iptr->sx.val.i == 0x00040000)
+ iptr->sx.val.i = 18;
+ else if (iptr->sx.val.i == 0x00080000)
+ iptr->sx.val.i = 19;
+ else if (iptr->sx.val.i == 0x00100000)
+ iptr->sx.val.i = 20;
+ else if (iptr->sx.val.i == 0x00200000)
+ iptr->sx.val.i = 21;
+ else if (iptr->sx.val.i == 0x00400000)
+ iptr->sx.val.i = 22;
+ else if (iptr->sx.val.i == 0x00800000)
+ iptr->sx.val.i = 23;
+ else if (iptr->sx.val.i == 0x01000000)
+ iptr->sx.val.i = 24;
+ else if (iptr->sx.val.i == 0x02000000)
+ iptr->sx.val.i = 25;
+ else if (iptr->sx.val.i == 0x04000000)
+ iptr->sx.val.i = 26;
+ else if (iptr->sx.val.i == 0x08000000)
+ iptr->sx.val.i = 27;
+ else if (iptr->sx.val.i == 0x10000000)
+ iptr->sx.val.i = 28;
+ else if (iptr->sx.val.i == 0x20000000)
+ iptr->sx.val.i = 29;
+ else if (iptr->sx.val.i == 0x40000000)
+ iptr->sx.val.i = 30;
+ else if (iptr->sx.val.i == 0x80000000)
+ iptr->sx.val.i = 31;
+ else
+ goto normal_ICONST;
+
+ iptr->opc = ICMD_IMULPOW2;
+ goto icmd_iconst_tail;
+#endif /* SUPPORT_CONST_MUL */
+ case ICMD_IDIV:
+ if (iptr->sx.val.i == 0x00000002)
+ iptr->sx.val.i = 1;
+ else if (iptr->sx.val.i == 0x00000004)
+ iptr->sx.val.i = 2;
+ else if (iptr->sx.val.i == 0x00000008)
+ iptr->sx.val.i = 3;
+ else if (iptr->sx.val.i == 0x00000010)
+ iptr->sx.val.i = 4;
+ else if (iptr->sx.val.i == 0x00000020)
+ iptr->sx.val.i = 5;
+ else if (iptr->sx.val.i == 0x00000040)
+ iptr->sx.val.i = 6;
+ else if (iptr->sx.val.i == 0x00000080)
+ iptr->sx.val.i = 7;
+ else if (iptr->sx.val.i == 0x00000100)
+ iptr->sx.val.i = 8;
+ else if (iptr->sx.val.i == 0x00000200)
+ iptr->sx.val.i = 9;
+ else if (iptr->sx.val.i == 0x00000400)
+ iptr->sx.val.i = 10;
+ else if (iptr->sx.val.i == 0x00000800)
+ iptr->sx.val.i = 11;
+ else if (iptr->sx.val.i == 0x00001000)
+ iptr->sx.val.i = 12;
+ else if (iptr->sx.val.i == 0x00002000)
+ iptr->sx.val.i = 13;
+ else if (iptr->sx.val.i == 0x00004000)
+ iptr->sx.val.i = 14;
+ else if (iptr->sx.val.i == 0x00008000)
+ iptr->sx.val.i = 15;
+ else if (iptr->sx.val.i == 0x00010000)
+ iptr->sx.val.i = 16;
+ else if (iptr->sx.val.i == 0x00020000)
+ iptr->sx.val.i = 17;
+ else if (iptr->sx.val.i == 0x00040000)
+ iptr->sx.val.i = 18;
+ else if (iptr->sx.val.i == 0x00080000)
+ iptr->sx.val.i = 19;
+ else if (iptr->sx.val.i == 0x00100000)
+ iptr->sx.val.i = 20;
+ else if (iptr->sx.val.i == 0x00200000)
+ iptr->sx.val.i = 21;
+ else if (iptr->sx.val.i == 0x00400000)
+ iptr->sx.val.i = 22;
+ else if (iptr->sx.val.i == 0x00800000)
+ iptr->sx.val.i = 23;
+ else if (iptr->sx.val.i == 0x01000000)
+ iptr->sx.val.i = 24;
+ else if (iptr->sx.val.i == 0x02000000)
+ iptr->sx.val.i = 25;
+ else if (iptr->sx.val.i == 0x04000000)
+ iptr->sx.val.i = 26;
+ else if (iptr->sx.val.i == 0x08000000)
+ iptr->sx.val.i = 27;
+ else if (iptr->sx.val.i == 0x10000000)
+ iptr->sx.val.i = 28;
+ else if (iptr->sx.val.i == 0x20000000)
+ iptr->sx.val.i = 29;
+ else if (iptr->sx.val.i == 0x40000000)
+ iptr->sx.val.i = 30;
+ else if (iptr->sx.val.i == 0x80000000)
+ iptr->sx.val.i = 31;
+ else
+ goto normal_ICONST;
+
+ iptr->opc = ICMD_IDIVPOW2;
+ goto icmd_iconst_tail;
+
+ case ICMD_IREM:
+ /*log_text("stack.c: ICMD_ICONST/ICMD_IREM");*/
+ if ((iptr->sx.val.i == 0x00000002) ||
+ (iptr->sx.val.i == 0x00000004) ||
+ (iptr->sx.val.i == 0x00000008) ||
+ (iptr->sx.val.i == 0x00000010) ||
+ (iptr->sx.val.i == 0x00000020) ||
+ (iptr->sx.val.i == 0x00000040) ||
+ (iptr->sx.val.i == 0x00000080) ||
+ (iptr->sx.val.i == 0x00000100) ||
+ (iptr->sx.val.i == 0x00000200) ||
+ (iptr->sx.val.i == 0x00000400) ||
+ (iptr->sx.val.i == 0x00000800) ||
+ (iptr->sx.val.i == 0x00001000) ||
+ (iptr->sx.val.i == 0x00002000) ||
+ (iptr->sx.val.i == 0x00004000) ||
+ (iptr->sx.val.i == 0x00008000) ||
+ (iptr->sx.val.i == 0x00010000) ||
+ (iptr->sx.val.i == 0x00020000) ||
+ (iptr->sx.val.i == 0x00040000) ||
+ (iptr->sx.val.i == 0x00080000) ||
+ (iptr->sx.val.i == 0x00100000) ||
+ (iptr->sx.val.i == 0x00200000) ||
+ (iptr->sx.val.i == 0x00400000) ||
+ (iptr->sx.val.i == 0x00800000) ||
+ (iptr->sx.val.i == 0x01000000) ||
+ (iptr->sx.val.i == 0x02000000) ||
+ (iptr->sx.val.i == 0x04000000) ||
+ (iptr->sx.val.i == 0x08000000) ||
+ (iptr->sx.val.i == 0x10000000) ||
+ (iptr->sx.val.i == 0x20000000) ||
+ (iptr->sx.val.i == 0x40000000) ||
+ (iptr->sx.val.i == 0x80000000))
+ {
+ iptr->opc = ICMD_IREMPOW2;
+ iptr->sx.val.i -= 1;
+ goto icmd_iconst_tail;
+ }
+ goto normal_ICONST;
+#if SUPPORT_CONST_LOGICAL
+ case ICMD_IAND:
+ iptr->opc = ICMD_IANDCONST;
+ goto icmd_iconst_tail;
+
+ case ICMD_IOR:
+ iptr->opc = ICMD_IORCONST;
+ goto icmd_iconst_tail;
+
+ case ICMD_IXOR:
+ iptr->opc = ICMD_IXORCONST;
+ goto icmd_iconst_tail;
+
+#endif /* SUPPORT_CONST_LOGICAL */
+ case ICMD_ISHL:
+ iptr->opc = ICMD_ISHLCONST;
+ goto icmd_iconst_tail;
+
+ case ICMD_ISHR:
+ iptr->opc = ICMD_ISHRCONST;
+ goto icmd_iconst_tail;
+
+ case ICMD_IUSHR:
+ iptr->opc = ICMD_IUSHRCONST;
+ goto icmd_iconst_tail;
+#if SUPPORT_LONG_SHIFT
+ case ICMD_LSHL:
+ iptr->opc = ICMD_LSHLCONST;
+ goto icmd_lconst_tail;
+
+ case ICMD_LSHR:
+ iptr->opc = ICMD_LSHRCONST;
+ goto icmd_lconst_tail;
+
+ case ICMD_LUSHR:
+ iptr->opc = ICMD_LUSHRCONST;
+ goto icmd_lconst_tail;
+#endif /* SUPPORT_LONG_SHIFT */
+ case ICMD_IF_ICMPEQ:
+ iptr[1].opc = ICMD_IFEQ;
+ /* FALLTHROUGH */
+
+ icmd_if_icmp_tail:
+ /* set the constant for the following icmd */
+ iptr[1].sx.val.i = iptr->sx.val.i;
+
+ /* this instruction becomes a nop */
+ iptr->opc = ICMD_NOP;
+ goto icmd_NOP;
+
+ 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_INTRP( goto normal_ICONST; )
+# if SUPPORT_CONST_STORE_ZERO_ONLY
+ if (iptr->sx.val.i != 0)
+ goto normal_ICONST;
+# endif
+ 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;
+ }
+
+ iptr[1].opc = ICMD_NOP;
+
+ /* copy the constant to s3 */
+ /* XXX constval -> astoreconstval? */
+ iptr->sx.s23.s3.constval = iptr->sx.val.i;
+ OP2_0(TYPE_ADR, TYPE_INT);
+ COUNT(count_pcmd_op);
+ break;
+
+ case ICMD_PUTSTATIC:
+ case ICMD_PUTFIELD:
+ IF_INTRP( goto normal_ICONST; )
+# if SUPPORT_CONST_STORE_ZERO_ONLY
+ if (iptr->sx.val.i != 0)
+ goto normal_ICONST;
+# endif
+ /* XXX check field type? */
+
+ /* copy the constant to s2 */
+ /* XXX constval -> fieldconstval? */
+ iptr->sx.s23.s2.constval = iptr->sx.val.i;
+
+putconst_tail:
+ /* set the field reference (s3) */
+ if (iptr[1].flags.bits & INS_FLAG_UNRESOLVED) {
+ iptr->sx.s23.s3.uf = iptr[1].sx.s23.s3.uf;
+ iptr->flags.bits |= INS_FLAG_UNRESOLVED;
+ }
+ else {
+ iptr->sx.s23.s3.fmiref = iptr[1].sx.s23.s3.fmiref;
+ }
+
+ switch (iptr[1].opc) {
+ case ICMD_PUTSTATIC:
+ iptr->opc = ICMD_PUTSTATICCONST;
+ OP0_0;
+ break;
+ case ICMD_PUTFIELD:
+ iptr->opc = ICMD_PUTFIELDCONST;
+ OP1_0(TYPE_ADR);
+ break;
+ }
+
+ iptr[1].opc = ICMD_NOP;
+ COUNT(count_pcmd_op);
+ break;
+#endif /* SUPPORT_CONST_STORE */
+
+ default:
+ goto normal_ICONST;
+ }
+
+ /* if we get here, the ICONST has been optimized */
+ break;
+
+normal_ICONST:
+ /* normal case of an unoptimized ICONST */
+ OP0_1(TYPE_INT);
+ break;
+
+ /************************** LCONST OPTIMIZATIONS **************************/
+
+ case ICMD_LCONST:
+ COUNT(count_pcmd_load);
+ if (len == 0)
+ goto normal_LCONST;
+
+ /* switch depending on the following instruction */
+
+ switch (iptr[1].opc) {
+#if SUPPORT_LONG_ADD
+ case ICMD_LADD:
+ iptr->opc = ICMD_LADDCONST;
+ /* FALLTHROUGH */
+
+ icmd_lconst_tail:
+ /* instruction of type LONG -> LONG */
+ iptr[1].opc = ICMD_NOP;
+ OP1_1(TYPE_LNG, TYPE_LNG);
+ COUNT(count_pcmd_op);
+ break;
+
+ case ICMD_LSUB:
+ iptr->opc = ICMD_LSUBCONST;
+ goto icmd_lconst_tail;
+
+#endif /* SUPPORT_LONG_ADD */
+#if SUPPORT_LONG_MUL && SUPPORT_CONST_MUL
+ case ICMD_LMUL:
+ iptr->opc = ICMD_LMULCONST;
+ goto icmd_lconst_tail;
+#else /* SUPPORT_LONG_MUL && SUPPORT_CONST_MUL */
+# if SUPPORT_LONG_SHIFT
+ case ICMD_LMUL:
+ if (iptr->sx.val.l == 0x00000002)
+ iptr->sx.val.i = 1;
+ else if (iptr->sx.val.l == 0x00000004)
+ iptr->sx.val.i = 2;
+ else if (iptr->sx.val.l == 0x00000008)
+ iptr->sx.val.i = 3;
+ else if (iptr->sx.val.l == 0x00000010)
+ iptr->sx.val.i = 4;
+ else if (iptr->sx.val.l == 0x00000020)
+ iptr->sx.val.i = 5;
+ else if (iptr->sx.val.l == 0x00000040)
+ iptr->sx.val.i = 6;
+ else if (iptr->sx.val.l == 0x00000080)
+ iptr->sx.val.i = 7;
+ else if (iptr->sx.val.l == 0x00000100)
+ iptr->sx.val.i = 8;
+ else if (iptr->sx.val.l == 0x00000200)
+ iptr->sx.val.i = 9;
+ else if (iptr->sx.val.l == 0x00000400)
+ iptr->sx.val.i = 10;
+ else if (iptr->sx.val.l == 0x00000800)
+ iptr->sx.val.i = 11;
+ else if (iptr->sx.val.l == 0x00001000)
+ iptr->sx.val.i = 12;
+ else if (iptr->sx.val.l == 0x00002000)
+ iptr->sx.val.i = 13;
+ else if (iptr->sx.val.l == 0x00004000)
+ iptr->sx.val.i = 14;
+ else if (iptr->sx.val.l == 0x00008000)
+ iptr->sx.val.i = 15;
+ else if (iptr->sx.val.l == 0x00010000)
+ iptr->sx.val.i = 16;
+ else if (iptr->sx.val.l == 0x00020000)
+ iptr->sx.val.i = 17;
+ else if (iptr->sx.val.l == 0x00040000)
+ iptr->sx.val.i = 18;
+ else if (iptr->sx.val.l == 0x00080000)
+ iptr->sx.val.i = 19;
+ else if (iptr->sx.val.l == 0x00100000)
+ iptr->sx.val.i = 20;
+ else if (iptr->sx.val.l == 0x00200000)
+ iptr->sx.val.i = 21;
+ else if (iptr->sx.val.l == 0x00400000)
+ iptr->sx.val.i = 22;
+ else if (iptr->sx.val.l == 0x00800000)
+ iptr->sx.val.i = 23;
+ else if (iptr->sx.val.l == 0x01000000)
+ iptr->sx.val.i = 24;
+ else if (iptr->sx.val.l == 0x02000000)
+ iptr->sx.val.i = 25;
+ else if (iptr->sx.val.l == 0x04000000)
+ iptr->sx.val.i = 26;
+ else if (iptr->sx.val.l == 0x08000000)
+ iptr->sx.val.i = 27;
+ else if (iptr->sx.val.l == 0x10000000)
+ iptr->sx.val.i = 28;
+ else if (iptr->sx.val.l == 0x20000000)
+ iptr->sx.val.i = 29;
+ else if (iptr->sx.val.l == 0x40000000)
+ iptr->sx.val.i = 30;
+ else if (iptr->sx.val.l == 0x80000000)
+ iptr->sx.val.i = 31;
+ else {
+ goto normal_LCONST;
+ }
+ iptr->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->sx.val.l == 0x00000002)
+ iptr->sx.val.i = 1;
+ else if (iptr->sx.val.l == 0x00000004)
+ iptr->sx.val.i = 2;
+ else if (iptr->sx.val.l == 0x00000008)
+ iptr->sx.val.i = 3;
+ else if (iptr->sx.val.l == 0x00000010)
+ iptr->sx.val.i = 4;
+ else if (iptr->sx.val.l == 0x00000020)
+ iptr->sx.val.i = 5;
+ else if (iptr->sx.val.l == 0x00000040)
+ iptr->sx.val.i = 6;
+ else if (iptr->sx.val.l == 0x00000080)
+ iptr->sx.val.i = 7;
+ else if (iptr->sx.val.l == 0x00000100)
+ iptr->sx.val.i = 8;
+ else if (iptr->sx.val.l == 0x00000200)
+ iptr->sx.val.i = 9;
+ else if (iptr->sx.val.l == 0x00000400)
+ iptr->sx.val.i = 10;
+ else if (iptr->sx.val.l == 0x00000800)
+ iptr->sx.val.i = 11;
+ else if (iptr->sx.val.l == 0x00001000)
+ iptr->sx.val.i = 12;
+ else if (iptr->sx.val.l == 0x00002000)
+ iptr->sx.val.i = 13;
+ else if (iptr->sx.val.l == 0x00004000)
+ iptr->sx.val.i = 14;
+ else if (iptr->sx.val.l == 0x00008000)
+ iptr->sx.val.i = 15;
+ else if (iptr->sx.val.l == 0x00010000)
+ iptr->sx.val.i = 16;
+ else if (iptr->sx.val.l == 0x00020000)
+ iptr->sx.val.i = 17;
+ else if (iptr->sx.val.l == 0x00040000)
+ iptr->sx.val.i = 18;
+ else if (iptr->sx.val.l == 0x00080000)
+ iptr->sx.val.i = 19;
+ else if (iptr->sx.val.l == 0x00100000)
+ iptr->sx.val.i = 20;
+ else if (iptr->sx.val.l == 0x00200000)
+ iptr->sx.val.i = 21;
+ else if (iptr->sx.val.l == 0x00400000)
+ iptr->sx.val.i = 22;
+ else if (iptr->sx.val.l == 0x00800000)
+ iptr->sx.val.i = 23;
+ else if (iptr->sx.val.l == 0x01000000)
+ iptr->sx.val.i = 24;
+ else if (iptr->sx.val.l == 0x02000000)
+ iptr->sx.val.i = 25;
+ else if (iptr->sx.val.l == 0x04000000)
+ iptr->sx.val.i = 26;
+ else if (iptr->sx.val.l == 0x08000000)
+ iptr->sx.val.i = 27;
+ else if (iptr->sx.val.l == 0x10000000)
+ iptr->sx.val.i = 28;
+ else if (iptr->sx.val.l == 0x20000000)
+ iptr->sx.val.i = 29;
+ else if (iptr->sx.val.l == 0x40000000)
+ iptr->sx.val.i = 30;
+ else if (iptr->sx.val.l == 0x80000000)
+ iptr->sx.val.i = 31;
+ else {
+ goto normal_LCONST;
+ }
+ iptr->opc = ICMD_LDIVPOW2;
+ goto icmd_lconst_tail;
+#endif /* SUPPORT_LONG_DIV_POW2 */
+
+#if SUPPORT_LONG_REM_POW2
+ case ICMD_LREM:
+ if ((iptr->sx.val.l == 0x00000002) ||
+ (iptr->sx.val.l == 0x00000004) ||
+ (iptr->sx.val.l == 0x00000008) ||
+ (iptr->sx.val.l == 0x00000010) ||
+ (iptr->sx.val.l == 0x00000020) ||
+ (iptr->sx.val.l == 0x00000040) ||
+ (iptr->sx.val.l == 0x00000080) ||
+ (iptr->sx.val.l == 0x00000100) ||
+ (iptr->sx.val.l == 0x00000200) ||
+ (iptr->sx.val.l == 0x00000400) ||
+ (iptr->sx.val.l == 0x00000800) ||
+ (iptr->sx.val.l == 0x00001000) ||
+ (iptr->sx.val.l == 0x00002000) ||
+ (iptr->sx.val.l == 0x00004000) ||
+ (iptr->sx.val.l == 0x00008000) ||
+ (iptr->sx.val.l == 0x00010000) ||
+ (iptr->sx.val.l == 0x00020000) ||
+ (iptr->sx.val.l == 0x00040000) ||
+ (iptr->sx.val.l == 0x00080000) ||
+ (iptr->sx.val.l == 0x00100000) ||
+ (iptr->sx.val.l == 0x00200000) ||
+ (iptr->sx.val.l == 0x00400000) ||
+ (iptr->sx.val.l == 0x00800000) ||
+ (iptr->sx.val.l == 0x01000000) ||
+ (iptr->sx.val.l == 0x02000000) ||
+ (iptr->sx.val.l == 0x04000000) ||
+ (iptr->sx.val.l == 0x08000000) ||
+ (iptr->sx.val.l == 0x10000000) ||
+ (iptr->sx.val.l == 0x20000000) ||
+ (iptr->sx.val.l == 0x40000000) ||
+ (iptr->sx.val.l == 0x80000000))
+ {
+ iptr->opc = ICMD_LREMPOW2;
+ iptr->sx.val.l -= 1;
+ goto icmd_lconst_tail;
}
+ goto normal_LCONST;
+#endif /* SUPPORT_LONG_REM_POW2 */
+
+#if SUPPORT_LONG_LOGICAL && SUPPORT_CONST_LOGICAL
+
+ case ICMD_LAND:
+ iptr->opc = ICMD_LANDCONST;
+ goto icmd_lconst_tail;
+
+ case ICMD_LOR:
+ iptr->opc = ICMD_LORCONST;
+ goto icmd_lconst_tail;
+
+ case ICMD_LXOR:
+ iptr->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].sx.val.i != 0))
+ goto normal_LCONST;
+
+ /* switch on the instruction after LCONST - LCMP */
+
+ switch (iptr[2].opc) {
+ case ICMD_IFEQ:
+ iptr->opc = ICMD_IF_LEQ;
+ /* FALLTHROUGH */
+
+ icmd_lconst_lcmp_tail:
+ /* convert LCONST, LCMP, IFXX to IF_LXX */
+ iptr->dst.insindex = iptr[2].dst.insindex;
+ iptr[1].opc = ICMD_NOP;
+ iptr[2].opc = ICMD_NOP;
+
+ OP1_BRANCH(TYPE_LNG);
+ BRANCH(tbptr);
+ COUNT(count_pcmd_bra);
+ COUNT(count_pcmd_op);
+ break;
+
+ case ICMD_IFNE:
+ iptr->opc = ICMD_IF_LNE;
+ goto icmd_lconst_lcmp_tail;
+
+ case ICMD_IFLT:
+ iptr->opc = ICMD_IF_LLT;
+ goto icmd_lconst_lcmp_tail;
+
+ case ICMD_IFGT:
+ iptr->opc = ICMD_IF_LGT;
+ goto icmd_lconst_lcmp_tail;
+
+ case ICMD_IFLE:
+ iptr->opc = ICMD_IF_LLE;
+ goto icmd_lconst_lcmp_tail;
+
+ case ICMD_IFGE:
+ iptr->opc = ICMD_IF_LGE;
+ goto icmd_lconst_lcmp_tail;
+
+ default:
+ goto normal_LCONST;
+ } /* end switch on opcode after LCONST - LCMP */
+ break;
+#endif /* SUPPORT_LONG_CMP_CONST */
+
+#if SUPPORT_CONST_STORE
+ case ICMD_LASTORE:
+ IF_INTRP( goto normal_LCONST; )
+# if SUPPORT_CONST_STORE_ZERO_ONLY
+ if (iptr->sx.val.l != 0)
+ goto normal_LCONST;
+# endif
+#if SIZEOF_VOID_P == 4
+ /* the constant must fit into a ptrint */
+ if (iptr->sx.val.l < -0x80000000L || iptr->sx.val.l >= 0x80000000L)
+ goto normal_LCONST;
#endif
- iptr->opc = ICMD_DUP_X2;
- DUP_X2;
+ /* move the constant to s3 */
+ iptr->sx.s23.s3.constval = iptr->sx.val.l;
+
+ iptr->opc = ICMD_LASTORECONST;
+ iptr->flags.bits |= INS_FLAG_CHECK;
+ OP2_0(TYPE_ADR, TYPE_INT);
+
+ iptr[1].opc = ICMD_NOP;
+ COUNT(count_pcmd_op);
+ break;
+
+ case ICMD_PUTSTATIC:
+ case ICMD_PUTFIELD:
+ IF_INTRP( goto normal_LCONST; )
+# if SUPPORT_CONST_STORE_ZERO_ONLY
+ if (iptr->sx.val.l != 0)
+ goto normal_LCONST;
+# endif
+#if SIZEOF_VOID_P == 4
+ /* the constant must fit into a ptrint */
+ if (iptr->sx.val.l < -0x80000000L || iptr->sx.val.l >= 0x80000000L)
+ goto normal_LCONST;
+#endif
+ /* XXX check field type? */
+
+ /* copy the constant to s2 */
+ /* XXX constval -> fieldconstval? */
+ iptr->sx.s23.s2.constval = iptr->sx.val.l;
+
+ goto putconst_tail;
+
+#endif /* SUPPORT_CONST_STORE */
+
+ default:
+ goto normal_LCONST;
+ } /* end switch opcode after LCONST */
+
+ /* if we get here, the LCONST has been optimized */
+ break;
+
+normal_LCONST:
+ /* the normal case of an unoptimized LCONST */
+ OP0_1(TYPE_LNG);
+ break;
+
+ /************************ END OF LCONST OPTIMIZATIONS *********************/
+
+ case ICMD_FCONST:
+ COUNT(count_pcmd_load);
+ OP0_1(TYPE_FLT);
+ break;
+
+ case ICMD_DCONST:
+ COUNT(count_pcmd_load);
+ 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; )
+
+ /* We can only optimize if the ACONST is resolved
+ * and there is an instruction after it. */
+
+ if ((len == 0) || (iptr->flags.bits & INS_FLAG_UNRESOLVED))
+ goto normal_ACONST;
+
+ switch (iptr[1].opc) {
+ case ICMD_AASTORE:
+ /* We can only optimize for NULL values
+ * here because otherwise a checkcast is
+ * required. */
+ if (iptr->sx.val.anyptr != NULL)
+ goto normal_ACONST;
+
+ /* copy the constant (NULL) to s3 */
+ iptr->sx.s23.s3.constval = 0;
+ iptr->opc = ICMD_AASTORECONST;
+ iptr->flags.bits |= INS_FLAG_CHECK;
+ OP2_0(TYPE_ADR, TYPE_INT);
+
+ iptr[1].opc = ICMD_NOP;
+ COUNT(count_pcmd_op);
+ break;
+
+ case ICMD_PUTSTATIC:
+ case ICMD_PUTFIELD:
+# if SUPPORT_CONST_STORE_ZERO_ONLY
+ if (iptr->sx.val.anyptr != NULL)
+ goto normal_ACONST;
+# endif
+ /* XXX check field type? */
+ /* copy the constant to s2 */
+ /* XXX constval -> fieldconstval? */
+ iptr->sx.s23.s2.constval = (ptrint) iptr->sx.val.anyptr;
+
+ goto putconst_tail;
+
+ default:
+ goto normal_ACONST;
+ }
+
+ /* if we get here the ACONST has been optimized */
+ break;
+
+normal_ACONST:
+#endif /* SUPPORT_CONST_STORE */
+ OP0_1(TYPE_ADR);
+ 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; /* type */
+
+ j = iptr->s1.varindex =
+ jd->local_map[iptr->s1.varindex * 5 + i];
+
+ if (sd.var[j].type == TYPE_RET) {
+ exceptions_throw_verifyerror(m, "forbidden load of returnAddress");
+ return false;
+ }
+
+ LOAD(i, j);
+ break;
+
+ /* pop 2 push 1 */
+
+ case ICMD_LALOAD:
+ 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);
+ 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);
+ 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_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.varindex))
+ {
+ assert(IS_LOCALVAR(copy));
+ SET_TEMPVAR(copy);
}
+ i--;
+ copy = copy->prev;
+ }
+
+ iptr->dst.varindex = iptr->s1.varindex;
+ 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; /* type */
+ javaindex = iptr->dst.varindex;
+ j = iptr->dst.varindex =
+ jd->local_map[javaindex * 5 + i];
+
+ COPY_VAL_AND_TYPE(sd, curstack->varnum, j);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ count_pcmd_store++;
+ i = sd.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]++;
}
- 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;
+ /* check for conflicts as described in Figure 5.2 */
+
+ copy = curstack->prev;
+ i = stackdepth - 2;
+ while (copy) {
+ if ((copy->varkind == LOCALVAR) &&
+ (copy->varnum == j))
+ {
+ copy->varkind = TEMPVAR;
+ assert(IS_LOCALVAR(copy));
+ SET_TEMPVAR(copy);
}
+ i--;
+ copy = copy->prev;
}
- 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;
+ /* if the variable is already coalesced, don't bother */
+
+ /* We do not need to check against OUTVAR, as invars */
+ /* are always before the coalescing boundary. */
+
+ if (curstack->varkind == LOCALVAR)
+ 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;
}
-#endif
- SWAP;
+
+ /* coalesce the temporary variable with Lj */
+ assert((curstack->varkind == TEMPVAR)
+ || (curstack->varkind == UNDEFVAR));
+ assert(!IS_LOCALVAR(curstack)); /* XXX correct? */
+ 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 == j))
+ {
+ assert(IS_LOCALVAR(curstack));
+ SET_TEMPVAR(curstack);
+ }
+
+ /* remember the stack boundary at this store */
+store_tail:
+ last_store_boundary[javaindex] = sd.new;
+
+ STORE(opcode - ICMD_ISTORE, j);
break;
- /* pop 2 push 1 */
+ /* pop 3 push 0 */
- case ICMD_IDIV:
- case ICMD_IREM:
-#if !SUPPORT_DIVISION
- bte = (builtintable_entry *) iptr->val.a;
+ 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);
+
+ bte = builtintable_get_internal(BUILTIN_canstore);
md = bte->md;
- i = iptr->op1;
if (md->memuse > rd->memuse)
rd->memuse = md->memuse;
if (md->argintreguse > rd->argintreguse)
rd->argintreguse = md->argintreguse;
+ /* XXX non-leaf method? */
/* make all stack variables saved */
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;
}
- /* fall through */
-#endif /* !SUPPORT_DIVISION */
+ 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);
+ 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);
+ OP3_0(TYPE_ADR, TYPE_INT, 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_0_ANY;
+ break;
+
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_FRETURN:
+ case ICMD_DRETURN:
+ case ICMD_ARETURN:
+ coalescing_boundary = sd.new;
+ IF_JIT( md_return_alloc(jd, curstack); )
+ COUNT(count_pcmd_return);
+ OP1_0(opcode - ICMD_IRETURN);
+ superblockend = true;
+ break;
+
+ case ICMD_ATHROW:
+ coalescing_boundary = sd.new;
+ COUNT(count_check_null);
+ OP1_0(TYPE_ADR);
+ curstack = NULL; stackdepth = 0;
+ superblockend = true;
+ break;
+
+ case ICMD_PUTSTATIC:
+ coalescing_boundary = sd.new;
+ COUNT(count_pcmd_mem);
+ 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);
+ OP1_BRANCH(TYPE_ADR);
+ BRANCH(tbptr);
+ break;
+
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
+ COUNT(count_pcmd_bra);
+ /* iptr->sx.val.i is set implicitly in parse by
+ clearing the memory or from IF_ICMPxx
+ optimization. */
+
+ OP1_BRANCH(TYPE_INT);
+/* iptr->sx.val.i = 0; */
+ BRANCH(tbptr);
+ break;
+
+ /* pop 0 push 0 branch */
+
+ case ICMD_GOTO:
+ COUNT(count_pcmd_bra);
+ OP0_BRANCH;
+ BRANCH(tbptr);
+ superblockend = true;
+ break;
+
+ /* pop 1 push 0 table branch */
+
+ case ICMD_TABLESWITCH:
+ COUNT(count_pcmd_table);
+ OP1_BRANCH(TYPE_INT);
+
+ table = iptr->dst.table;
+ BRANCH_TARGET(*table, tbptr);
+ table++;
+
+ i = iptr->sx.s23.s3.tablehigh
+ - iptr->sx.s23.s2.tablelow + 1;
+
+ while (--i >= 0) {
+ BRANCH_TARGET(*table, tbptr);
+ table++;
+ }
+ superblockend = true;
+ break;
+
+ /* pop 1 push 0 table branch */
+
+ case ICMD_LOOKUPSWITCH:
+ COUNT(count_pcmd_table);
+ OP1_BRANCH(TYPE_INT);
+
+ BRANCH_TARGET(iptr->sx.s23.s3.lookupdefault, tbptr);
+
+ lookup = iptr->dst.lookup;
+
+ i = iptr->sx.s23.s2.lookupcount;
+
+ while (--i >= 0) {
+ BRANCH_TARGET(lookup->target, tbptr);
+ lookup++;
+ }
+ superblockend = true;
+ break;
+
+ case ICMD_MONITORENTER:
+ case ICMD_MONITOREXIT:
+ coalescing_boundary = sd.new;
+ COUNT(count_check_null);
+ 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_BRANCH(TYPE_INT, TYPE_INT);
+ BRANCH(tbptr);
+ break;
+
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+ COUNT(count_pcmd_bra);
+ OP2_BRANCH(TYPE_ADR, TYPE_ADR);
+ BRANCH(tbptr);
+ break;
+
+ /* pop 2 push 0 */
+
+ case ICMD_PUTFIELD:
+ coalescing_boundary = sd.new;
+ COUNT(count_check_null);
+ COUNT(count_pcmd_mem);
+ INSTRUCTION_GET_FIELDREF(iptr, fmiref);
+ OP2_0(TYPE_ADR, fmiref->parseddesc.fd->type);
+ 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
+ OP2_0_ANY_ANY; /* pop two slots */
+ }
+ else {
+ iptr->opc = ICMD_POP;
+ OP1_0_ANY; /* pop one (two-word) slot */
+ }
+ 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
+ COUNT(count_dup_instruction);
+
+icmd_DUP:
+ src1 = curstack;
- 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);
+ COPY_UP(src1);
+ coalescing_boundary = sd.new - 1;
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;
+ case ICMD_DUP2:
+ REQUIRE(1);
+ if (IS_2_WORD_TYPE(curstack->type)) {
+ /* ..., cat2 */
+ iptr->opc = ICMD_DUP;
+ goto icmd_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
+ src1 = curstack->prev;
+ src2 = curstack;
- if (md->memuse > rd->memuse)
- rd->memuse = md->memuse;
- if (md->argintreguse > rd->argintreguse)
- rd->argintreguse = md->argintreguse;
+ COPY_UP(src1); iptr++; len--;
+ COPY_UP(src2);
- /* make all stack variables saved */
+ coalescing_boundary = sd.new;
+ }
+ break;
- copy = curstack;
- while (copy) {
- copy->flags |= SAVEDVAR;
- copy = copy->prev;
+ /* 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
- /* fall through */
-#endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
+icmd_DUP_X1:
+ src1 = curstack->prev;
+ src2 = curstack;
+ POPANY; POPANY;
+ stackdepth -= 2;
- 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;
+ DUP_SLOT(src2); dst1 = curstack; stackdepth++;
- case ICMD_LSHL:
- case ICMD_LSHR:
- case ICMD_LUSHR:
- COUNT(count_pcmd_op);
- OP2IT_1(TYPE_LNG);
- break;
+ MOVE_UP(src1); iptr++; len--;
+ MOVE_UP(src2); iptr++; len--;
- case ICMD_FADD:
- case ICMD_FSUB:
- case ICMD_FMUL:
- case ICMD_FDIV:
- case ICMD_FREM:
- COUNT(count_pcmd_op);
- OP2_1(TYPE_FLT);
- break;
+ COPY_DOWN(curstack, dst1);
- case ICMD_DADD:
- case ICMD_DSUB:
- case ICMD_DMUL:
- case ICMD_DDIV:
- case ICMD_DREM:
- COUNT(count_pcmd_op);
- OP2_1(TYPE_DBL);
+ coalescing_boundary = sd.new;
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;
- len--;
- bptr->icount--;
- /* iptr[1].opc = ICMD_NOP; */
- OP2_0(TYPE_LNG);
- tbptr = m->basicblocks + m->basicblockindex[iptr->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);
+ case ICMD_DUP2_X1:
+ 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;
+ goto icmd_DUP_X1;
}
- else
-#endif /* SUPPORT_LONG_CMP_CONST */
- OPTT2_1(TYPE_LNG, TYPE_INT);
- break;
- 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;
+ 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
- /* 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;
+icmd_DUP2_X1:
+ src1 = curstack->prev->prev;
+ src2 = curstack->prev;
+ src3 = curstack;
+ POPANY; POPANY; POPANY;
+ stackdepth -= 3;
- 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;
+ DUP_SLOT(src2); dst1 = curstack; stackdepth++;
+ DUP_SLOT(src3); dst2 = curstack; stackdepth++;
- case ICMD_CHECKCAST:
- if (iptr->op1 == 0) {
- /* array type cast-check */
+ MOVE_UP(src1); iptr++; len--;
+ MOVE_UP(src2); iptr++; len--;
+ MOVE_UP(src3); iptr++; len--;
- bte = builtintable_get_internal(BUILTIN_arraycheckcast);
- md = bte->md;
+ COPY_DOWN(curstack, dst2); iptr++; len--;
+ COPY_DOWN(curstack->prev, dst1);
- if (md->memuse > rd->memuse)
- rd->memuse = md->memuse;
- if (md->argintreguse > rd->argintreguse)
- rd->argintreguse = md->argintreguse;
+ coalescing_boundary = sd.new;
+ }
+ break;
- /* make all stack variables saved */
+ /* pop 3 push 4 dup */
- copy = curstack;
- while (copy) {
- copy->flags |= SAVEDVAR;
- copy = copy->prev;
+ case ICMD_DUP_X2:
+ 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;
+ goto icmd_DUP_X1;
}
- OP1_1(TYPE_ADR, TYPE_ADR);
- break;
+ 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
+icmd_DUP_X2:
+ src1 = curstack->prev->prev;
+ src2 = curstack->prev;
+ src3 = curstack;
+ POPANY; POPANY; POPANY;
+ stackdepth -= 3;
- case ICMD_INSTANCEOF:
- case ICMD_ARRAYLENGTH:
- OP1_1(TYPE_ADR, TYPE_INT);
- break;
+ DUP_SLOT(src3); dst1 = curstack; stackdepth++;
- case ICMD_NEWARRAY:
- case ICMD_ANEWARRAY:
- OP1_1(TYPE_INT, TYPE_ADR);
- break;
+ MOVE_UP(src1); iptr++; len--;
+ MOVE_UP(src2); iptr++; len--;
+ MOVE_UP(src3); iptr++; len--;
- case ICMD_GETFIELD:
- COUNT(count_check_null);
- COUNT(count_pcmd_mem);
- OP1_1(TYPE_ADR, iptr->op1);
- break;
+ COPY_DOWN(curstack, dst1);
- /* pop 0 push 1 */
-
- case ICMD_GETSTATIC:
- COUNT(count_pcmd_mem);
- OP0_1(iptr->op1);
+ coalescing_boundary = sd.new;
+ }
break;
- case ICMD_NEW:
- OP0_1(TYPE_ADR);
- break;
+ case ICMD_DUP2_X2:
+ 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;
+ goto icmd_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;
+ goto icmd_DUP_X2;
+ }
+ }
+
+ 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;
+ goto icmd_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
- case ICMD_JSR:
- OP0_1(TYPE_ADR);
- tbptr = m->basicblocks + m->basicblockindex[iptr->op1];
+ src1 = curstack->prev->prev->prev;
+ src2 = curstack->prev->prev;
+ src3 = curstack->prev;
+ src4 = curstack;
+ POPANY; POPANY; POPANY; POPANY;
+ stackdepth -= 4;
- iptr[0].target = (void *) tbptr;
+ DUP_SLOT(src3); dst1 = curstack; stackdepth++;
+ DUP_SLOT(src4); dst2 = curstack; stackdepth++;
- /* This is a dirty hack. The typechecker
- * needs it because the OP1_0ANY below
- * overwrites iptr->dst.
- */
- iptr->val.a = (void *) iptr->dst;
+ MOVE_UP(src1); iptr++; len--;
+ MOVE_UP(src2); iptr++; len--;
+ MOVE_UP(src3); iptr++; len--;
+ MOVE_UP(src4); iptr++; len--;
- tbptr->type = BBTYPE_SBR;
+ COPY_DOWN(curstack, dst2); iptr++; len--;
+ COPY_DOWN(curstack->prev, dst1);
- /* We need to check for overflow right here because
- * the pushed value is poped after MARKREACHED. */
- CHECKOVERFLOW;
- MARKREACHED(tbptr, copy);
- OP1_0ANY;
+ coalescing_boundary = sd.new;
+ }
break;
- /* pop many push any */
+ /* pop 2 push 2 swap */
- case ICMD_BUILTIN:
-#if defined(USEBUILTINTABLE)
- builtin:
+ case ICMD_SWAP:
+#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
- 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);
- um = iptr->target;
- md = um->methodref->parseddesc.md;
-/* if (lm->flags & ACC_STATIC) */
-/* {COUNT(count_check_null);} */
+ src1 = curstack->prev;
+ src2 = curstack;
+ POPANY; POPANY;
+ stackdepth -= 2;
- _callhandling:
+ MOVE_UP(src2); iptr++; len--;
+ MOVE_UP(src1);
- last_pei = bptr->icount - len - 1;
+ coalescing_boundary = sd.new;
+ break;
- i = md->paramcount;
+ /* 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;
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);
+ /* make all stack variables saved */
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) {
+ sd.var[copy->varnum].flags |= SAVEDVAR;
copy->flags |= SAVEDVAR;
copy = copy->prev;
}
+ /* FALLTHROUGH */
- i = md->paramcount;
- POPMANY(i);
- if (md->returntype.type != TYPE_VOID)
- OP0_1(md->returntype.type);
- break;
+#endif /* !SUPPORT_DIVISION */
- case ICMD_INLINE_START:
- case ICMD_INLINE_END:
- SETDST;
+ 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, TYPE_INT, TYPE_INT);
break;
- case ICMD_MULTIANEWARRAY:
- if (rd->argintreguse < 3)
- rd->argintreguse = 3;
+ 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;
- i = iptr->op1;
+ if (md->memuse > rd->memuse)
+ rd->memuse = md->memuse;
+ if (md->argintreguse > rd->argintreguse)
+ rd->argintreguse = md->argintreguse;
+ /* XXX non-leaf method? */
+
+ /* make all stack variables saved */
- REQUIRE(i);
-#if defined(SPECIALMEMUSE)
-# if defined(__DARWIN__)
- if (rd->memuse < (i + INT_ARG_CNT + LA_WORD_SIZE))
- rd->memuse = i + LA_WORD_SIZE + INT_ARG_CNT;
-# else
- if (rd->memuse < (i + LA_WORD_SIZE + 3))
- rd->memuse = i + LA_WORD_SIZE + 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_WORD_SIZE + INT_ARG_CNT;
-# else
- copy->regoff = i + LA_WORD_SIZE + 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) {
+ sd.var[copy->varnum].flags |= SAVEDVAR;
copy->flags |= SAVEDVAR;
copy = copy->prev;
}
- i = iptr->op1;
- POPMANY(i);
- OP0_1(TYPE_ADR);
+ /* FALLTHROUGH */
+
+#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, TYPE_LNG, TYPE_LNG);
break;
- default:
- *exceptionptr =
- new_internalerror("Unknown ICMD %d", opcode);
- return NULL;
- } /* switch */
+ case ICMD_LSHL:
+ case ICMD_LSHR:
+ case ICMD_LUSHR:
+ COUNT(count_pcmd_op);
+ OP2_1(TYPE_LNG, TYPE_INT, TYPE_LNG);
+ break;
- CHECKOVERFLOW;
- iptr++;
- } /* while instructions */
+ case ICMD_FADD:
+ case ICMD_FSUB:
+ case ICMD_FMUL:
+ case ICMD_FDIV:
+ case ICMD_FREM:
+ COUNT(count_pcmd_op);
+ OP2_1(TYPE_FLT, TYPE_FLT, TYPE_FLT);
+ break;
- /* set out-stack of block */
+ case ICMD_DADD:
+ case ICMD_DSUB:
+ case ICMD_DMUL:
+ case ICMD_DDIV:
+ case ICMD_DREM:
+ COUNT(count_pcmd_op);
+ OP2_1(TYPE_DBL, TYPE_DBL, TYPE_DBL);
+ break;
- bptr->outstack = curstack;
- bptr->outdepth = stackdepth;
+ case ICMD_LCMP:
+ COUNT(count_pcmd_op);
+#if SUPPORT_LONG_CMP_CONST
+ if ((len == 0) || (iptr[1].sx.val.i != 0))
+ goto normal_LCMP;
+
+ switch (iptr[1].opc) {
+ case ICMD_IFEQ:
+ iptr->opc = ICMD_IF_LCMPEQ;
+ icmd_lcmp_if_tail:
+ iptr->dst.insindex = iptr[1].dst.insindex;
+ iptr[1].opc = ICMD_NOP;
+
+ OP2_BRANCH(TYPE_LNG, TYPE_LNG);
+ BRANCH(tbptr);
+
+ COUNT(count_pcmd_bra);
+ break;
+ case ICMD_IFNE:
+ iptr->opc = ICMD_IF_LCMPNE;
+ goto icmd_lcmp_if_tail;
+ case ICMD_IFLT:
+ iptr->opc = ICMD_IF_LCMPLT;
+ goto icmd_lcmp_if_tail;
+ case ICMD_IFGT:
+ iptr->opc = ICMD_IF_LCMPGT;
+ goto icmd_lcmp_if_tail;
+ case ICMD_IFLE:
+ iptr->opc = ICMD_IF_LCMPLE;
+ goto icmd_lcmp_if_tail;
+ case ICMD_IFGE:
+ iptr->opc = ICMD_IF_LCMPGE;
+ goto icmd_lcmp_if_tail;
+ default:
+ goto normal_LCMP;
+ }
+ break;
+normal_LCMP:
+#endif /* SUPPORT_LONG_CMP_CONST */
+ OP2_1(TYPE_LNG, TYPE_LNG, TYPE_INT);
+ break;
- /* stack slots at basic block end become interfaces */
+ /* XXX why is this deactivated? */
+#if 0
+ case ICMD_FCMPL:
+ COUNT(count_pcmd_op);
+ if ((len == 0) || (iptr[1].sx.val.i != 0))
+ goto normal_FCMPL;
+
+ switch (iptr[1].opc) {
+ case ICMD_IFEQ:
+ iptr->opc = ICMD_IF_FCMPEQ;
+ icmd_if_fcmpl_tail:
+ iptr->dst.insindex = iptr[1].dst.insindex;
+ iptr[1].opc = ICMD_NOP;
+
+ OP2_BRANCH(TYPE_FLT, TYPE_FLT);
+ BRANCH(tbptr);
+
+ COUNT(count_pcmd_bra);
+ break;
+ case ICMD_IFNE:
+ iptr->opc = ICMD_IF_FCMPNE;
+ goto icmd_if_fcmpl_tail;
+ case ICMD_IFLT:
+ iptr->opc = ICMD_IF_FCMPL_LT;
+ goto icmd_if_fcmpl_tail;
+ case ICMD_IFGT:
+ iptr->opc = ICMD_IF_FCMPL_GT;
+ goto icmd_if_fcmpl_tail;
+ case ICMD_IFLE:
+ iptr->opc = ICMD_IF_FCMPL_LE;
+ goto icmd_if_fcmpl_tail;
+ case ICMD_IFGE:
+ iptr->opc = ICMD_IF_FCMPL_GE;
+ goto icmd_if_fcmpl_tail;
+ default:
+ goto normal_FCMPL;
+ }
+ break;
- 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;
- );
- }
+normal_FCMPL:
+ OPTT2_1(TYPE_FLT, TYPE_FLT, TYPE_INT);
+ break;
- /* check if interface slots at basic block begin must be saved */
+ case ICMD_FCMPG:
+ COUNT(count_pcmd_op);
+ if ((len == 0) || (iptr[1].sx.val.i != 0))
+ goto normal_FCMPG;
+
+ switch (iptr[1].opc) {
+ case ICMD_IFEQ:
+ iptr->opc = ICMD_IF_FCMPEQ;
+ icmd_if_fcmpg_tail:
+ iptr->dst.insindex = iptr[1].dst.insindex;
+ iptr[1].opc = ICMD_NOP;
+
+ OP2_BRANCH(TYPE_FLT, TYPE_FLT);
+ BRANCH(tbptr);
+
+ COUNT(count_pcmd_bra);
+ break;
+ case ICMD_IFNE:
+ iptr->opc = ICMD_IF_FCMPNE;
+ goto icmd_if_fcmpg_tail;
+ case ICMD_IFLT:
+ iptr->opc = ICMD_IF_FCMPG_LT;
+ goto icmd_if_fcmpg_tail;
+ case ICMD_IFGT:
+ iptr->opc = ICMD_IF_FCMPG_GT;
+ goto icmd_if_fcmpg_tail;
+ case ICMD_IFLE:
+ iptr->opc = ICMD_IF_FCMPG_LE;
+ goto icmd_if_fcmpg_tail;
+ case ICMD_IFGE:
+ iptr->opc = ICMD_IF_FCMPG_GE;
+ goto icmd_if_fcmpg_tail;
+ default:
+ goto normal_FCMPG;
+ }
+ break;
- 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;
+normal_FCMPG:
+ OP2_1(TYPE_FLT, TYPE_FLT, TYPE_INT);
+ break;
+
+ case ICMD_DCMPL:
+ COUNT(count_pcmd_op);
+ if ((len == 0) || (iptr[1].sx.val.i != 0))
+ goto normal_DCMPL;
+
+ switch (iptr[1].opc) {
+ case ICMD_IFEQ:
+ iptr->opc = ICMD_IF_DCMPEQ;
+ icmd_if_dcmpl_tail:
+ iptr->dst.insindex = iptr[1].dst.insindex;
+ iptr[1].opc = ICMD_NOP;
+
+ OP2_BRANCH(TYPE_DBL, TYPE_DBL);
+ BRANCH(tbptr);
+
+ COUNT(count_pcmd_bra);
+ break;
+ case ICMD_IFNE:
+ iptr->opc = ICMD_IF_DCMPNE;
+ goto icmd_if_dcmpl_tail;
+ case ICMD_IFLT:
+ iptr->opc = ICMD_IF_DCMPL_LT;
+ goto icmd_if_dcmpl_tail;
+ case ICMD_IFGT:
+ iptr->opc = ICMD_IF_DCMPL_GT;
+ goto icmd_if_dcmpl_tail;
+ case ICMD_IFLE:
+ iptr->opc = ICMD_IF_DCMPL_LE;
+ goto icmd_if_dcmpl_tail;
+ case ICMD_IFGE:
+ iptr->opc = ICMD_IF_DCMPL_GE;
+ goto icmd_if_dcmpl_tail;
+ default:
+ goto normal_DCMPL;
}
- }
- );
+ break;
- } /* if */
- else
- superblockend = true;
- bptr++;
- } /* while blocks */
- } while (repeat && !deadcode);
+normal_DCMPL:
+ OPTT2_1(TYPE_DBL, TYPE_INT);
+ break;
-#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++;
- }
+ case ICMD_DCMPG:
+ COUNT(count_pcmd_op);
+ if ((len == 0) || (iptr[1].sx.val.i != 0))
+ goto normal_DCMPG;
+
+ switch (iptr[1].opc) {
+ case ICMD_IFEQ:
+ iptr->opc = ICMD_IF_DCMPEQ;
+ icmd_if_dcmpg_tail:
+ iptr->dst.insindex = iptr[1].dst.insindex;
+ iptr[1].opc = ICMD_NOP;
+
+ OP2_BRANCH(TYPE_DBL, TYPE_DBL);
+ BRANCH(tbptr);
+
+ COUNT(count_pcmd_bra);
+ break;
+ case ICMD_IFNE:
+ iptr->opc = ICMD_IF_DCMPNE;
+ goto icmd_if_dcmpg_tail;
+ case ICMD_IFLT:
+ iptr->opc = ICMD_IF_DCMPG_LT;
+ goto icmd_if_dcmpg_tail;
+ case ICMD_IFGT:
+ iptr->opc = ICMD_IF_DCMPG_GT;
+ goto icmd_if_dcmpg_tail;
+ case ICMD_IFLE:
+ iptr->opc = ICMD_IF_DCMPG_LE;
+ goto icmd_if_dcmpg_tail;
+ case ICMD_IFGE:
+ iptr->opc = ICMD_IF_DCMPG_GE;
+ goto icmd_if_dcmpg_tail;
+ default:
+ goto normal_DCMPG;
+ }
+ break;
- 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]++;
+normal_DCMPG:
+ OP2_1(TYPE_DBL, TYPE_DBL, TYPE_INT);
+ break;
+#else
+ case ICMD_FCMPL:
+ case ICMD_FCMPG:
+ COUNT(count_pcmd_op);
+ OP2_1(TYPE_FLT, TYPE_FLT, TYPE_INT);
+ break;
+
+ case ICMD_DCMPL:
+ case ICMD_DCMPG:
+ COUNT(count_pcmd_op);
+ OP2_1(TYPE_DBL, TYPE_DBL, TYPE_INT);
+ break;
+#endif
- 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) */
+ /* pop 1 push 1 */
- /* just return methodinfo* to signal everything was ok */
+ 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;
- return m;
+ 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;
-#if defined(ENABLE_VERIFIER)
-throw_stack_underflow:
- *exceptionptr =
- new_verifyerror(m, "Unable to pop operand off an empty stack");
- return NULL;
+ case ICMD_CHECKCAST:
+ coalescing_boundary = sd.new;
+ if (iptr->flags.bits & INS_FLAG_ARRAY) {
+ /* array type cast-check */
-throw_stack_overflow:
- *exceptionptr = new_verifyerror(m, "Stack size too large");
- return NULL;
+ bte = builtintable_get_internal(BUILTIN_arraycheckcast);
+ md = bte->md;
-throw_stack_depth_error:
- *exceptionptr = new_verifyerror(m,"Stack depth mismatch");
- return NULL;
+ if (md->memuse > rd->memuse)
+ rd->memuse = md->memuse;
+ if (md->argintreguse > rd->argintreguse)
+ rd->argintreguse = md->argintreguse;
-throw_stack_type_error:
- exceptions_throw_verifyerror_for_stack(m, expectedtype);
- return NULL;
+ /* make all stack variables saved */
-throw_stack_category_error:
- *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
- return NULL;
-#endif
-}
+ copy = curstack;
+ while (copy) {
+ sd.var[copy->varnum].flags |= SAVEDVAR;
+ copy->flags |= SAVEDVAR;
+ copy = copy->prev;
+ }
+ }
+ OP1_1(TYPE_ADR, TYPE_ADR);
+ break;
+ case ICMD_INSTANCEOF:
+ case ICMD_ARRAYLENGTH:
+ coalescing_boundary = sd.new;
+ OP1_1(TYPE_ADR, TYPE_INT);
+ break;
-/* debugging helpers **********************************************************/
+ case ICMD_NEWARRAY:
+ case ICMD_ANEWARRAY:
+ coalescing_boundary = sd.new;
+ OP1_1(TYPE_INT, TYPE_ADR);
+ break;
-/* stack_print *****************************************************************
+ case ICMD_GETFIELD:
+ coalescing_boundary = sd.new;
+ COUNT(count_check_null);
+ COUNT(count_pcmd_mem);
+ INSTRUCTION_GET_FIELDREF(iptr, fmiref);
+ OP1_1(TYPE_ADR, fmiref->parseddesc.fd->type);
+ break;
- Print the stack representation starting with the given top stackptr.
+ /* pop 0 push 1 */
- NOTE: Currently this function may only be called after register allocation!
+ case ICMD_GETSTATIC:
+ coalescing_boundary = sd.new;
+ COUNT(count_pcmd_mem);
+ INSTRUCTION_GET_FIELDREF(iptr, fmiref);
+ OP0_1(fmiref->parseddesc.fd->type);
+ break;
-*******************************************************************************/
+ case ICMD_NEW:
+ coalescing_boundary = sd.new;
+ OP0_1(TYPE_ADR);
+ break;
-#if !defined(NDEBUG)
-void stack_print(codegendata *cd, stackptr s)
-{
- int i, j;
- stackptr t;
+ case ICMD_JSR:
+ OP0_1(TYPE_RET);
- i = cd->maxstack;
- t = s;
-
- while (t) {
- i--;
- t = t->prev;
- }
- j = cd->maxstack - i;
- while (--i >= 0)
- printf(" ");
-
- while (s) {
- j--;
- if (s->flags & SAVEDVAR)
- switch (s->varkind) {
- case TEMPVAR:
- if (s->flags & INMEMORY)
- printf(" M%02d", s->regoff);
-#ifdef HAS_ADDRESS_REGISTER_FILE
- else if (s->type == TYPE_ADR)
- printf(" R%02d", s->regoff);
-#endif
- else if (IS_FLT_DBL_TYPE(s->type))
- printf(" F%02d", s->regoff);
- else {
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (IS_2_WORD_TYPE(s->type)) {
-# if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- printf(" %3d/%3d", GET_LOW_REG(s->regoff),
- GET_HIGH_REG(s->regoff));
- else
-# endif
- printf(" %3s/%3s", regs[GET_LOW_REG(s->regoff)],
- regs[GET_HIGH_REG(s->regoff)]);
-# else
- printf(" %3d/%3d", GET_LOW_REG(s->regoff),
- GET_HIGH_REG(s->regoff));
-# endif
- }
- else
-#endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
- {
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- printf(" %3d", s->regoff);
- else
-# endif
- printf(" %3s", regs[s->regoff]);
-#else
- printf(" %3d", s->regoff);
-#endif
- }
- }
- break;
- case STACKVAR:
- printf(" I%02d", s->varnum);
- break;
- case LOCALVAR:
- printf(" L%02d", s->varnum);
- break;
- case ARGVAR:
- if (s->varnum == -1) {
- /* Return Value */
- /* varkind ARGVAR "misused for this special case */
- printf(" V0");
- }
- else /* "normal" Argvar */
- printf(" A%02d", s->varnum);
- break;
- default:
- printf(" !%02d", j);
- }
- else
- switch (s->varkind) {
- case TEMPVAR:
- if (s->flags & INMEMORY)
- printf(" m%02d", s->regoff);
-#ifdef HAS_ADDRESS_REGISTER_FILE
- else if (s->type == TYPE_ADR)
- printf(" r%02d", s->regoff);
-#endif
- else if (IS_FLT_DBL_TYPE(s->type))
- printf(" f%02d", s->regoff);
- else {
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (IS_2_WORD_TYPE(s->type)) {
-# if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- printf(" %3d/%3d", GET_LOW_REG(s->regoff),
- GET_HIGH_REG(s->regoff));
- else
-# endif
- printf(" %3s/%3s", regs[GET_LOW_REG(s->regoff)],
- regs[GET_HIGH_REG(s->regoff)]);
-# else
- printf(" %3d/%3d", GET_LOW_REG(s->regoff),
- GET_HIGH_REG(s->regoff));
-# endif
- }
- else
-#endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
- {
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- printf(" %3d", s->regoff);
- else
-# endif
- printf(" %3s", regs[s->regoff]);
-#else
- printf(" %3d", s->regoff);
-#endif
- }
- }
- break;
- case STACKVAR:
- printf(" i%02d", s->varnum);
- break;
- case LOCALVAR:
- printf(" l%02d", s->varnum);
- break;
- case ARGVAR:
- if (s->varnum == -1) {
- /* Return Value */
- /* varkind ARGVAR "misused for this special case */
- printf(" v0");
- }
- else /* "normal" Argvar */
- printf(" a%02d", s->varnum);
- break;
- default:
- printf(" ?%02d", j);
- }
- s = s->prev;
- }
-}
-#endif /* !defined(NDEBUG) */
+ assert(sd.bptr->next); /* XXX exception */
+ sd.var[curstack->varnum].vv.retaddr = sd.bptr->next;
+ tbptr = BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex);
+ tbptr->type = BBTYPE_SBR;
-#if 0
-static void print_reg(stackptr s) {
- if (s) {
- if (s->flags & SAVEDVAR)
- switch (s->varkind) {
- case TEMPVAR:
- if (s->flags & INMEMORY)
- printf(" tm%02d", s->regoff);
- else
- printf(" tr%02d", s->regoff);
- break;
- case STACKVAR:
- printf(" s %02d", s->varnum);
- break;
- case LOCALVAR:
- printf(" l %02d", s->varnum);
- break;
- case ARGVAR:
- printf(" a %02d", s->varnum);
- break;
- default:
- printf(" ! %02d", s->varnum);
- }
- else
- switch (s->varkind) {
- case TEMPVAR:
- if (s->flags & INMEMORY)
- printf(" Tm%02d", s->regoff);
- else
- printf(" Tr%02d", s->regoff);
- break;
- case STACKVAR:
- printf(" S %02d", s->varnum);
- break;
- case LOCALVAR:
- printf(" L %02d", s->varnum);
- break;
- case ARGVAR:
- printf(" A %02d", s->varnum);
- break;
- default:
- printf(" ? %02d", s->varnum);
- }
- }
- else
- printf(" ");
-
-}
-#endif
+ tbptr = stack_mark_reached(&sd, tbptr, curstack, stackdepth);
+ if (!tbptr)
+ return false;
+ iptr->sx.s23.s3.jsrtarget.block = tbptr;
-#if !defined(NDEBUG)
-static char *jit_type[] = {
- "int",
- "lng",
- "flt",
- "dbl",
- "adr"
-};
-#endif
+ /* We need to check for overflow right here because
+ * the pushed value is poped afterwards */
+ CHECKOVERFLOW;
+ superblockend = true;
+ /* XXX should not be marked as interface, as it does not need to be */
+ /* allocated. Same for the invar of the target. */
+ break;
-/* show_icmd_method ************************************************************
+ /* pop many push any */
- Print the intermediate representation of a method.
+ case ICMD_BUILTIN:
+icmd_BUILTIN:
+ bte = iptr->sx.s23.s3.bte;
+ md = bte->md;
+ goto _callhandling;
- NOTE: Currently this function may only be called after register allocation!
+ case ICMD_INVOKESTATIC:
+ case ICMD_INVOKESPECIAL:
+ case ICMD_INVOKEVIRTUAL:
+ case ICMD_INVOKEINTERFACE:
+ COUNT(count_pcmd_met);
-*******************************************************************************/
+ /* Check for functions to replace with builtin
+ * functions. */
-#if !defined(NDEBUG)
-void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd)
-{
- basicblock *bptr;
- exceptiontable *ex;
- s4 i, j;
- u1 *u1ptr;
- codeinfo *code;
+ if (builtintable_replace_function(iptr))
+ goto icmd_BUILTIN;
-#if defined(USE_THREADS)
- /* We need to enter a lock here, since the binutils disassembler
- is not reentrant-able and we could not read functions printed
- at the same time. */
+ INSTRUCTION_GET_METHODDESC(iptr, md);
+ /* XXX resurrect this COUNT? */
+/* if (lm->flags & ACC_STATIC) */
+/* {COUNT(count_check_null);} */
- builtin_monitorenter(lock_show_icmd);
-#endif
+ _callhandling:
- code = cd->code;
+ coalescing_boundary = sd.new;
- printf("\n");
+ i = md->paramcount;
- method_println(m);
-
- printf("\nBasic blocks: %d\n", m->basicblockcount);
- printf("Max locals: %d\n", cd->maxlocals);
- printf("Max stack: %d\n", cd->maxstack);
- printf("Line number table length: %d\n", m->linenumbercount);
-
- printf("Exceptions (Number: %d):\n", cd->exceptiontablelength);
- for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
- printf(" L%03d ... ", ex->start->debug_nr );
- printf("L%03d = ", ex->end->debug_nr);
- printf("L%03d", ex->handler->debug_nr);
- printf(" (catchtype: ");
- if (ex->catchtype.any)
- if (IS_CLASSREF(ex->catchtype))
- utf_display_classname(ex->catchtype.ref->name);
- else
- utf_display_classname(ex->catchtype.cls->name);
- else
- printf("ANY");
- printf(")\n");
- }
-
- printf("Local Table:\n");
- for (i = 0; i < cd->maxlocals; i++) {
- printf(" %3d: ", i);
+ 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;
-#if defined(ENABLE_JIT)
- for (j = TYPE_INT; j <= TYPE_ADR; j++) {
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
- if (rd->locals[i][j].type >= 0) {
- printf(" (%s) ", jit_type[j]);
- if (rd->locals[i][j].flags & INMEMORY)
- printf("m%2d", rd->locals[i][j].regoff);
-# ifdef HAS_ADDRESS_REGISTER_FILE
- else if (j == TYPE_ADR)
- printf("r%02d", rd->locals[i][j].regoff);
-# endif
- else if ((j == TYPE_FLT) || (j == TYPE_DBL))
- printf("f%02d", rd->locals[i][j].regoff);
- else {
-# if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (IS_2_WORD_TYPE(j))
- printf(" %3s/%3s",
- regs[GET_LOW_REG(rd->locals[i][j].regoff)],
- regs[GET_HIGH_REG(rd->locals[i][j].regoff)]);
- else
-# endif
- printf("%3s", regs[rd->locals[i][j].regoff]);
- }
- }
-# if defined(ENABLE_INTRP)
- }
-# endif
- }
-#endif /* defined(ENABLE_JIT) */
+ REQUIRE(i);
- printf("\n");
- }
- printf("\n");
+ /* XXX optimize for <= 2 args */
+ /* XXX not for ICMD_BUILTIN */
+ iptr->s1.argcount = stackdepth;
+ iptr->sx.s23.s2.args = DMNEW(s4, stackdepth);
-#if defined(ENABLE_LSRA)
- if (!opt_lsra) {
-#endif
-#if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-#endif
- printf("Interface Table:\n");
- for (i = 0; i < cd->maxstack; i++) {
- if ((rd->interfaces[i][0].type >= 0) ||
- (rd->interfaces[i][1].type >= 0) ||
- (rd->interfaces[i][2].type >= 0) ||
- (rd->interfaces[i][3].type >= 0) ||
- (rd->interfaces[i][4].type >= 0)) {
- printf(" %3d: ", i);
+ copy = curstack;
+ for (i-- ; i >= 0; i--) {
+ iptr->sx.s23.s2.args[i] = copy->varnum;
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
- for (j = TYPE_INT; j <= TYPE_ADR; j++) {
- if (rd->interfaces[i][j].type >= 0) {
- printf(" (%s) ", jit_type[j]);
- if (rd->interfaces[i][j].flags & SAVEDVAR) {
- if (rd->interfaces[i][j].flags & INMEMORY)
- printf("M%2d", rd->interfaces[i][j].regoff);
-#ifdef HAS_ADDRESS_REGISTER_FILE
- else if (j == TYPE_ADR)
- printf("R%02d", rd->interfaces[i][j].regoff);
-#endif
- else if ((j == TYPE_FLT) || (j == TYPE_DBL))
- printf("F%02d", rd->interfaces[i][j].regoff);
- else {
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (IS_2_WORD_TYPE(j))
- printf(" %3s/%3s",
- regs[GET_LOW_REG(rd->interfaces[i][j].regoff)],
- regs[GET_HIGH_REG(rd->interfaces[i][j].regoff)]);
- else
+ /* 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 (!(sd.var[copy->varnum].flags & SAVEDVAR) &&
+ (!IS_FLT_DBL_TYPE(copy->type)
+ || md->params[i].inmemory)) {
+#else
+ if (!(sd.var[copy->varnum].flags & SAVEDVAR)) {
#endif
- printf("%3s",regs[rd->interfaces[i][j].regoff]);
- }
- }
- else {
- if (rd->interfaces[i][j].flags & INMEMORY)
- printf("m%2d", rd->interfaces[i][j].regoff);
-#ifdef HAS_ADDRESS_REGISTER_FILE
- else if (j == TYPE_ADR)
- printf("r%02d", rd->interfaces[i][j].regoff);
+
+ SET_PREALLOC(copy);
+
+#if defined(ENABLE_INTRP)
+ if (!opt_intrp) {
#endif
- else if ((j == TYPE_FLT) || (j == TYPE_DBL))
- printf("f%02d", rd->interfaces[i][j].regoff);
- else {
+ if (md->params[i].inmemory) {
+ sd.var[copy->varnum].vv.regoff =
+ md->params[i].regoff;
+ sd.var[copy->varnum].flags |=
+ INMEMORY;
+ }
+ else {
+ if (IS_FLT_DBL_TYPE(copy->type)) {
+#if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
+ assert(0); /* XXX is this assert ok? */
+#else
+ sd.var[copy->varnum].vv.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(j))
- printf(" %3s/%3s",
- regs[GET_LOW_REG(rd->interfaces[i][j].regoff)],
- regs[GET_HIGH_REG(rd->interfaces[i][j].regoff)]);
- else
+ if (IS_2_WORD_TYPE(copy->type))
+ sd.var[copy->varnum].vv.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 */
+ sd.var[copy->varnum].vv.regoff =
+ rd->argintregs[md->params[i].regoff];
+ }
+ }
+#if defined(ENABLE_INTRP)
+ } /* end if (!opt_intrp) */
#endif
- printf("%3s",regs[rd->interfaces[i][j].regoff]);
}
+ }
+ copy = copy->prev;
}
- }
- }
- printf("\n");
-# if defined(ENABLE_INTRP)
- }
-# endif
-#endif /* defined(ENABLE_JIT) */
-
- }
- }
- printf("\n");
-#if defined(ENABLE_INTRP)
- }
-#endif
-#if defined(ENABLE_LSRA)
- }
-#endif
+ /* deal with live-through stack slots "under" the */
+ /* arguments */
+ /* XXX not for ICMD_BUILTIN */
- if (code->rplpoints) {
- printf("Replacement Points:\n");
- replace_show_replacement_points(code);
- printf("\n");
- }
+ i = md->paramcount;
- /* show code before first basic block */
+ while (copy) {
+ SET_TEMPVAR(copy);
+ iptr->sx.s23.s2.args[i++] = copy->varnum;
+ sd.var[copy->varnum].flags |= SAVEDVAR;
+ copy = copy->prev;
+ }
- if (opt_showdisassemble) {
- u1ptr = (u1 *) ((ptrint) code->mcode + cd->dseglen);
+ /* pop the arguments */
- for (; u1ptr < (u1 *) ((ptrint) code->mcode + cd->dseglen + m->basicblocks[0].mpc);)
- DISASSINSTR(u1ptr);
+ i = md->paramcount;
- printf("\n");
- }
+ stackdepth -= i;
+ while (--i >= 0) {
+ POPANY;
+ }
- /* show code of all basic blocks */
+ /* push the return value */
- for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
- show_icmd_block(m, cd, bptr);
- }
+ if (md->returntype.type != TYPE_VOID) {
+ GET_NEW_VAR(sd, new_index, md->returntype.type);
+ DST(md->returntype.type, new_index);
+ stackdepth++;
+ }
+ break;
- /* show stubs code */
+ case ICMD_INLINE_START:
+ case ICMD_INLINE_END:
+ CLR_S1;
+ CLR_DST;
+ break;
- if (opt_showdisassemble && opt_showexceptionstubs) {
- printf("\nException stubs code:\n");
- printf("Length: %d\n\n", (s4) (code->mcodelength -
- ((ptrint) cd->dseglen +
- m->basicblocks[m->basicblockcount].mpc)));
+ case ICMD_MULTIANEWARRAY:
+ coalescing_boundary = sd.new;
+ if (rd->argintreguse < 3)
+ rd->argintreguse = 3;
- u1ptr = (u1 *) ((ptrint) code->mcode + cd->dseglen +
- m->basicblocks[m->basicblockcount].mpc);
+ i = iptr->s1.argcount;
- for (; (ptrint) u1ptr < ((ptrint) code->mcode + code->mcodelength);)
- DISASSINSTR(u1ptr);
+ REQUIRE(i);
- printf("\n");
- }
+ iptr->sx.s23.s2.args = DMNEW(s4, i);
-#if defined(USE_THREADS)
- builtin_monitorexit(lock_show_icmd);
+#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
-}
-#endif /* !defined(NDEBUG) */
+ copy = curstack;
+ while (--i >= 0) {
+ /* 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;
+ sd.var[copy->varnum].flags |=
+ INMEMORY & PREALLOC;
+#if defined(SPECIALMEMUSE)
+# if defined(__DARWIN__)
+ sd.var[copy->varnum].vv.regoff = i +
+ LA_SIZE_IN_POINTERS + INT_ARG_CNT;
+# else
+ sd.var[copy->varnum].vv.regoff = i +
+ LA_SIZE_IN_POINTERS + 3;
+# endif
+#else
+# if defined(__I386__)
+ sd.var[copy->varnum].vv.regoff = i + 3;
+# elif defined(__MIPS__) && SIZEOF_VOID_P == 4
+ sd.var[copy->varnum].vv.regoff = i + 2;
+# else
+ sd.var[copy->varnum].vv.regoff = i;
+# endif /* defined(__I386__) */
+#endif /* defined(SPECIALMEMUSE) */
+ }
+ copy = copy->prev;
+ }
+ while (copy) {
+ sd.var[copy->varnum].flags |= SAVEDVAR;
+ copy = copy->prev;
+ }
+ i = iptr->s1.argcount;
+ stackdepth -= i;
+ while (--i >= 0) {
+ POPANY;
+ }
+ GET_NEW_VAR(sd, new_index, TYPE_ADR);
+ DST(TYPE_ADR, new_index);
+ stackdepth++;
+ break;
-/* show_icmd_block *************************************************************
+ default:
+ *exceptionptr =
+ new_internalerror("Unknown ICMD %d", opcode);
+ return false;
+ } /* switch */
- Print the intermediate representation of a basic block.
+ CHECKOVERFLOW;
+ iptr++;
+ } /* while instructions */
- NOTE: Currently this function may only be called after register allocation!
+ /* stack slots at basic block end become interfaces */
-*******************************************************************************/
+ sd.bptr->outdepth = stackdepth;
+ sd.bptr->outvars = DMNEW(s4, stackdepth);
-#if !defined(NDEBUG)
-void show_icmd_block(methodinfo *m, codegendata *cd, basicblock *bptr)
-{
- s4 i, j;
- bool deadcode;
- instruction *iptr;
- u1 *u1ptr;
+ i = stackdepth - 1;
+ for (copy = curstack; copy; i--, copy = copy->prev) {
+ varinfo *v;
+ s4 t;
+
+ /* 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);
+ t = copy->type;
+ if (t == TYPE_RET)
+ t = TYPE_ADR;
+
+ v = sd.var + copy->varnum;
+ v->flags |= OUTVAR;
+
+ if (jd->interface_map[i*5 + t].flags == UNUSED) {
+ /* no interface var until now for this depth and */
+ /* type */
+ jd->interface_map[i*5 + t].flags = v->flags;
+ }
+ else {
+ jd->interface_map[i*5 + t].flags |= v->flags;
+ }
+
+ sd.bptr->outvars[i] = copy->varnum;
+ }
- if (bptr->flags != BBDELETED) {
- deadcode = bptr->flags <= BBREACHED;
+ /* check if interface slots at basic block begin must be saved */
+ IF_NO_INTRP(
+ for (i=0; i<sd.bptr->indepth; ++i) {
+ varinfo *v = sd.var + sd.bptr->invars[i];
+ s4 t;
+
+ t = v->type;
+ if (t == TYPE_RET)
+ t = TYPE_ADR;
+
+ if (jd->interface_map[i*5 + t].flags == UNUSED) {
+ /* no interface var until now for this depth and */
+ /* type */
+ jd->interface_map[i*5 + t].flags = v->flags;
+ }
+ else {
+ jd->interface_map[i*5 + t].flags |= v->flags;
+ }
+ }
+ );
- printf("[");
+ /* store the number of this block's variables */
- if (deadcode)
- for (j = cd->maxstack; j > 0; j--)
- printf(" ? ");
- else
- stack_print(cd, bptr->instack);
-
- printf("] %sL%03d(flags: %d, bitflags: %01x, next: %d, type: ",
- (bptr->bitflags & BBFLAG_REPLACEMENT) ? "<REPLACE> " : "",
- bptr->debug_nr, bptr->flags, bptr->bitflags,
- (bptr->next) ? (bptr->next->debug_nr) : -1);
-
- switch (bptr->type) {
- case BBTYPE_STD:
- printf("STD");
- break;
- case BBTYPE_EXH:
- printf("EXH");
- break;
- case BBTYPE_SBR:
- printf("SBR");
- break;
- }
+ sd.bptr->varcount = sd.vartop - sd.bptr->varstart;
- printf(", instruction count: %d, predecessors: %d):\n",
- bptr->icount, bptr->pre_count);
+#if defined(STACK_VERBOSE)
+ stack_verbose_block_exit(&sd, superblockend);
+#endif
- iptr = bptr->iinstr;
+ /* reach the following block, if any */
- for (i = 0; i < bptr->icount; i++, iptr++) {
- printf("[");
+ if (!superblockend)
+ if (!stack_reach_next_block(&sd))
+ return false;
- if (deadcode)
- for (j = cd->maxstack; j > 0; j--)
- printf(" ? ");
- else
- stack_print(cd, iptr->dst);
+ } /* for blocks */
- printf("] %5d (line: %5d) ", i, iptr->line);
+ } while (sd.repeat && !deadcode);
- show_icmd(iptr, deadcode);
- printf("\n");
- }
+ /* XXX reset TYPE_RET to TYPE_ADR */
- if (opt_showdisassemble && (!deadcode)) {
- printf("\n");
- u1ptr = (u1 *) ((ptrint) cd->code->mcode + cd->dseglen + bptr->mpc);
+ for (i=0; i<sd.vartop; ++i) {
+ if (sd.var[i].type == TYPE_RET)
+ sd.var[i].type = TYPE_ADR;
+ }
- if (bptr->next != NULL) {
- for (; u1ptr < (u1 *) ((ptrint) cd->code->mcode + cd->dseglen + bptr->next->mpc);)
- DISASSINSTR(u1ptr);
+ /* XXX hack to fix up the ranges of the cloned single-block handlers */
- }
- else {
- for (; u1ptr < (u1 *) ((ptrint) cd->code->mcode + cd->code->mcodelength);)
- DISASSINSTR(u1ptr);
- }
- printf("\n");
+ ex = cd->exceptiontable;
+ for (; ex != NULL; ex = ex->down) {
+ if (ex->start == ex->end) {
+ assert(ex->end->next);
+ ex->end = ex->end->next;
}
}
-}
-#endif /* !defined(NDEBUG) */
+ /* gather statistics *****************************************************/
-/* show_icmd *******************************************************************
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ if (jd->new_basicblockcount > count_max_basic_blocks)
+ count_max_basic_blocks = jd->new_basicblockcount;
+ count_basic_blocks += jd->new_basicblockcount;
+ if (jd->new_instructioncount > count_max_javainstr)
+ count_max_javainstr = jd->new_instructioncount;
+ count_javainstr += jd->new_instructioncount;
+ if (jd->new_stackcount > count_upper_bound_new_stack)
+ count_upper_bound_new_stack = jd->new_stackcount;
+ if ((sd.new - jd->new_stack) > count_max_new_stack)
+ count_max_new_stack = (sd.new - jd->new_stack);
+
+ sd.bptr = jd->new_basicblocks;
+ for (; sd.bptr; sd.bptr = sd.bptr->next) {
+ if (sd.bptr->flags > BBREACHED) {
+ if (sd.bptr->indepth >= 10)
+ count_block_stack[10]++;
+ else
+ count_block_stack[sd.bptr->indepth]++;
+ len = sd.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]++;
+ }
+ }
- Print the intermediate representation of an instruction.
+ if (iteration_count == 1)
+ count_analyse_iterations[0]++;
+ else if (iteration_count == 2)
+ count_analyse_iterations[1]++;
+ else if (iteration_count == 3)
+ count_analyse_iterations[2]++;
+ else if (iteration_count == 4)
+ count_analyse_iterations[3]++;
+ else
+ count_analyse_iterations[4]++;
- NOTE: Currently this function may only be called after register allocation!
+ if (jd->new_basicblockcount <= 5)
+ count_method_bb_distribution[0]++;
+ else if (jd->new_basicblockcount <= 10)
+ count_method_bb_distribution[1]++;
+ else if (jd->new_basicblockcount <= 15)
+ count_method_bb_distribution[2]++;
+ else if (jd->new_basicblockcount <= 20)
+ count_method_bb_distribution[3]++;
+ else if (jd->new_basicblockcount <= 30)
+ count_method_bb_distribution[4]++;
+ else if (jd->new_basicblockcount <= 40)
+ count_method_bb_distribution[5]++;
+ else if (jd->new_basicblockcount <= 50)
+ count_method_bb_distribution[6]++;
+ else if (jd->new_basicblockcount <= 75)
+ count_method_bb_distribution[7]++;
+ else
+ count_method_bb_distribution[8]++;
+ }
+#endif /* defined(ENABLE_STATISTICS) */
-*******************************************************************************/
+ /* everything's ok *******************************************************/
-#if !defined(NDEBUG)
-void show_icmd(instruction *iptr, bool deadcode)
-{
- int j;
- s4 *s4ptr;
- void **tptr = NULL;
-
- printf("%s", icmd_names[iptr->opc]);
-
- switch (iptr->opc) {
- case ICMD_IADDCONST:
- case ICMD_ISUBCONST:
- case ICMD_IMULCONST:
- case ICMD_IMULPOW2:
- case ICMD_IDIVPOW2:
- case ICMD_IREMPOW2:
- case ICMD_IANDCONST:
- case ICMD_IORCONST:
- case ICMD_IXORCONST:
- case ICMD_ISHLCONST:
- case ICMD_ISHRCONST:
- case ICMD_IUSHRCONST:
- case ICMD_LSHLCONST:
- case ICMD_LSHRCONST:
- case ICMD_LUSHRCONST:
- case ICMD_ICONST:
- case ICMD_IASTORECONST:
- case ICMD_BASTORECONST:
- case ICMD_CASTORECONST:
- case ICMD_SASTORECONST:
- printf(" %d (0x%08x)", iptr->val.i, iptr->val.i);
- break;
-
- case ICMD_IFEQ_ICONST:
- case ICMD_IFNE_ICONST:
- case ICMD_IFLT_ICONST:
- case ICMD_IFGE_ICONST:
- case ICMD_IFGT_ICONST:
- case ICMD_IFLE_ICONST:
- printf(" %d, %d (0x%08x)", iptr[1].op1, iptr->val.i, iptr->val.i);
- break;
-
- case ICMD_ELSE_ICONST:
- printf(" %d (0x%08x)", iptr->val.i, iptr->val.i);
- break;
-
- case ICMD_LADDCONST:
- case ICMD_LSUBCONST:
- case ICMD_LMULCONST:
- case ICMD_LMULPOW2:
- case ICMD_LDIVPOW2:
- case ICMD_LREMPOW2:
- case ICMD_LANDCONST:
- case ICMD_LORCONST:
- case ICMD_LXORCONST:
- case ICMD_LCONST:
- case ICMD_LASTORECONST:
-#if SIZEOF_VOID_P == 4
- printf(" %lld (0x%016llx)", iptr->val.l, iptr->val.l);
-#else
- printf(" %ld (0x%016lx)", iptr->val.l, iptr->val.l);
-#endif
- break;
+ return true;
- case ICMD_FCONST:
- printf(" %f (0x%08x)", iptr->val.f, iptr->val.i);
- break;
+ /* goto labels for throwing verifier exceptions **************************/
- case ICMD_DCONST:
-#if SIZEOF_VOID_P == 4
- printf(" %g (0x%016llx)", iptr->val.d, iptr->val.l);
-#else
- printf(" %g (0x%016lx)", iptr->val.d, iptr->val.l);
-#endif
- break;
+#if defined(ENABLE_VERIFIER)
- case ICMD_ACONST:
- case ICMD_AASTORECONST:
- /* check if this is a constant string or a class reference */
+throw_stack_underflow:
+ exceptions_throw_verifyerror(m, "Unable to pop operand off an empty stack");
+ return false;
- if (iptr->target) {
- if (iptr->val.a)
- printf(" %p", iptr->val.a);
- else
- printf(" (NOT RESOLVED)");
+throw_stack_overflow:
+ exceptions_throw_verifyerror(m, "Stack size too large");
+ return false;
- printf(", Class = \"");
- utf_display(((constant_classref *) iptr->target)->name);
- printf("\"");
+throw_stack_depth_error:
+ exceptions_throw_verifyerror(m,"Stack depth mismatch");
+ return false;
- }
- else {
- printf(" %p", iptr->val.a);
- if (iptr->val.a) {
- printf(", String = \"");
- utf_display(javastring_toutf(iptr->val.a, false));
- printf("\"");
- }
- }
- break;
-
- case ICMD_GETFIELD:
- case ICMD_PUTFIELD:
- if (iptr->val.a)
- printf(" %d, ", ((fieldinfo *) iptr->val.a)->offset);
- else
- printf(" (NOT RESOLVED), ");
- utf_display_classname(((unresolved_field *) iptr->target)->fieldref->classref->name);
- printf(".");
- utf_display(((unresolved_field *) iptr->target)->fieldref->name);
- printf(" (type ");
- utf_display(((unresolved_field *) iptr->target)->fieldref->descriptor);
- printf(")");
- break;
-
- case ICMD_PUTSTATIC:
- case ICMD_GETSTATIC:
- if (iptr->val.a) {
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(((fieldinfo *) iptr->val.a)->class))
- printf(" (NOT INITIALIZED) ");
- else
- printf(" ");
- }
- else
- printf(" (NOT RESOLVED) ");
- utf_display_classname(((unresolved_field *) iptr->target)->fieldref->classref->name);
- printf(".");
- utf_display(((unresolved_field *) iptr->target)->fieldref->name);
- printf(" (type ");
- utf_display(((unresolved_field *) iptr->target)->fieldref->descriptor);
- printf(")");
- break;
-
- case ICMD_PUTSTATICCONST:
- case ICMD_PUTFIELDCONST:
- switch (iptr[1].op1) {
- case TYPE_INT:
- printf(" %d (0x%08x),", iptr->val.i, iptr->val.i);
- break;
- case TYPE_LNG:
-#if SIZEOF_VOID_P == 4
- printf(" %lld (0x%016llx),", iptr->val.l, iptr->val.l);
-#else
- printf(" %ld (0x%016lx),", iptr->val.l, iptr->val.l);
-#endif
- break;
- case TYPE_ADR:
- printf(" %p,", iptr->val.a);
- break;
- case TYPE_FLT:
- printf(" %g (0x%08x),", iptr->val.f, iptr->val.i);
- break;
- case TYPE_DBL:
-#if SIZEOF_VOID_P == 4
- printf(" %g (0x%016llx),", iptr->val.d, iptr->val.l);
-#else
- printf(" %g (0x%016lx),", iptr->val.d, iptr->val.l);
-#endif
- break;
- }
- if (iptr->opc == ICMD_PUTFIELDCONST) {
- if (iptr[1].val.a)
- printf(" %d,", ((fieldinfo *) iptr[1].val.a)->offset);
- else
- printf(" (NOT RESOLVED),");
- }
- printf(" ");
- utf_display_classname(((unresolved_field *) iptr[1].target)->fieldref->classref->name);
- printf(".");
- utf_display(((unresolved_field *) iptr[1].target)->fieldref->name);
- printf(" (type ");
- utf_display(((unresolved_field *) iptr[1].target)->fieldref->descriptor);
- printf(")");
- break;
-
- case ICMD_IINC:
- printf(" %d + %d", iptr->op1, iptr->val.i);
- break;
-
- case ICMD_IASTORE:
- case ICMD_SASTORE:
- case ICMD_BASTORE:
- case ICMD_CASTORE:
- case ICMD_LASTORE:
- case ICMD_DASTORE:
- case ICMD_FASTORE:
- case ICMD_AASTORE:
-
- case ICMD_IALOAD:
- case ICMD_SALOAD:
- case ICMD_BALOAD:
- case ICMD_CALOAD:
- case ICMD_LALOAD:
- case ICMD_DALOAD:
- case ICMD_FALOAD:
- case ICMD_AALOAD:
- if (iptr->op1 != 0)
- printf("(opt.)");
- break;
-
- case ICMD_RET:
- case ICMD_ILOAD:
- case ICMD_LLOAD:
- case ICMD_FLOAD:
- case ICMD_DLOAD:
- case ICMD_ALOAD:
- case ICMD_ISTORE:
- case ICMD_LSTORE:
- case ICMD_FSTORE:
- case ICMD_DSTORE:
- case ICMD_ASTORE:
- printf(" %d", iptr->op1);
- break;
-
- case ICMD_NEW:
- printf(" ");
- utf_display_classname(((classinfo *) iptr->val.a)->name);
- break;
-
- case ICMD_NEWARRAY:
- switch (iptr->op1) {
- case 4:
- printf(" boolean");
- break;
- case 5:
- printf(" char");
- break;
- case 6:
- printf(" float");
- break;
- case 7:
- printf(" double");
- break;
- case 8:
- printf(" byte");
- break;
- case 9:
- printf(" short");
- break;
- case 10:
- printf(" int");
- break;
- case 11:
- printf(" long");
- break;
- }
- break;
+throw_stack_type_error:
+ exceptions_throw_verifyerror_for_stack(m, expectedtype);
+ return false;
- case ICMD_ANEWARRAY:
- if (iptr->op1) {
- printf(" ");
- utf_display_classname(((classinfo *) iptr->val.a)->name);
- }
- break;
+throw_stack_category_error:
+ exceptions_throw_verifyerror(m, "Attempt to split long or double on the stack");
+ return false;
- case ICMD_MULTIANEWARRAY:
- if (iptr->val.a == NULL) {
- printf(" (NOT RESOLVED) %d ", iptr->op1);
- utf_display(((constant_classref *) iptr->target)->name);
- }
- else {
- printf(" %d ",iptr->op1);
- utf_display_classname(((classinfo *) iptr->val.a)->name);
- }
- break;
-
- case ICMD_CHECKCAST:
- case ICMD_INSTANCEOF:
- {
- classinfo *c = iptr->val.a;
- if (c) {
- if (c->flags & ACC_INTERFACE)
- printf(" (INTERFACE) ");
- else
- printf(" (CLASS,%3d) ", c->vftbl->diffval);
- }
- else {
- printf(" (NOT RESOLVED) ");
- }
- utf_display_classname(((constant_classref *) iptr->target)->name);
- }
- break;
-
- case ICMD_INLINE_START:
- case ICMD_INLINE_END:
- printf(" ");
- utf_display_classname(iptr->method->class->name);
- printf(".");
- utf_display_classname(iptr->method->name);
- utf_display_classname(iptr->method->descriptor);
- break;
-
- case ICMD_BUILTIN:
- printf(" %s", ((builtintable_entry *) iptr->val.a)->name);
- break;
-
- case ICMD_INVOKEVIRTUAL:
- case ICMD_INVOKESPECIAL:
- case ICMD_INVOKESTATIC:
- case ICMD_INVOKEINTERFACE:
- if (!iptr->val.a)
- printf(" (NOT RESOLVED) ");
- else
- printf(" ");
- utf_display_classname(((unresolved_method *) iptr->target)->methodref->classref->name);
- printf(".");
- utf_display(((unresolved_method *) iptr->target)->methodref->name);
- utf_display(((unresolved_method *) iptr->target)->methodref->descriptor);
- break;
-
- case ICMD_IFEQ:
- case ICMD_IFNE:
- case ICMD_IFLT:
- case ICMD_IFGE:
- case ICMD_IFGT:
- case ICMD_IFLE:
- if (deadcode || !iptr->target)
- printf(" %d (0x%08x) op1=%d", iptr->val.i, iptr->val.i, iptr->op1);
- else
- printf(" %d (0x%08x) L%03d (%p)", iptr->val.i, iptr->val.i, ((basicblock *) iptr->target)->debug_nr,iptr->target);
- break;
-
- case ICMD_IF_LEQ:
- case ICMD_IF_LNE:
- case ICMD_IF_LLT:
- case ICMD_IF_LGE:
- case ICMD_IF_LGT:
- case ICMD_IF_LLE:
- if (deadcode || !iptr->target)
-#if SIZEOF_VOID_P == 4
- printf("(%lld) op1=%d", iptr->val.l, iptr->op1);
-#else
- printf("(%ld) op1=%d", iptr->val.l, iptr->op1);
-#endif
- else
-#if SIZEOF_VOID_P == 4
- printf("(%lld) L%03d", iptr->val.l, ((basicblock *) iptr->target)->debug_nr);
-#else
- printf("(%ld) L%03d", iptr->val.l, ((basicblock *) iptr->target)->debug_nr);
#endif
- break;
-
- case ICMD_JSR:
- case ICMD_GOTO:
- 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_LCMPEQ:
- case ICMD_IF_LCMPNE:
- case ICMD_IF_LCMPLT:
- case ICMD_IF_LCMPGE:
- case ICMD_IF_LCMPGT:
- case ICMD_IF_LCMPLE:
- case ICMD_IF_ACMPEQ:
- case ICMD_IF_ACMPNE:
- case ICMD_INLINE_GOTO:
- if (deadcode || !iptr->target)
- printf(" op1=%d", iptr->op1);
- else
- printf(" L%03d (%p)", ((basicblock *) iptr->target)->debug_nr,iptr->target);
- break;
+}
- case ICMD_TABLESWITCH:
- s4ptr = (s4*)iptr->val.a;
- if (deadcode || !iptr->target) {
- printf(" %d;", *s4ptr);
- }
- else {
- tptr = (void **) iptr->target;
- printf(" L%03d;", ((basicblock *) *tptr)->debug_nr);
- tptr++;
- }
+/* functions for verbose stack analysis output ********************************/
- s4ptr++; /* skip default */
- j = *s4ptr++; /* low */
- j = *s4ptr++ - j; /* high */
- while (j >= 0) {
- if (deadcode || !*tptr)
- printf(" %d", *s4ptr++);
- else {
- printf(" L%03d", ((basicblock *) *tptr)->debug_nr);
- tptr++;
- }
- j--;
- }
- break;
+#if defined(STACK_VERBOSE)
+static void stack_verbose_show_varinfo(stackdata_t *sd, varinfo *v)
+{
+ printf("%c", show_jit_type_letters[v->type]);
+ if (v->type == TYPE_RET)
+ printf("{L%03d}", v->vv.retaddr->nr);
+}
+
+
+static void stack_verbose_show_variable(stackdata_t *sd, s4 index)
+{
+ assert(index >= 0 && index < sd->vartop);
+ stack_verbose_show_varinfo(sd, sd->var + index);
+}
- case ICMD_LOOKUPSWITCH:
- s4ptr = (s4*)iptr->val.a;
- if (deadcode || !iptr->target) {
- printf(" %d;", *s4ptr);
+static void stack_verbose_show_block(stackdata_t *sd, basicblock *bptr)
+{
+ s4 i;
+
+ printf("L%03d type:%d in:%d [", bptr->nr, bptr->type, bptr->indepth);
+ if (bptr->invars) {
+ for (i=0; i<bptr->indepth; ++i) {
+ if (i)
+ putchar(' ');
+ stack_verbose_show_variable(sd, bptr->invars[i]);
}
- else {
- tptr = (void **) iptr->target;
- printf(" L%03d;", ((basicblock *) *tptr)->debug_nr);
- tptr++;
+ }
+ else
+ putchar('-');
+ printf("] inlocals [");
+ if (bptr->inlocals) {
+ for (i=0; i<sd->localcount; ++i) {
+ if (i)
+ putchar(' ');
+ stack_verbose_show_varinfo(sd, bptr->inlocals + i);
}
- s4ptr++; /* default */
- j = *s4ptr++; /* count */
-
- while (--j >= 0) {
- if (deadcode || !*tptr) {
- s4ptr++; /* skip value */
- printf(" %d",*s4ptr++);
- }
- else {
- printf(" L%03d", ((basicblock *) *tptr)->debug_nr);
- tptr++;
- }
+ }
+ else
+ putchar('-');
+ printf("] out:%d [", bptr->outdepth);
+ if (bptr->outvars) {
+ for (i=0; i<bptr->outdepth; ++i) {
+ if (i)
+ putchar(' ');
+ stack_verbose_show_variable(sd, bptr->outvars[i]);
+ }
+ }
+ else
+ putchar('-');
+ printf("]");
+
+ if (bptr->original)
+ printf(" (clone of L%03d)", bptr->original->nr);
+ else {
+ basicblock *b = bptr->copied_to;
+ if (b) {
+ printf(" (copied to ");
+ for (; b; b = b->copied_to)
+ printf("L%03d ", b->nr);
+ printf(")");
}
- break;
+ }
+}
+
+
+static void stack_verbose_block_enter(stackdata_t *sd, bool reanalyse)
+{
+ int i;
+
+ printf("======================================== STACK %sANALYSE BLOCK ",
+ (reanalyse) ? "RE-" : "");
+ stack_verbose_show_block(sd, sd->bptr);
+ printf("\n");
- case ICMD_ARETURN:
- if (iptr->val.a) {
- printf(" (NOT RESOLVED), Class = \"");
- utf_display(((unresolved_class *) iptr->val.a)->classref->name);
- printf("\"");
+ if (sd->handlers[0]) {
+ printf("HANDLERS: ");
+ for (i=0; sd->handlers[i]; ++i) {
+ printf("L%03d ", sd->handlers[i]->handler->nr);
}
+ printf("\n");
}
+ printf("\n");
+}
+
+
+static void stack_verbose_block_exit(stackdata_t *sd, bool superblockend)
+{
+ printf("%s ", (superblockend) ? "SUPERBLOCKEND" : "END");
+ stack_verbose_show_block(sd, sd->bptr);
+ printf("\n");
}
-#endif /* !defined(NDEBUG) */
+#endif
/*