* src/vm/jit/stack.h (COPY): Prevent setting varkind to STACKVAR for stackslots copie...
[cacao.git] / src / vm / jit / stack.h
index 64a5c8881c531cb3fda294e0b526ead59b2b0ecb..712b3678a6e5b10ee6b608b3df6523189f9c7891 100644 (file)
@@ -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.
 
 
    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);
@@ -403,4 +507,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:
  */