X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fstack.h;h=2af166477e2e98c6358f6bdc976a8c5d869a1f3d;hb=9f859ad50d3d5d98c185d40b86b2179bc4dc9aeb;hp=1950606e3793e1e7c155d2ce783e0a22888af60a;hpb=822b618bd06ac404897f2edd0d97ae8e91b6c2fa;p=cacao.git diff --git a/src/vm/jit/stack.h b/src/vm/jit/stack.h index 1950606e3..2af166477 100644 --- a/src/vm/jit/stack.h +++ b/src/vm/jit/stack.h @@ -27,8 +27,7 @@ Authors: Christian Thalinger Changes: Christian Ullrich - - $Id: stack.h 4676 2006-03-22 18:32:47Z edwin $ + Edwin Steiner */ @@ -48,27 +47,23 @@ /* macros used internally by analyse_stack ************************************/ -#if defined(ENABLE_LSRA) -# define INC_LIFETIMES(a) { m->maxlifetimes += (a); } -#else -# define INC_LIFETIMES(a) -#endif - -/* convenient abbreviations */ -#define CURKIND curstack->varkind -#define CURTYPE curstack->type - - /*--------------------------------------------------*/ -/* SIGNALING ERRORS */ +/* BASIC TYPE CHECKING */ /*--------------------------------------------------*/ -#define TYPE_VERIFYERROR(t) \ - do { \ - exceptions_throw_verifyerror_for_stack(m,t); \ - return NULL; \ - } while (0) +/* XXX would be nice if we did not have to pass the expected type */ +#if defined(ENABLE_VERIFIER) +#define CHECK_BASIC_TYPE(expected,actual) \ + do { \ + if ((actual) != (expected)) { \ + expectedtype = (expected); \ + goto throw_stack_type_error; \ + } \ + } while (0) +#else /* !ENABLE_VERIFIER */ +#define CHECK_BASIC_TYPE(expected,actual) +#endif /* ENABLE_VERIFIER */ /*--------------------------------------------------*/ /* STACK UNDERFLOW/OVERFLOW CHECKS */ @@ -77,19 +72,14 @@ /* underflow checks */ #if defined(ENABLE_VERIFIER) -#define REQUIRE(num) \ - do { \ - if (stackdepth < (num)) \ - goto throw_stack_underflow; \ - } while (0) +#define REQUIRE(num) \ + do { \ + if (stackdepth < (num)) \ + goto throw_stack_underflow; \ + } while (0) #else /* !ENABLE_VERIFIER */ #define REQUIRE(num) #endif /* ENABLE_VERIFIER */ - -#define REQUIRE_1 REQUIRE(1) -#define REQUIRE_2 REQUIRE(2) -#define REQUIRE_3 REQUIRE(3) -#define REQUIRE_4 REQUIRE(4) /* overflow check */ @@ -100,12 +90,12 @@ /* XXX we should find a way to remove the opc/op1 check */ #if defined(ENABLE_VERIFIER) -#define CHECKOVERFLOW \ - do { \ - if (stackdepth > m->maxstack) \ - if (iptr[0].opc != ICMD_ACONST || iptr[0].op1 == 0) \ - goto throw_stack_overflow; \ - } while(0) +#define CHECKOVERFLOW \ + do { \ + if (stackdepth > m->maxstack) \ + if ((iptr->opc != ICMD_ACONST) || INSTRUCTION_MUST_CHECK(iptr))\ + goto throw_stack_overflow; \ + } while(0) #else /* !ENABLE_VERIFIER */ #define CHECKOVERFLOW #endif /* ENABLE_VERIFIER */ @@ -114,388 +104,34 @@ /* ALLOCATING STACK SLOTS */ /*--------------------------------------------------*/ -#define NEWSTACK_(s,v,n) \ - do { \ - new->prev = curstack; \ - new->type = (s); \ - new->flags = 0; \ - new->varkind = (v); \ - new->varnum = (n); \ - curstack = new; \ - new++; \ +#define NEWSTACK(s,v,n) \ + do { \ + sd.new->prev = curstack; \ + sd.new->type = (s); \ + sd.new->flags = 0; \ + sd.new->varkind = (v); \ + sd.new->varnum = (n); \ + curstack = sd.new; \ + sd.var[(n)].type = (s); \ + sd.var[(n)].flags = 0; \ + sd.new++; \ } while (0) - -/* Initialize regoff, so -sia can show regnames even before reg.inc */ -/* regs[rd->intregargnum has to be set for this */ -/* new->regoff = (IS_FLT_DBL_TYPE(s))?-1:rd->intreg_argnum; }*/ - -#define NEWSTACK(s,v,n) { NEWSTACK_(s,v,n); INC_LIFETIMES(1); } +/* Initialize regoff, so -sia can show regnames even before reg.inc */ +/* regs[rd->intregargnum] has to be set for this */ +/* new->regoff = (IS_FLT_DBL_TYPE(s))?-1:rd->intreg_argnum; } */ #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 \ - do { \ - curstack = 0; \ - stackdepth = 0; \ - } while (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) \ - do { \ - if ((s) != curstack->type) { \ - TYPE_VERIFYERROR((s)); \ - } \ - if (curstack->varkind == UNDEFVAR) \ - curstack->varkind = TEMPVAR; \ - curstack = curstack->prev; \ - } while (0) - -#define POPANY \ - do { \ - if (curstack->varkind == UNDEFVAR) \ - curstack->varkind = TEMPVAR; \ - curstack = curstack->prev; \ - } while (0) - -/* Do not copy Interface Stackslots over DUPx, Swaps! */ -#define COPY(s,d) \ - do { \ - (d)->flags = 0; \ - (d)->type = (s)->type; \ - if ( (s)->varkind != STACKVAR) { \ - (d)->varkind = (s)->varkind; \ - (d)->varnum = (s)->varnum; \ - } else { \ - (d)->varkind = TEMPVAR; \ - (d)->varnum = 0; \ - } \ - } while (0) - - -/*--------------------------------------------------*/ -/* 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) \ - do { \ - REQUIRE_1; \ - POP(s); \ - SETDST; \ - stackdepth--; \ - } while (0) - -#define OP1_0ANY \ - do { \ - REQUIRE_1; \ - POPANY; \ - SETDST; \ - stackdepth--; \ - } while (0) - -#define OP0_1(s) \ - do { \ - NEWSTACKn(s, stackdepth); \ - SETDST; \ - stackdepth++; \ - } while (0) - -#define OP1_1(s,d) \ - do { \ - REQUIRE_1; \ - POP(s); \ - NEWSTACKn(d, stackdepth - 1);\ - SETDST; \ - } while (0) - -#define OP2_0(s) \ - do { \ - REQUIRE_2; \ - POP(s); \ - POP(s); \ - SETDST; \ - stackdepth -= 2; \ - } while (0) - -#define OPTT2_0(t,b) \ - do { \ - REQUIRE_2; \ - POP(t); \ - POP(b); \ - SETDST; \ - stackdepth -= 2; \ - } while (0) - -#define OP2_1(s) \ - do { \ - REQUIRE_2; \ - POP(s); \ - POP(s); \ - NEWSTACKn(s, stackdepth - 2); \ - SETDST; \ - stackdepth--; \ - } while (0) - -#define OP2IAT_1(s) \ - do { \ - REQUIRE_2; \ - POP(TYPE_INT); \ - POP(TYPE_ADR); \ - NEWSTACKn(s, stackdepth - 2); \ - SETDST; \ - stackdepth--; \ - } while (0) - -#define OP2IT_1(s) \ - do { \ - REQUIRE_2; \ - POP(TYPE_INT); \ - POP(s); \ - NEWSTACKn(s, stackdepth - 2); \ - SETDST; \ - stackdepth--; \ - } while (0) - -#define OPTT2_1(s,d) \ - do { \ - REQUIRE_2; \ - POP(s); \ - POP(s); \ - NEWSTACKn(d, stackdepth - 2); \ - SETDST; \ - stackdepth--; \ - } while (0) - -#define OP2_2(s) \ - do { \ - REQUIRE_2; \ - POP(s); \ - POP(s); \ - NEWSTACKn(s, stackdepth - 2); \ - NEWSTACKn(s, stackdepth - 1); \ - SETDST; \ - } while (0) - -#define OP3TIA_0(s) \ - do { \ - REQUIRE_3; \ - POP(s); \ - POP(TYPE_INT); \ - POP(TYPE_ADR); \ - SETDST; \ - stackdepth -= 3; \ - } while (0) - -#define OP3_0(s) \ - do { \ - REQUIRE_3; \ - POP(s); \ - POP(s); \ - POP(s); \ - SETDST; \ - stackdepth -= 3; \ - } while (0) - -#define POPMANY(i) \ - do { \ - REQUIRE((i)); \ - stackdepth -= (i); \ - while(--(i) >= 0) { \ - POPANY; \ - } \ - SETDST; \ - } while (0) - -/* Do not copy Interface Stackslots over DUP! */ -#define DUP {REQUIRE_1; \ - if (CURKIND != STACKVAR) { \ - NEWSTACK(CURTYPE,CURKIND,curstack->varnum); \ - } else { \ - NEWSTACK(CURTYPE, TEMPVAR, stackdepth); \ - } \ - SETDST; stackdepth++; INC_LIFETIMES(1);} -#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++; INC_LIFETIMES(3);} -#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; INC_LIFETIMES(5);} -#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++; INC_LIFETIMES(4);} -#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; INC_LIFETIMES(6);} - - -/*--------------------------------------------------*/ -/* 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). - */ - - -#if defined(ENABLE_INTRP) -#define IF_NO_INTRP(x) if (!opt_intrp) { x } -#else -#define IF_NO_INTRP(x) { x } -#endif - -#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);\ - } \ - IF_NO_INTRP(rd->interfaces[(i)][copy->type].type = copy->type; \ - rd->interfaces[(i)][copy->type].flags |= copy->flags;) \ - (i)--; copy = copy->prev; \ - } \ - (i) = bptr->indepth - 1; \ - copy = bptr->instack; \ - while (copy) { \ - IF_NO_INTRP( \ - rd->interfaces[(i)][copy->type].type = copy->type; \ - if (copy->varkind == STACKVAR) { \ - if (copy->flags & SAVEDVAR) \ - rd->interfaces[(i)][copy->type].flags |= SAVEDVAR; \ - } \ - ) \ - (i)--; copy = copy->prev; \ - } \ -} - - -/* MARKREACHED marks the destination block 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) \ - do { \ - if ((b) <= (bptr)) \ - (b)->bitflags |= BBFLAG_REPLACEMENT; \ - if ((b)->flags < BBREACHED) { \ - COPYCURSTACK((c)); \ - (b)->flags = BBREACHED; \ - (b)->instack = (c); \ - (b)->indepth = stackdepth; \ - } else { \ - stackptr s = curstack; \ - stackptr t = (b)->instack; \ - if ((b)->indepth != stackdepth) { \ - *exceptionptr = new_verifyerror(m,"Stack depth mismatch"); \ - return NULL; \ - } \ - while (s) { \ - if (s->type != t->type) \ - TYPE_VERIFYERROR(t->type); \ - s = s->prev; \ - t = t->prev; \ - } \ - } \ - } while (0) - /* function prototypes ********************************************************/ bool stack_init(void); -methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd); - -void stack_print(codegendata *cd, stackptr s); -void show_icmd_method(methodinfo *m, codegendata *cd, registerdata *rd); -void show_icmd_block(methodinfo *m, codegendata *cd, basicblock *bptr); -void show_icmd(instruction *iptr, bool deadcode); +bool stack_analyse(jitdata *jd); -/* machine dependent return value handling function */ -void md_return_alloc(methodinfo *m, registerdata *rd, s4 return_type, - stackptr stackslot); +void stack_javalocals_store(instruction *iptr, s4 *javalocals); #endif /* _STACK_H */