Removed compiler_addinitclass
[cacao.git] / jit / stack.c
index 90dbc45c06a7f4a283c8e7604d2b422b918e76d1..4263e470f5be1eacf272fbf8b2a61468daeb3b28 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes: Edwin Steiner
 
-   $Id: stack.c 797 2003-12-16 22:29:21Z edwin $
+   $Id: stack.c 814 2003-12-31 01:41:15Z edwin $
 
 */
 
@@ -69,8 +69,8 @@ extern int dseglen;
 /*--------------------------------------------------*/
 
 #define TYPEPANIC  {show_icmd_method();panic("Stack type mismatch");}
-#define UNDERFLOW  {show_icmd_method();panic("Stack underflow");}
-#define OVERFLOW   {show_icmd_method();panic("Stack overflow");}
+#define UNDERFLOW  {show_icmd_method();panic("Operand stack underflow");}
+#define OVERFLOW   {show_icmd_method();panic("Operand stack overflow");}
 
 /*--------------------------------------------------*/
 /* STACK UNDERFLOW/OVERFLOW CHECKS                  */
@@ -97,18 +97,24 @@ extern int dseglen;
        } while(0)
 
 /*--------------------------------------------------*/
-/* STACK MANIPULATION                               */
+/* ALLOCATING STACK SLOTS                           */
 /*--------------------------------------------------*/
 
-/* resetting to an empty operand stack */
-#define STACKRESET {curstack=0;stackdepth=0;}
-
 #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;}
 
@@ -120,13 +126,18 @@ extern int dseglen;
                      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++;}
@@ -176,7 +187,10 @@ extern int dseglen;
                     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.
@@ -209,6 +223,9 @@ extern int dseglen;
                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;\
@@ -259,6 +276,31 @@ extern int dseglen;
 }
 
 
