X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Fstack.h;h=2af166477e2e98c6358f6bdc976a8c5d869a1f3d;hb=c4211068c30121af531e8ce20f0bf6604d8c0fda;hp=a382de3c2475313685fdadf284b7641893b1b180;hpb=fd47d5e80136db91d3b2374c6236dd9e4c667740;p=cacao.git diff --git a/src/vm/jit/stack.h b/src/vm/jit/stack.h index a382de3c2..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 2181 2005-04-01 16:53:33Z edwin $ + Changes: Christian Ullrich + Edwin Steiner */ @@ -34,31 +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 TYPEPANIC {panic("Stack type mismatch");} +/* 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 */ @@ -66,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 */ @@ -87,220 +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) {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 */ -/*--------------------------------------------------*/ +#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) -/* 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). - */ +/* 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 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 NEWSTACKn(s,n) NEWSTACK(s,UNDEFVAR,n) +#define NEWSTACK0(s) NEWSTACK(s,UNDEFVAR,0) -#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); \ - panic("Stack depth mismatch"); \ - } \ - while (s) { \ - if (s->type != t->type) \ - TYPEPANIC; \ - s = s->prev; \ - t = t->prev; \ - } \ - } \ - } while (0) +/* function prototypes ********************************************************/ -/* function prototypes */ +bool stack_init(void); -methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd); +bool stack_analyse(jitdata *jd); -void icmd_print_stack(codegendata *cd, stackptr s); -char *icmd_builtin_name(functionptr bptr); -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); +void stack_javalocals_store(instruction *iptr, s4 *javalocals); #endif /* _STACK_H */ @@ -316,4 +147,5 @@ void show_icmd(instruction *iptr, bool deadcode); * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */