X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fstack.h;h=2af166477e2e98c6358f6bdc976a8c5d869a1f3d;hb=c4211068c30121af531e8ce20f0bf6604d8c0fda;hp=a49b2e40ab4090749c9fc6c725309011c2689552;hpb=16b541414ff612aa5c71fb2cd91f1f1d172da7d0;p=cacao.git diff --git a/src/vm/jit/stack.h b/src/vm/jit/stack.h index a49b2e40a..2af166477 100644 --- a/src/vm/jit/stack.h +++ b/src/vm/jit/stack.h @@ -1,9 +1,9 @@ /* vm/jit/stack.h - stack analysis header - 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 + Copyright (C) 1996-2005, 2006 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. @@ -19,14 +19,15 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. - Contact: cacao@complang.tuwien.ac.at + Contact: cacao@cacaojvm.org Authors: Christian Thalinger - $Id: stack.h 3007 2005-07-12 20:58:01Z twisti $ + Changes: Christian Ullrich + Edwin Steiner */ @@ -34,55 +35,35 @@ #ifndef _STACK_H #define _STACK_H -#include "vm/global.h" +#include "config.h" + +#include "vm/types.h" + #include "vm/exceptions.h" +#include "vm/global.h" +#include "vm/jit/jit.h" #include "vm/jit/reg.h" -/**********************************************************************/ -/* 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 +/* macros used internally by analyse_stack ************************************/ /*--------------------------------------------------*/ -/* SIGNALING ERRORS */ +/* BASIC TYPE CHECKING */ /*--------------------------------------------------*/ -#define TYPE_VERIFYERROR(t) \ - do { \ - char *type; \ - switch ((t)) { \ - case TYPE_INT: \ - type = "integer"; \ - break; \ - case TYPE_LNG: \ - type = "long"; \ - break; \ - case TYPE_FLT: \ - type = "float"; \ - break; \ - case TYPE_DBL: \ - type = "double"; \ - break; \ - case TYPE_ADR: \ - type = "object/array"; \ - break; \ - } \ - *exceptionptr = new_verifyerror(m, \ - "Expecting to find %s on stack", \ - type); \ - 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 */ @@ -90,19 +71,15 @@ /* underflow checks */ -#define REQUIRE(num) \ - do { \ - if (stackdepth < (num)) { \ - *exceptionptr = \ - new_verifyerror(m, "Unable to pop operand off an empty stack"); \ - return NULL; \ - } \ - } while(0) - -#define REQUIRE_1 REQUIRE(1) -#define REQUIRE_2 REQUIRE(2) -#define REQUIRE_3 REQUIRE(3) -#define REQUIRE_4 REQUIRE(4) +#if defined(ENABLE_VERIFIER) +#define REQUIRE(num) \ + do { \ + if (stackdepth < (num)) \ + goto throw_stack_underflow; \ + } while (0) +#else /* !ENABLE_VERIFIER */ +#define REQUIRE(num) +#endif /* ENABLE_VERIFIER */ /* overflow check */ @@ -111,296 +88,50 @@ * 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) { \ - *exceptionptr = new_verifyerror(m, "Stack size too large"); \ - return NULL; \ - } \ - } \ - } while(0) - +/* 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->opc != ICMD_ACONST) || INSTRUCTION_MUST_CHECK(iptr))\ + goto throw_stack_overflow; \ + } while(0) +#else /* !ENABLE_VERIFIER */ +#define CHECKOVERFLOW +#endif /* ENABLE_VERIFIER */ /*--------------------------------------------------*/ /* 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; }*/ - -#ifdef LSRA -# define NEWSTACK(s,v,n) {NEWSTACK_(s,v,n); m->maxlifetimes++;} -#else -# define NEWSTACK(s,v,n) NEWSTACK_(s,v,n) -#endif +/* 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) - -#define COPY(s,d) \ - do { \ - (d)->flags = 0; \ - (d)->type = (s)->type; \ - (d)->varkind = (s)->varkind; \ - (d)->varnum = (s)->varnum; \ - } 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) {REQUIRE_1;POP(s);SETDST;stackdepth--;} -#define OP1_0ANY {REQUIRE_1;POPANY;SETDST;stackdepth--;} - -#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) {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) \ - do { \ - REQUIRE((i)); \ - stackdepth -= (i); \ - while(--(i) >= 0) { \ - POPANY; \ - } \ - SETDST; \ - } while (0) - -#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);\ - } \ - 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) { \ - 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)->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, cd, rd); \ - log_text("Stack depth mismatch"); \ - assert(0); \ - } \ - 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 icmd_print_stack(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 */ @@ -416,4 +147,5 @@ void md_return_alloc(methodinfo *m, registerdata *rd, s4 return_type, * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */