/* 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.
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 2870 2005-06-29 12:39:31Z christian $
+ Changes: Christian Ullrich
+
+ $Id: stack.h 4524 2006-02-16 19:39:36Z christian $
*/
#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 */
-/**********************************************************************/
+/* macros used internally by analyse_stack ************************************/
-#ifdef STATISTICS
-#define COUNT(cnt) cnt++
+#if defined(ENABLE_LSRA)
+# define INC_LIFETIMES(a) { m->maxlifetimes += (a); }
#else
-#define COUNT(cnt)
+# define INC_LIFETIMES(a)
#endif
-
+
/* convenient abbreviations */
#define CURKIND curstack->varkind
#define CURTYPE curstack->type
+
/*--------------------------------------------------*/
/* SIGNALING ERRORS */
/*--------------------------------------------------*/
#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); \
+ exceptions_throw_verifyerror_for_stack(m,t); \
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++;}
- /* 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
+#define NEWSTACK_(s,v,n) \
+ do { \
+ new->prev = curstack; \
+ new->type = (s); \
+ new->flags = 0; \
+ new->varkind = (v); \
+ new->varnum = (n); \
+ curstack = new; \
+ 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); }
#define NEWSTACKn(s,n) NEWSTACK(s,UNDEFVAR,n)
#define NEWSTACK0(s) NEWSTACK(s,UNDEFVAR,0)
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; \
- (d)->varkind = (s)->varkind; \
- (d)->varnum = (s)->varnum; \
+ if ( (s)->varkind != STACKVAR) { \
+ (d)->varkind = (s)->varkind; \
+ (d)->varnum = (s)->varnum; \
+ } else { \
+ (d)->varkind = TEMPVAR; \
+ (d)->varnum = 0; \
+ } \
} while (0)
#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 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); \
+ NEWSTACKn(s, stackdepth); \
SETDST; \
stackdepth++; \
} while (0)
#define OP1_1(s,d) \
do { \
REQUIRE_1; \
- POP((s)); \
- NEWSTACKn((d),stackdepth - 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 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 { \
SETDST; \
} while (0)
-#define DUP {REQUIRE_1;NEWSTACK(CURTYPE,CURKIND,curstack->varnum);SETDST; \
- stackdepth++;}
+/* 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++;}
+ 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;}
+ 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++;}
+ 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;}
+ curstack=new+5;new+=6;SETDST;stackdepth+=2; INC_LIFETIMES(6);}
/*--------------------------------------------------*/
* 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); \
copy->varkind = STACKVAR; \
copy->varnum = (i);\
} \
- rd->interfaces[(i)][copy->type].type = copy->type; \
- rd->interfaces[(i)][copy->type].flags |= copy->flags; \
+ 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) { \
- rd->interfaces[(i)][copy->type].type = copy->type; \
- if (copy->varkind == STACKVAR) { \
- if (copy->flags & SAVEDVAR) \
- rd->interfaces[(i)][copy->type].flags |= SAVEDVAR; \
- } \
+ 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; \
} \
}
#define MARKREACHED(b,c) \
do { \
- if ((b)->flags < 0) { \
+ if ((b)->flags < BBREACHED) { \
COPYCURSTACK((c)); \
- (b)->flags = 0; \
+ (b)->flags = BBREACHED; \
(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); \
+ *exceptionptr = new_verifyerror(m,"Stack depth mismatch"); \
+ return NULL; \
} \
while (s) { \
if (s->type != t->type) \
/* function prototypes ********************************************************/
+bool stack_init(void);
+
methodinfo *analyse_stack(methodinfo *m, codegendata *cd, registerdata *rd);
void icmd_print_stack(codegendata *cd, stackptr s);
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/