-/* jit/stack.c - stack analysis
+/* vm/jit/stack.c - stack analysis
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
- R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
- M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
- P. Tomsich, J. Wenninger
+ Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+ R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
+ C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
+ Institut f. Computersprachen - TU Wien
This file is part of CACAO.
Changes: Edwin Steiner
- $Id: stack.c 1296 2004-07-10 17:02:15Z stefan $
+ $Id: stack.c 1735 2004-12-07 14:33:27Z twisti $
*/
#include <stdio.h>
#include <string.h>
-#include "global.h"
-#include "native.h"
-#include "builtin.h"
+
#include "disass.h"
-#include "tables.h"
#include "types.h"
-#include "options.h"
-#include "statistics.h"
-#include "jit/jit.h"
-#include "jit/stack.h"
-#include "jit/reg.h"
+#include "mm/memory.h"
+#include "native/native.h"
#include "toolbox/logging.h"
-#include "toolbox/memory.h"
-
-
-/* from codegen.inc */
-extern int dseglen;
-
-/**********************************************************************/
-/* Macros used internally by analyse_stack */
-/**********************************************************************/
-
-#ifdef STATISTICS
-#define COUNT(cnt) cnt++
-#else
-#define COUNT(cnt)
-#endif
-
-/* convenient abbreviations */
-#define CURKIND curstack->varkind
-#define CURTYPE curstack->type
-
-/*--------------------------------------------------*/
-/* SIGNALING ERRORS */
-/*--------------------------------------------------*/
-
-#define TYPEPANIC {panic("Stack type mismatch");}
-
-
-/*--------------------------------------------------*/
-/* STACK UNDERFLOW/OVERFLOW CHECKS */
-/*--------------------------------------------------*/
-
-/* underflow checks */
-
-#define REQUIRE(num) \
- do { \
- if (stackdepth < (num)) { \
- sprintf(msg, "(class: "); \
- utf_sprint(msg + strlen(msg), m->class->name); \
- sprintf(msg + strlen(msg), ", method: "); \
- utf_sprint(msg + strlen(msg), m->name); \
- sprintf(msg + strlen(msg), ", signature: "); \
- utf_sprint(msg + strlen(msg), m->descriptor); \
- sprintf(msg + strlen(msg), ") Unable to pop operand off an empty stack"); \
- *exceptionptr = \
- new_exception_message(string_java_lang_VerifyError, msg); \
- return NULL; \
- } \
- } while(0)
-
-#define REQUIRE_1 REQUIRE(1)
-#define REQUIRE_2 REQUIRE(2)
-#define REQUIRE_3 REQUIRE(3)
-#define REQUIRE_4 REQUIRE(4)
-
-
-/* overflow check */
-/* We allow ACONST instructions inserted as arguments to builtin
- * functions to exceed the maximum stack depth. Maybe we should check
- * against maximum stack depth only at block boundaries?
- */
-
-#define CHECKOVERFLOW \
- do { \
- if (stackdepth > m->maxstack) { \
- if (iptr[0].opc != ICMD_ACONST \
- || iptr[0].op1 == 0) { \
- sprintf(msg, "(class: "); \
- utf_sprint_classname(msg + strlen(msg), m->class->name); \
- sprintf(msg + strlen(msg), ", method: "); \
- utf_sprint(msg + strlen(msg), m->name); \
- sprintf(msg + strlen(msg), ", signature: "); \
- utf_sprint(msg + strlen(msg), m->descriptor); \
- sprintf(msg + strlen(msg), ") Stack size too large"); \
- *exceptionptr = \
- new_exception_message(string_java_lang_VerifyError, msg); \
- return NULL; \
- } \
- } \
- } while(0)
-
-
-/*--------------------------------------------------*/
-/* ALLOCATING STACK SLOTS */
-/*--------------------------------------------------*/
-
-#define NEWSTACK(s,v,n) {new->prev=curstack;new->type=s;new->flags=0; \
- new->varkind=v;new->varnum=n;curstack=new;new++;}
-#define NEWSTACKn(s,n) NEWSTACK(s,UNDEFVAR,n)
-#define NEWSTACK0(s) NEWSTACK(s,UNDEFVAR,0)
-
-/* allocate the input stack for an exception handler */
-#define NEWXSTACK {NEWSTACK(TYPE_ADR,STACKVAR,0);curstack=0;}
-
-
-/*--------------------------------------------------*/
-/* STACK MANIPULATION */
-/*--------------------------------------------------*/
-
-/* resetting to an empty operand stack */
-#define STACKRESET {curstack=0;stackdepth=0;}
-
-/* set the output stack of the current instruction */
-#define SETDST {iptr->dst=curstack;}
-
-/* The following macros do NOT check stackdepth, set stackdepth or iptr->dst */
-#define POP(s) {if(s!=curstack->type){TYPEPANIC;} \
- if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR;\
- curstack=curstack->prev;}
-#define POPANY {if(curstack->varkind==UNDEFVAR)curstack->varkind=TEMPVAR; \
- curstack=curstack->prev;}
-#define COPY(s,d) {(d)->flags=0;(d)->type=(s)->type;\
- (d)->varkind=(s)->varkind;(d)->varnum=(s)->varnum;}
-
-
-/*--------------------------------------------------*/
-/* STACK OPERATIONS MODELING */
-/*--------------------------------------------------*/
-
-/* The following macros are used to model the stack manipulations of
- * different kinds of instructions.
- *
- * These macros check the input stackdepth and they set the output
- * stackdepth and the output stack of the instruction (iptr->dst).
- *
- * These macros do *not* check for stack overflows!
- */
-
-#define PUSHCONST(s){NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
-#define LOAD(s,v,n) {NEWSTACK(s,v,n);SETDST;stackdepth++;}
-#define STORE(s) {REQUIRE_1;POP(s);SETDST;stackdepth--;}
-#define OP1_0(s) {REQUIRE_1;POP(s);SETDST;stackdepth--;}
-#define OP1_0ANY {REQUIRE_1;POPANY;SETDST;stackdepth--;}
-#define OP0_1(s) {NEWSTACKn(s,stackdepth);SETDST;stackdepth++;}
-#define OP1_1(s,d) {REQUIRE_1;POP(s);NEWSTACKn(d,stackdepth-1);SETDST;}
-#define OP2_0(s) {REQUIRE_2;POP(s);POP(s);SETDST;stackdepth-=2;}
-#define OPTT2_0(t,b){REQUIRE_2;POP(t);POP(b);SETDST;stackdepth-=2;}
-#define OP2_1(s) {REQUIRE_2;POP(s);POP(s);NEWSTACKn(s,stackdepth-2);SETDST;stackdepth--;}
-#define OP2IAT_1(s) {REQUIRE_2;POP(TYPE_INT);POP(TYPE_ADR);NEWSTACKn(s,stackdepth-2);\
- SETDST;stackdepth--;}
-#define OP2IT_1(s) {REQUIRE_2;POP(TYPE_INT);POP(s);NEWSTACKn(s,stackdepth-2);\
- SETDST;stackdepth--;}
-#define OPTT2_1(s,d){REQUIRE_2;POP(s);POP(s);NEWSTACKn(d,stackdepth-2);SETDST;stackdepth--;}
-#define OP2_2(s) {REQUIRE_2;POP(s);POP(s);NEWSTACKn(s,stackdepth-2);\
- NEWSTACKn(s,stackdepth-1);SETDST;}
-#define OP3TIA_0(s) {REQUIRE_3;POP(s);POP(TYPE_INT);POP(TYPE_ADR);SETDST;stackdepth-=3;}
-#define OP3_0(s) {REQUIRE_3;POP(s);POP(s);POP(s);SETDST;stackdepth-=3;}
-#define POPMANY(i) {REQUIRE(i);stackdepth-=i;while(--i>=0){POPANY;}SETDST;}
-#define DUP {REQUIRE_1;NEWSTACK(CURTYPE,CURKIND,curstack->varnum);SETDST; \
- stackdepth++;}
-#define SWAP {REQUIRE_2;COPY(curstack,new);POPANY;COPY(curstack,new+1);POPANY;\
- new[0].prev=curstack;new[1].prev=new;\
- curstack=new+1;new+=2;SETDST;}
-#define DUP_X1 {REQUIRE_2;COPY(curstack,new);COPY(curstack,new+2);POPANY;\
- COPY(curstack,new+1);POPANY;new[0].prev=curstack;\
- new[1].prev=new;new[2].prev=new+1;\
- curstack=new+2;new+=3;SETDST;stackdepth++;}
-#define DUP2_X1 {REQUIRE_3;COPY(curstack,new+1);COPY(curstack,new+4);POPANY;\
- COPY(curstack,new);COPY(curstack,new+3);POPANY;\
- COPY(curstack,new+2);POPANY;new[0].prev=curstack;\
- new[1].prev=new;new[2].prev=new+1;\
- new[3].prev=new+2;new[4].prev=new+3;\
- curstack=new+4;new+=5;SETDST;stackdepth+=2;}
-#define DUP_X2 {REQUIRE_3;COPY(curstack,new);COPY(curstack,new+3);POPANY;\
- COPY(curstack,new+2);POPANY;COPY(curstack,new+1);POPANY;\
- new[0].prev=curstack;new[1].prev=new;\
- new[2].prev=new+1;new[3].prev=new+2;\
- curstack=new+3;new+=4;SETDST;stackdepth++;}
-#define DUP2_X2 {REQUIRE_4;COPY(curstack,new+1);COPY(curstack,new+5);POPANY;\
- COPY(curstack,new);COPY(curstack,new+4);POPANY;\
- COPY(curstack,new+3);POPANY;COPY(curstack,new+2);POPANY;\
- new[0].prev=curstack;new[1].prev=new;\
- new[2].prev=new+1;new[3].prev=new+2;\
- new[4].prev=new+3;new[5].prev=new+4;\
- curstack=new+5;new+=6;SETDST;stackdepth+=2;}
-
-
-/*--------------------------------------------------*/
-/* MACROS FOR HANDLING BASIC BLOCKS */
-/*--------------------------------------------------*/
-
-/* COPYCURSTACK makes a copy of the current operand stack (curstack)
- * and returns it in the variable copy.
- *
- * This macro is used to propagate the operand stack from one basic
- * block to another. The destination block receives the copy as its
- * input stack.
- */
-#define COPYCURSTACK(copy) {\
- int d;\
- stackptr s;\
- if(curstack){\
- s=curstack;\
- new+=stackdepth;\
- d=stackdepth;\
- copy=new;\
- while(s){\
- copy--;d--;\
- copy->prev=copy-1;\
- copy->type=s->type;\
- copy->flags=0;\
- copy->varkind=STACKVAR;\
- copy->varnum=d;\
- s=s->prev;\
- }\
- copy->prev=NULL;\
- copy=new-1;\
- }\
- else\
- copy=NULL;\
-}
-
-/* BBEND is called at the end of each basic block (after the last
- * instruction of the block has been processed).
- */
-
-#define BBEND(s,i){ \
- i = stackdepth - 1; \
- copy = s; \
- while (copy) { \
- if ((copy->varkind == STACKVAR) && (copy->varnum > i)) \
- copy->varkind = TEMPVAR; \
- else { \
- copy->varkind = STACKVAR; \
- copy->varnum = i;\
- } \
- m->registerdata->interfaces[i][copy->type].type = copy->type; \
- m->registerdata->interfaces[i][copy->type].flags |= copy->flags; \
- i--; copy = copy->prev; \
- } \
- i = bptr->indepth - 1; \
- copy = bptr->instack; \
- while (copy) { \
- m->registerdata->interfaces[i][copy->type].type = copy->type; \
- if (copy->varkind == STACKVAR) { \
- if (copy->flags & SAVEDVAR) \
- m->registerdata->interfaces[i][copy->type].flags |= SAVEDVAR; \
- } \
- i--; copy = copy->prev; \
- } \
-}
-
-
-/* MARKREACHED marks the destination block <b> as reached. If this
- * block has been reached before we check if stack depth and types
- * match. Otherwise the destination block receives a copy of the
- * current stack as its input stack.
- *
- * b...destination block
- * c...current stack
- */
-#define MARKREACHED(b,c) { \
- if(b->flags<0) \
- {COPYCURSTACK(c);b->flags=0;b->instack=c;b->indepth=stackdepth;} \
- else {stackptr s=curstack;stackptr t=b->instack; \
- if(b->indepth!=stackdepth) \
- {show_icmd_method(m);panic("Stack depth mismatch");} \
- while(s){if (s->type!=t->type) \
- TYPEPANIC \
- s=s->prev;t=t->prev; \
- } \
- } \
-}
+#include "vm/global.h"
+#include "vm/builtin.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/tables.h"
+#include "vm/jit/codegen.inc.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/reg.h"
+#include "vm/jit/stack.h"
/**********************************************************************/
* types are not discerned.
*/
-methodinfo *analyse_stack(methodinfo *m)
+methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd)
{
int b_count;
int b_index;
basicblock *tbptr;
s4 *s4ptr;
void* *tptr;
- int *argren;
- char msg[MAXLOGTEXT]; /* maybe we get an exception */
+ s4 *argren;
- argren = DMNEW(int, m->maxlocals);
- /*int *argren = (int *)alloca(m->maxlocals * sizeof(int));*/ /* table for argument renaming */
- for (i = 0; i < m->maxlocals; i++)
+ argren = DMNEW(s4, cd->maxlocals); /* table for argument renaming */
+ for (i = 0; i < cd->maxlocals; i++)
argren[i] = i;
- m->registerdata->arguments_num = 0;
+ rd->arguments_num = 0;
new = m->stack;
loops = 0;
m->basicblocks[0].flags = BBREACHED;
m->basicblocks[0].instack = 0;
m->basicblocks[0].indepth = 0;
- for (i = 0; i < m->exceptiontablelength; i++) {
- bptr = &m->basicblocks[m->basicblockindex[m->exceptiontable[i].handlerpc]];
+ 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 = stackdepth;
}
else if (bptr->indepth != stackdepth) {
- show_icmd_method(m);
+ show_icmd_method(m, cd, rd);
+ printf("Block: %d, required depth: %d, current depth: %d\n", bptr->debug_nr, bptr->indepth, stackdepth);
panic("Stack depth mismatch");
}
if (breplace && opcode == breplace->opcode) {
iptr[0].opc = breplace->icmd;
iptr[0].op1 = breplace->type_d;
- iptr[0].val.a = breplace->builtin;
+ iptr[0].val.fp = breplace->builtin;
m->isleafmethod = false;
switch (breplace->icmd) {
case ICMD_BUILTIN1:
if (breplace && opcode == breplace->opcode) {
iptr[0].opc = breplace->icmd;
iptr[0].op1 = breplace->type_d;
- iptr[0].val.a = breplace->builtin;
+ iptr[0].val.fp = breplace->builtin;
m->isleafmethod = false;
switch (breplace->icmd) {
case ICMD_BUILTIN1:
break;
case ICMD_RET:
- m->registerdata->locals[iptr->op1][TYPE_ADR].type = TYPE_ADR;
+ rd->locals[iptr->op1][TYPE_ADR].type = TYPE_ADR;
case ICMD_RETURN:
COUNT(count_pcmd_return);
SETDST;
COUNT(count_pcmd_op);
#if SUPPORT_ONLY_ZERO_ASTORE
} else
-#endif /* SUPPORT_ONLY_ZERO_ASTORE */
PUSHCONST(TYPE_INT);
+#endif /* SUPPORT_ONLY_ZERO_ASTORE */
break;
#endif /* SUPPORT_CONST_ASTORE */
COUNT(count_pcmd_op);
#if SUPPORT_ONLY_ZERO_ASTORE
} else
-#endif /* SUPPORT_ONLY_ZERO_ASTORE */
PUSHCONST(TYPE_LNG);
+#endif /* SUPPORT_ONLY_ZERO_ASTORE */
break;
#endif /* SUPPORT_CONST_ASTORE */
#if SUPPORT_CONST_ASTORE
if (len > 0 && iptr->val.a == 0) {
if (iptr[1].opc == ICMD_BUILTIN3 &&
- iptr[1].val.a == BUILTIN_aastore) {
+ iptr[1].val.fp == BUILTIN_aastore) {
iptr[0].opc = ICMD_AASTORECONST;
iptr[1].opc = ICMD_NOP;
OPTT2_0(TYPE_INT, TYPE_ADR);
COUNT(count_load_instruction);
i = opcode-ICMD_ILOAD;
iptr->op1 = argren[iptr->op1];
- m->registerdata->locals[iptr->op1][i].type = i;
+ rd->locals[iptr->op1][i].type = i;
LOAD(i, LOCALVAR, iptr->op1);
break;
REQUIRE_1;
i = opcode - ICMD_ISTORE;
- m->registerdata->locals[iptr->op1][i].type = i;
+ rd->locals[iptr->op1][i].type = i;
#ifdef STATISTICS
count_pcmd_store++;
i = new - curstack;
#ifdef TYPECHECK_STACK_COMPCAT
if (opt_verify) {
REQUIRE_1;
- if (IS_2_WORD_TYPE(curstack->type))
- panic("Illegal instruction: POP on category 2 type");
+ if (IS_2_WORD_TYPE(curstack->type)) {
+ *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
+ return NULL;
+ }
}
#endif
OP1_0ANY;
case ICMD_POP2:
REQUIRE_1;
- if (! IS_2_WORD_TYPE(curstack->type)) {
+ if (!IS_2_WORD_TYPE(curstack->type)) {
/* ..., cat1 */
#ifdef TYPECHECK_STACK_COMPCAT
if (opt_verify) {
REQUIRE_2;
- if (IS_2_WORD_TYPE(curstack->prev->type))
- panic("Illegal instruction: POP2 on cat2, cat1 types");
+ if (IS_2_WORD_TYPE(curstack->prev->type)) {
+ *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
+ return NULL;
+ }
}
#endif
OP1_0ANY; /* second pop */
#ifdef TYPECHECK_STACK_COMPCAT
if (opt_verify) {
REQUIRE_1;
- if (IS_2_WORD_TYPE(curstack->type))
- panic("Illegal instruction: DUP on category 2 type");
+ if (IS_2_WORD_TYPE(curstack->type)) {
+ *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
+ return NULL;
+ }
}
#endif
COUNT(count_dup_instruction);
/* ..., ????, cat1 */
#ifdef TYPECHECK_STACK_COMPCAT
if (opt_verify) {
- if (IS_2_WORD_TYPE(curstack->prev->type))
- panic("Illegal instruction: DUP2 on cat2, cat1 types");
+ if (IS_2_WORD_TYPE(curstack->prev->type)) {
+ *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
+ return NULL;
+ }
}
#endif
copy = curstack;
NEWSTACK(copy->type, copy->varkind,
copy->varnum);
SETDST;
- stackdepth+=2;
+ stackdepth += 2;
}
break;
if (opt_verify) {
REQUIRE_2;
if (IS_2_WORD_TYPE(curstack->type) ||
- IS_2_WORD_TYPE(curstack->prev->type))
- panic("Illegal instruction: DUP_X1 on cat 2 type");
+ IS_2_WORD_TYPE(curstack->prev->type)) {
+ *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
+ return NULL;
+ }
}
#endif
DUP_X1;
/* ..., ????, cat2 */
#ifdef TYPECHECK_STACK_COMPCAT
if (opt_verify) {
- if (IS_2_WORD_TYPE(curstack->prev->type))
- panic("Illegal instruction: DUP2_X1 on cat2, cat2 types");
+ if (IS_2_WORD_TYPE(curstack->prev->type)) {
+ *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
+ return NULL;
+ }
}
#endif
iptr->opc = ICMD_DUP_X1;
if (opt_verify) {
REQUIRE_3;
if (IS_2_WORD_TYPE(curstack->prev->type)
- || IS_2_WORD_TYPE(curstack->prev->prev->type))
- panic("Illegal instruction: DUP2_X1 on invalid types");
+ || IS_2_WORD_TYPE(curstack->prev->prev->type)) {
+ *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
+ return NULL;
+ }
}
#endif
DUP2_X1;
/* ..., cat2, ???? */
#ifdef TYPECHECK_STACK_COMPCAT
if (opt_verify) {
- if (IS_2_WORD_TYPE(curstack->type))
- panic("Illegal instruction: DUP_X2 on cat2, cat2 types");
+ if (IS_2_WORD_TYPE(curstack->type)) {
+ *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
+ return NULL;
+ }
}
#endif
iptr->opc = ICMD_DUP_X1;
if (opt_verify) {
REQUIRE_3;
if (IS_2_WORD_TYPE(curstack->type)
- || IS_2_WORD_TYPE(curstack->prev->prev->type))
- panic("Illegal instruction: DUP_X2 on invalid types");
+ || IS_2_WORD_TYPE(curstack->prev->prev->type)) {
+ *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
+ return NULL;
+ }
}
#endif
DUP_X2;
#ifdef TYPECHECK_STACK_COMPCAT
if (opt_verify) {
REQUIRE_3;
- if (IS_2_WORD_TYPE(curstack->prev->prev->type))
- panic("Illegal instruction: DUP2_X2 on invalid types");
+ if (IS_2_WORD_TYPE(curstack->prev->prev->type)) {
+ *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
+ return NULL;
+ }
}
#endif
iptr->opc = ICMD_DUP_X2;
/* ..., cat2, ????, cat1 */
#ifdef TYPECHECK_STACK_COMPCAT
if (opt_verify) {
- if (IS_2_WORD_TYPE(curstack->prev->type))
- panic("Illegal instruction: DUP2_X2 on invalid types");
+ if (IS_2_WORD_TYPE(curstack->prev->type)) {
+ *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
+ return NULL;
+ }
}
#endif
iptr->opc = ICMD_DUP2_X1;
if (opt_verify) {
REQUIRE_4;
if (IS_2_WORD_TYPE(curstack->prev->type)
- || IS_2_WORD_TYPE(curstack->prev->prev->prev->type))
- panic("Illegal instruction: DUP2_X2 on invalid types");
+ || IS_2_WORD_TYPE(curstack->prev->prev->prev->type)) {
+ *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
+ return NULL;
+ }
}
#endif
DUP2_X2;
if (opt_verify) {
REQUIRE_2;
if (IS_2_WORD_TYPE(curstack->type)
- || IS_2_WORD_TYPE(curstack->prev->type))
- panic("Illegal instruction: SWAP on category 2 type");
+ || IS_2_WORD_TYPE(curstack->prev->type)) {
+ *exceptionptr = new_verifyerror(m, "Attempt to split long or double on the stack");
+ return NULL;
+ }
}
#endif
SWAP;
#if !SUPPORT_DIVISION
iptr[0].opc = ICMD_BUILTIN2;
iptr[0].op1 = TYPE_INT;
- iptr[0].val.a = BUILTIN_idiv;
+ iptr[0].val.fp = BUILTIN_idiv;
m->isleafmethod = false;
goto builtin2;
#endif
#if !SUPPORT_DIVISION
iptr[0].opc = ICMD_BUILTIN2;
iptr[0].op1 = TYPE_INT;
- iptr[0].val.a = BUILTIN_irem;
+ iptr[0].val.fp = BUILTIN_irem;
m->isleafmethod = false;
goto builtin2;
#endif
#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
iptr[0].opc = ICMD_BUILTIN2;
iptr[0].op1 = TYPE_LNG;
- iptr[0].val.a = BUILTIN_ldiv;
+ iptr[0].val.fp = BUILTIN_ldiv;
m->isleafmethod = false;
goto builtin2;
#endif
#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
iptr[0].opc = ICMD_BUILTIN2;
iptr[0].op1 = TYPE_LNG;
- iptr[0].val.a = BUILTIN_lrem;
+ iptr[0].val.fp = BUILTIN_lrem;
m->isleafmethod = false;
goto builtin2;
#endif
if (lm->flags & ACC_STATIC)
{COUNT(count_check_null);}
i = iptr->op1;
- if (i > m->registerdata->arguments_num)
- m->registerdata->arguments_num = i;
+ if (i > rd->arguments_num)
+ rd->arguments_num = i;
REQUIRE(i);
#if defined(__X86_64__)
{
copy = copy->prev;
}
- stackargs += (iarg < m->registerdata->intreg_argnum) ?
- 0 : (iarg - m->registerdata->intreg_argnum);
- stackargs += (farg < m->registerdata->fltreg_argnum) ?
- 0 : (farg - m->registerdata->fltreg_argnum);
+ stackargs += (iarg < rd->intreg_argnum) ?
+ 0 : (iarg - rd->intreg_argnum);
+ stackargs += (farg < rd->fltreg_argnum) ?
+ 0 : (farg - rd->fltreg_argnum);
i = iptr->op1;
copy = curstack;
if (!(copy->flags & SAVEDVAR)) {
copy->varkind = ARGVAR;
if (IS_FLT_DBL_TYPE(copy->type)) {
- if (--farg < m->registerdata->fltreg_argnum) {
+ if (--farg < rd->fltreg_argnum) {
copy->varnum = farg;
} else {
- copy->varnum = --stackargs + m->registerdata->intreg_argnum;
+ copy->varnum = --stackargs + rd->intreg_argnum;
}
} else {
- if (--iarg < m->registerdata->intreg_argnum) {
+ if (--iarg < rd->intreg_argnum) {
copy->varnum = iarg;
} else {
- copy->varnum = --stackargs + m->registerdata->intreg_argnum;
+ copy->varnum = --stackargs + rd->intreg_argnum;
}
}
} else {
}
break;
}
+ case ICMD_INLINE_START:
+ case ICMD_INLINE_END:
+ SETDST;
+ break;
case ICMD_BUILTIN3:
/* DEBUG */ /*dolog("builtin3");*/
curstack->varkind = ARGVAR;
curstack->varnum = 2;
}
- if (3 > m->registerdata->arguments_num) {
- m->registerdata->arguments_num = 3;
+ if (3 > rd->arguments_num) {
+ rd->arguments_num = 3;
}
OP1_0ANY;
curstack->varkind = ARGVAR;
curstack->varnum = 1;
}
- if (2 > m->registerdata->arguments_num) {
- m->registerdata->arguments_num = 2;
+ if (2 > rd->arguments_num) {
+ rd->arguments_num = 2;
}
OP1_0ANY;
curstack->varkind = ARGVAR;
curstack->varnum = 0;
}
- if (1 > m->registerdata->arguments_num) {
- m->registerdata->arguments_num = 1;
+ if (1 > rd->arguments_num) {
+ rd->arguments_num = 1;
}
OP1_0ANY;
copy = curstack;
case ICMD_MULTIANEWARRAY:
i = iptr->op1;
REQUIRE(i);
- if ((i + m->registerdata->intreg_argnum) > m->registerdata->arguments_num)
- m->registerdata->arguments_num = i + m->registerdata->intreg_argnum;
+ if ((i + rd->intreg_argnum) > rd->arguments_num)
+ rd->arguments_num = i + rd->intreg_argnum;
copy = curstack;
while (--i >= 0) {
/* check INT type here? Currently typecheck does this. */
if (! (copy->flags & SAVEDVAR)) {
copy->varkind = ARGVAR;
- copy->varnum = i + m->registerdata->intreg_argnum;
+ copy->varnum = i + rd->intreg_argnum;
}
copy = copy->prev;
}
break;
case ICMD_CLEAR_ARGREN:
- for (i = iptr->op1; i<m->maxlocals; i++)
+ for (i = iptr->op1; i < cd->maxlocals; i++)
argren[i] = i;
iptr->opc = opcode = ICMD_NOP;
SETDST;
break;
default:
- printf("ICMD %d at %d\n", iptr->opc, (s4) (iptr - m->instructions));
- panic("Missing ICMD code during stack analysis");
+ *exceptionptr =
+ new_exception_message(string_java_lang_InternalError,
+ "Unknown ICMD");
+ return NULL;
} /* switch */
CHECKOVERFLOW;
-
- /* DEBUG */ /*dolog("iptr++");*/
iptr++;
} /* while instructions */
+
bptr->outstack = curstack;
bptr->outdepth = stackdepth;
BBEND(curstack, i);
} /* while blocks */
} while (repeat && !deadcode);
-#ifdef STATISTICS
- 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);
+#if defined(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]++;
+ 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++;
}
- bptr++;
- }
- if (loops == 1)
- count_analyse_iterations[0]++;
- else if (loops == 2)
- count_analyse_iterations[1]++;
- else if (loops == 3)
- count_analyse_iterations[2]++;
- else if (loops == 4)
- count_analyse_iterations[3]++;
- else
- count_analyse_iterations[4]++;
-
- if (m->basicblockcount <= 5)
- count_method_bb_distribution[0]++;
- else if (m->basicblockcount <= 10)
- count_method_bb_distribution[1]++;
- else if (m->basicblockcount <= 15)
- count_method_bb_distribution[2]++;
- else if (m->basicblockcount <= 20)
- count_method_bb_distribution[3]++;
- else if (m->basicblockcount <= 30)
- count_method_bb_distribution[4]++;
- else if (m->basicblockcount <= 40)
- count_method_bb_distribution[5]++;
- else if (m->basicblockcount <= 50)
- count_method_bb_distribution[6]++;
- else if (m->basicblockcount <= 75)
- count_method_bb_distribution[7]++;
- else
- count_method_bb_distribution[8]++;
+ if (loops == 1)
+ count_analyse_iterations[0]++;
+ else if (loops == 2)
+ count_analyse_iterations[1]++;
+ else if (loops == 3)
+ count_analyse_iterations[2]++;
+ else if (loops == 4)
+ count_analyse_iterations[3]++;
+ else
+ count_analyse_iterations[4]++;
+
+ if (m->basicblockcount <= 5)
+ count_method_bb_distribution[0]++;
+ else if (m->basicblockcount <= 10)
+ count_method_bb_distribution[1]++;
+ else if (m->basicblockcount <= 15)
+ count_method_bb_distribution[2]++;
+ else if (m->basicblockcount <= 20)
+ count_method_bb_distribution[3]++;
+ else if (m->basicblockcount <= 30)
+ count_method_bb_distribution[4]++;
+ else if (m->basicblockcount <= 40)
+ count_method_bb_distribution[5]++;
+ else if (m->basicblockcount <= 50)
+ count_method_bb_distribution[6]++;
+ else if (m->basicblockcount <= 75)
+ count_method_bb_distribution[7]++;
+ else
+ count_method_bb_distribution[8]++;
+ }
#endif
/* just return methodinfo* to signal everything was ok */
/* DEBUGGING HELPERS */
/**********************************************************************/
-void icmd_print_stack(methodinfo *m, stackptr s)
+void icmd_print_stack(codegendata *cd, stackptr s)
{
int i, j;
stackptr t;
- i = m->maxstack;
+ i = cd->maxstack;
t = s;
while (t) {
i--;
t = t->prev;
}
- j = m->maxstack - i;
+ j = cd->maxstack - i;
while (--i >= 0)
printf(" ");
while (s) {
};
-void show_icmd_method(methodinfo *m)
+void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd)
{
int i, j;
basicblock *bptr;
printf(".");
utf_fprint(stdout, m->name);
utf_fprint_classname(stdout, m->descriptor);
- printf ("\n\nMax locals: %d\n", (int) m->maxlocals);
- printf ("Max stack: %d\n", (int) m->maxstack);
+ printf("\n\nMax locals: %d\n", (int) cd->maxlocals);
+ printf("Max stack: %d\n", (int) cd->maxstack);
- printf ("Line number table length: %d\n", m->linenumbercount);
+ printf("Line number table length: %d\n", m->linenumbercount);
- printf ("Exceptions (Number: %d):\n", m->exceptiontablelength);
- for (ex = m->exceptiontable; ex != NULL; ex = ex->down) {
+ 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\n", ex->handler->debug_nr);
}
- printf ("Local Table:\n");
- for (i = 0; i < m->maxlocals; i++) {
+ printf("Local Table:\n");
+ for (i = 0; i < cd->maxlocals; i++) {
printf(" %3d: ", i);
for (j = TYPE_INT; j <= TYPE_ADR; j++)
- if (m->registerdata->locals[i][j].type >= 0) {
+ if (rd->locals[i][j].type >= 0) {
printf(" (%s) ", jit_type[j]);
- if (m->registerdata->locals[i][j].flags & INMEMORY)
- printf("m%2d", m->registerdata->locals[i][j].regoff);
+ if (rd->locals[i][j].flags & INMEMORY)
+ printf("m%2d", rd->locals[i][j].regoff);
else if ((j == TYPE_FLT) || (j == TYPE_DBL))
- printf("f%02d", m->registerdata->locals[i][j].regoff);
+ printf("f%02d", rd->locals[i][j].regoff);
else {
- printf("%3s", regs[m->registerdata->locals[i][j].regoff]);
+ printf("%3s", regs[rd->locals[i][j].regoff]);
}
}
printf("\n");
}
printf("\n");
-
- printf ("Interface Table:\n");
- for (i = 0; i < m->maxstack; i++) {
- if ((m->registerdata->interfaces[i][0].type >= 0) ||
- (m->registerdata->interfaces[i][1].type >= 0) ||
- (m->registerdata->interfaces[i][2].type >= 0) ||
- (m->registerdata->interfaces[i][3].type >= 0) ||
- (m->registerdata->interfaces[i][4].type >= 0)) {
+#ifdef LSRA
+ if (!opt_lsra) {
+#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);
for (j = TYPE_INT; j <= TYPE_ADR; j++)
- if (m->registerdata->interfaces[i][j].type >= 0) {
+ if (rd->interfaces[i][j].type >= 0) {
printf(" (%s) ", jit_type[j]);
- if (m->registerdata->interfaces[i][j].flags & SAVEDVAR) {
- if (m->registerdata->interfaces[i][j].flags & INMEMORY)
- printf("M%2d", m->registerdata->interfaces[i][j].regoff);
+ if (rd->interfaces[i][j].flags & SAVEDVAR) {
+ if (rd->interfaces[i][j].flags & INMEMORY)
+ printf("M%2d", rd->interfaces[i][j].regoff);
else if ((j == TYPE_FLT) || (j == TYPE_DBL))
- printf("F%02d", m->registerdata->interfaces[i][j].regoff);
+ printf("F%02d", rd->interfaces[i][j].regoff);
else {
- printf("%3s", regs[m->registerdata->interfaces[i][j].regoff]);
+ printf("%3s", regs[rd->interfaces[i][j].regoff]);
}
}
else {
- if (m->registerdata->interfaces[i][j].flags & INMEMORY)
- printf("m%2d", m->registerdata->interfaces[i][j].regoff);
+ if (rd->interfaces[i][j].flags & INMEMORY)
+ printf("m%2d", rd->interfaces[i][j].regoff);
else if ((j == TYPE_FLT) || (j == TYPE_DBL))
- printf("f%02d", m->registerdata->interfaces[i][j].regoff);
+ printf("f%02d", rd->interfaces[i][j].regoff);
else {
- printf("%3s", regs[m->registerdata->interfaces[i][j].regoff]);
+ printf("%3s", regs[rd->interfaces[i][j].regoff]);
}
}
}
}
}
printf("\n");
-
+#ifdef LSRA
+ }
+#endif
if (showdisassemble) {
#if defined(__I386__) || defined(__X86_64__)
u1 *u1ptr;
s4 a;
- u1ptr = m->mcode + dseglen;
+ u1ptr = (u1 *) ((ptrint) m->mcode + cd->dseglen);
for (i = 0; i < m->basicblocks[0].mpc; i++, u1ptr++) {
a = disassinstr(u1ptr, i);
i += a;
#else
s4 *s4ptr;
- s4ptr = (s4 *) (m->mcode + dseglen);
+ s4ptr = (s4 *) ((ptrint) m->mcode + cd->dseglen);
for (i = 0; i < m->basicblocks[0].mpc; i += 4, s4ptr++) {
disassinstr(s4ptr, i);
}
}
for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
- show_icmd_block(m, bptr);
+ show_icmd_block(m, cd, bptr);
}
}
-void show_icmd_block(methodinfo *m, basicblock *bptr)
+void show_icmd_block(methodinfo *m, codegendata *cd, basicblock *bptr)
{
int i, j;
int deadcode;
deadcode = bptr->flags <= BBREACHED;
printf("[");
if (deadcode)
- for (j = m->maxstack; j > 0; j--)
+ for (j = cd->maxstack; j > 0; j--)
printf(" ? ");
else
- icmd_print_stack(m, bptr->instack);
+ icmd_print_stack(cd, bptr->instack);
printf("] L%03d(%d - %d) flags=%d:\n", bptr->debug_nr, bptr->icount, bptr->pre_count,bptr->flags);
iptr = bptr->iinstr;
for (i = 0; i < bptr->icount; i++, iptr++) {
printf("[");
if (deadcode) {
- for (j = m->maxstack; j > 0; j--)
+ for (j = cd->maxstack; j > 0; j--)
printf(" ? ");
}
else
- icmd_print_stack(m, iptr->dst);
+ icmd_print_stack(cd, iptr->dst);
printf("] %4d ", i);
show_icmd(iptr, deadcode);
printf("\n");
printf("\n");
i = bptr->mpc;
- u1ptr = m->mcode + dseglen + i;
+ u1ptr = (u1 *) ((ptrint) m->mcode + cd->dseglen + i);
if (bptr->next != NULL) {
for (; i < bptr->next->mpc; i++, u1ptr++) {
printf("\n");
} else {
- for (; u1ptr < (u1 *) (m->mcode + m->mcodelength); i++, u1ptr++) {
+ for (; u1ptr < (u1 *) ((ptrint) m->mcode + m->mcodelength); i++, u1ptr++) {
a = disassinstr(u1ptr, i);
i += a;
u1ptr += a;
printf("\n");
i = bptr->mpc;
- s4ptr = (s4 *) (m->mcode + dseglen + i);
+ s4ptr = (s4 *) ((ptrint) m->mcode + cd->dseglen + i);
if (bptr->next != NULL) {
for (; i < bptr->next->mpc; i += 4, s4ptr++) {
printf("\n");
} else {
- for (; s4ptr < (s4 *) (m->mcode + m->mcodelength); i += 4, s4ptr++) {
+ for (; s4ptr < (s4 *) ((ptrint) m->mcode + m->mcodelength); i += 4, s4ptr++) {
disassinstr(s4ptr, i);
}
printf("\n");
printf("%s", icmd_names[iptr->opc]);
- switch ((int) iptr->opc) {
+ switch (iptr->opc) {
case ICMD_IADDCONST:
case ICMD_ISUBCONST:
case ICMD_IMULCONST:
}
break;
+ case ICMD_INLINE_START:
+ printf("\t\t\t%s.%s%s depth=%i",iptr->method->class->name->text,iptr->method->name->text,iptr->method->descriptor->text, iptr->op1);
+ break;
+ case ICMD_INLINE_END:
+ break;
+
case ICMD_BUILTIN3:
case ICMD_BUILTIN2:
case ICMD_BUILTIN1:
- printf(" %s", icmd_builtin_name((functionptr) iptr->val.a));
+ printf(" %s", icmd_builtin_name((functionptr) iptr->val.fp));
break;
case ICMD_INVOKEVIRTUAL:
}
break;
}
- printf(" Line number: %d, method:",iptr->line);
- utf_display(iptr->method->class->name);
- printf(".");
- utf_display(iptr->method->name);
+ printf(" Line number: %d, method:",iptr->line);
+/* printf("\t\t");
+ utf_display(iptr->method->class->name);
+ printf(".");
+ utf_display(iptr->method->name); */
}