+/**********************************************************************/
+/* analyse_stack                                                      */
+/**********************************************************************/
+
+/* analyse_stack uses the intermediate code created by parse.c to
+ * build a model of the JVM operand stack for the current method.
+ *
+ * The following checks are performed:
+ *   - check for operand stack underflow (before each instruction)
+ *   - check for operand stack overflow (after[1] each instruction)
+ *   - check for matching stack depth at merging points
+ *   - check for matching basic types[2] at merging points
+ *   - check basic types for instruction input (except for BUILTIN*
+ *         opcodes and MULTIANEWARRAY)
+ *
+ * [1]) XXX Checking this after the instruction should be ok. parse.c
+ * counts the number of required stack slots in such a way that it is
+ * only vital that we don't exceed `maxstack` at basic block
+ * boundaries.
+ *
+ * [2]) 'basic types' means the distinction between INT, LONG, FLOAT,
+ * DOUBLE and ADDRESS types. Subtypes of INT and different ADDRESS
+ * types are not discerned.
+ */
+
 void analyse_stack()
 {
        int b_count;
@@ -1030,6 +1072,13 @@ void analyse_stack()
                                                /* pop 1 push 0 */
 
                                        case ICMD_POP:
+#ifdef TYPECHECK_STACK_COMPCAT
+                                               if (opt_verify) {
+                                                       REQUIRE_1;
+                                                       if (IS_2_WORD_TYPE(curstack->type))
+                                                               panic("Illegal instruction: POP on category 2 type");
+                                               }
+#endif
                                                OP1_0ANY;
                                                break;
 
@@ -1258,6 +1307,14 @@ void analyse_stack()
                                        case ICMD_POP2:
                                                REQUIRE_1;
                                                if (! IS_2_WORD_TYPE(curstack->type)) {
+                                                       /* ..., cat1 */
+#ifdef TYPECHECK_STACK_COMPCAT
+                                                       if (opt_verify) {
+                                                               REQUIRE_2;
+                                                               if (IS_2_WORD_TYPE(curstack->prev->type))
+                                                                       panic("Illegal instruction: POP2 on cat2, cat1 types");
+                                                       }
+#endif
                                                        OP1_0ANY;                /* second pop */
                                                }
                                                else
@@ -1268,6 +1325,13 @@ void analyse_stack()
                                                /* pop 0 push 1 dup */
                                                
                                        case ICMD_DUP:
+#ifdef TYPECHECK_STACK_COMPCAT
+                                               if (opt_verify) {
+                                                       REQUIRE_1;
+                                                       if (IS_2_WORD_TYPE(curstack->type))
+                                                               panic("Illegal instruction: DUP on category 2 type");
+                                               }
+#endif
                                                COUNT(count_dup_instruction);
                                                DUP;
                                                break;
@@ -1275,11 +1339,19 @@ void analyse_stack()
                                        case ICMD_DUP2:
                                                REQUIRE_1;
                                                if (IS_2_WORD_TYPE(curstack->type)) {
+                                                       /* ..., cat2 */
                                                        iptr->opc = ICMD_DUP;
                                                        DUP;
                                                }
                                                else {
                                                        REQUIRE_2;
+                                                       /* ..., ????, cat1 */
+#ifdef TYPECHECK_STACK_COMPCAT
+                                                       if (opt_verify) {
+                                                               if (IS_2_WORD_TYPE(curstack->prev->type))
+                                                                       panic("Illegal instruction: DUP2 on cat2, cat1 types");
+                                                       }
+#endif
                                                        copy = curstack;
                                                        NEWSTACK(copy->prev->type, copy->prev->varkind,
                                                                         copy->prev->varnum);
@@ -1293,16 +1365,40 @@ void analyse_stack()
                                                /* pop 2 push 3 dup */
                                                
                                        case ICMD_DUP_X1:
+#ifdef TYPECHECK_STACK_COMPCAT
+                                               if (opt_verify) {
+                                                       REQUIRE_2;
+                                                       if (IS_2_WORD_TYPE(curstack->type) ||
+                                                               IS_2_WORD_TYPE(curstack->prev->type))
+                                                               panic("Illegal instruction: DUP_X1 on cat 2 type");
+                                               }
+#endif
                                                DUP_X1;
                                                break;
 
                                        case ICMD_DUP2_X1:
                                                REQUIRE_2;
                                                if (IS_2_WORD_TYPE(curstack->type)) {
+                                                       /* ..., ????, cat2 */
+#ifdef TYPECHECK_STACK_COMPCAT
+                                                       if (opt_verify) {
+                                                               if (IS_2_WORD_TYPE(curstack->prev->type))
+                                                                       panic("Illegal instruction: DUP2_X1 on cat2, cat2 types");
+                                                       }
+#endif
                                                        iptr->opc = ICMD_DUP_X1;
                                                        DUP_X1;
                                                }
                                                else {
+                                                       /* ..., ????, cat1 */
+#ifdef TYPECHECK_STACK_COMPCAT
+                                                       if (opt_verify) {
+                                                               REQUIRE_3;
+                                                               if (IS_2_WORD_TYPE(curstack->prev->type)
+                                                                       || IS_2_WORD_TYPE(curstack->prev->prev->type))
+                                                                       panic("Illegal instruction: DUP2_X1 on invalid types");
+                                                       }
+#endif
                                                        DUP2_X1;
                                                }
                                                break;
@@ -1312,10 +1408,26 @@ void analyse_stack()
                                        case ICMD_DUP_X2:
                                                REQUIRE_2;
                                                if (IS_2_WORD_TYPE(curstack->prev->type)) {
+                                                       /* ..., cat2, ???? */
+#ifdef TYPECHECK_STACK_COMPCAT
+                                                       if (opt_verify) {
+                                                               if (IS_2_WORD_TYPE(curstack->type))
+                                                                       panic("Illegal instruction: DUP_X2 on cat2, cat2 types");
+                                                       }
+#endif
                                                        iptr->opc = ICMD_DUP_X1;
                                                        DUP_X1;
                                                }
                                                else {
+                                                       /* ..., cat1, ???? */
+#ifdef TYPECHECK_STACK_COMPCAT
+                                                       if (opt_verify) {
+                                                               REQUIRE_3;
+                                                               if (IS_2_WORD_TYPE(curstack->type)
+                                                                       || IS_2_WORD_TYPE(curstack->prev->prev->type))
+                                                                       panic("Illegal instruction: DUP_X2 on invalid types");
+                                                       }
+#endif
                                                        DUP_X2;
                                                }
                                                break;
@@ -1323,22 +1435,49 @@ void analyse_stack()
                                        case ICMD_DUP2_X2:
                                                REQUIRE_2;
                                                if (IS_2_WORD_TYPE(curstack->type)) {
+                                                       /* ..., ????, cat2 */
                                                        if (IS_2_WORD_TYPE(curstack->prev->type)) {
+                                                               /* ..., cat2, cat2 */
                                                                iptr->opc = ICMD_DUP_X1;
                                                                DUP_X1;
                                                        }
                                                        else {
+                                                               /* ..., cat1, cat2 */
+#ifdef TYPECHECK_STACK_COMPCAT
+                                                               if (opt_verify) {
+                                                                       REQUIRE_3;
+                                                                       if (IS_2_WORD_TYPE(curstack->prev->prev->type))
+                                                                               panic("Illegal instruction: DUP2_X2 on invalid types");
+                                                               }
+#endif
                                                                iptr->opc = ICMD_DUP_X2;
                                                                DUP_X2;
                                                        }
                                                }
                                                else {
                                                        REQUIRE_3;
+                                                       /* ..., ????, ????, cat1 */
                                                        if (IS_2_WORD_TYPE(curstack->prev->prev->type)) {
+                                                               /* ..., cat2, ????, cat1 */
+#ifdef TYPECHECK_STACK_COMPCAT
+                                                               if (opt_verify) {
+                                                                       if (IS_2_WORD_TYPE(curstack->prev->type))
+                                                                               panic("Illegal instruction: DUP2_X2 on invalid types");
+                                                               }
+#endif
                                                                iptr->opc = ICMD_DUP2_X1;
                                                                DUP2_X1;
                                                        }
                                                        else {
+                                                               /* ..., cat1, ????, cat1 */
+#ifdef TYPECHECK_STACK_COMPCAT
+                                                               if (opt_verify) {
+                                                                       REQUIRE_4;
+                                                                       if (IS_2_WORD_TYPE(curstack->prev->type)
+                                                                               || IS_2_WORD_TYPE(curstack->prev->prev->prev->type))
+                                                                               panic("Illegal instruction: DUP2_X2 on invalid types");
+                                                               }
+#endif
                                                                DUP2_X2;
                                                        }
                                                }
@@ -1347,6 +1486,14 @@ void analyse_stack()
                                                /* pop 2 push 2 swap */
                                                
                                        case ICMD_SWAP:
+#ifdef TYPECHECK_STACK_COMPCAT
+                                               if (opt_verify) {
+                                                       REQUIRE_2;
+                                                       if (IS_2_WORD_TYPE(curstack->type)
+                                                               || IS_2_WORD_TYPE(curstack->prev->type))
+                                                               panic("Illegal instruction: SWAP on category 2 type");
+                                               }
+#endif
                                                SWAP;
                                                break;
 
@@ -1768,6 +1915,7 @@ void analyse_stack()
                                                        arguments_num = i + intreg_argnum;
                                                copy = curstack;
                                                while (--i >= 0) {
+                                                       /* XXX check INT type here? Currently typecheck does this. */
                                                        if (! (copy->flags & SAVEDVAR)) {
                                                                copy->varkind = ARGVAR;
                                                                copy->varnum = i + intreg_argnum;
@@ -1903,6 +2051,10 @@ void analyse_stack()
 }
 
 
+/**********************************************************************/
+/* DEBUGGING HELPERS                                                  */
+/**********************************************************************/
+
 void icmd_print_stack(stackptr s)
 {
        int i, j;