* src/vm/jit/stack.c: Verify that subroutines are not merged.
authoredwin <none@none>
Sun, 8 Oct 2006 11:39:41 +0000 (11:39 +0000)
committeredwin <none@none>
Sun, 8 Oct 2006 11:39:41 +0000 (11:39 +0000)
(SBRSTART): New macro.
(COPY_VAL_AND_TYPE_VAR): New macro, propagate SBRSTART.
(COPY_VAL_AND_TYPE): Use COPY_VAL_AND_TYPE_VAR.
(stack_create_invars): Cleaned up, use COPY_VAL_AND_TYPE_VAR.
(stack_create_invars_from_outvars): Use COPY_VAL_AND_TYPE_VAR.
(stack_check_invars): Check against merging of subroutines. Wrapped
verifier checks in #if defined(ENABLE_VERIFIER).
(stack_check_invars_from_outvars): Likewise.
(stack_reanalyse_block): Wrapped verifier checks in
#if defined(ENABLE_VERIFIER).
(stack_analyse): Prepare a real variable for the handler stack.
Implemented re-analysing of blocks. Set SBRSTART for JSR.

* src/vm/jit/parse.c (parse): Reserve extra variables needed by
stack_analyse.

* src/vm/global.h (STACK_EXTRA_VARS): New macro.

src/vm/global.h
src/vm/jit/parse.c
src/vm/jit/stack.c

index 6ed28c87d222c033dee640c18b2c54dda6f5fa92..00f45b1b88c08fce83c82e350b4cbf9448f95bf9 100644 (file)
@@ -33,7 +33,7 @@
             Joseph Wenninger
             Christian Thalinger
 
-   $Id: global.h 5658 2006-10-04 10:10:01Z twisti $
+   $Id: global.h 5721 2006-10-08 11:39:41Z edwin $
 
 */
 
@@ -319,13 +319,16 @@ void compiler_unlock();
 /* The verifier needs additional variables in the variable array. Since these */
 /* must be reserved and set by parse.c and stack.c, we define these numbers   */
 /* here to avoid mysterious hard-coded constants.                             */
+/* stack.c needs an extra variable if the verifier is disabled.               */
 
 #if defined(ENABLE_VERIFIER)
 #    define VERIFIER_EXTRA_LOCALS  1
 #    define VERIFIER_EXTRA_VARS    1
+#    define STACK_EXTRA_VARS       0
 #else
 #    define VERIFIER_EXTRA_LOCALS  0
 #    define VERIFIER_EXTRA_VARS    0
+#    define STACK_EXTRA_VARS       1
 #endif
 
 #endif /* _GLOBAL_H */
index 85859ca2277a0ad9743abc6f386726e623569b67..67f28475a78152e031fb322e1aa4c07cfce4d2ac 100644 (file)
@@ -31,7 +31,7 @@
             Joseph Wenninger
             Christian Thalinger
 
-   $Id: parse.c 5718 2006-10-07 23:56:43Z edwin $
+   $Id: parse.c 5721 2006-10-08 11:39:41Z edwin $
 
 */
 
@@ -1592,6 +1592,11 @@ invoke_method:
 
                jd->vartop = nlocals;
 
+               /* reserve extra variables needed by stack analyse */
+
+               jd->varcount += STACK_EXTRA_VARS;
+               jd->vartop   += STACK_EXTRA_VARS;
+
                /* The verifier needs space for saving invars in some cases and */
                /* extra variables.                                             */
 
index 4b8e136cb23cde6be820296fe05755f7f4cf32ca..eb678d1ac73a20c7582e14b00f4ba3e9dee58392 100644 (file)
@@ -30,7 +30,7 @@
             Christian Thalinger
             Christian Ullrich
 
-   $Id: stack.c 5717 2006-10-07 23:02:53Z edwin $
+   $Id: stack.c 5721 2006-10-08 11:39:41Z edwin $
 
 */
 
 #define MIN(a,b)  (((a) < (b)) ? (a) : (b))
 
 
+/* For returnAddresses we use a field of the typeinfo to store from which  */
+/* subroutine the returnAddress will return, if used.                      */
+/* XXX It would be nicer to use typeinfo.typeclass, but the verifier seems */
+/* to need it initialised to NULL. This should be investigated.            */
+
+#if defined(ENABLE_VERIFIER)
+#define SBRSTART  typeinfo.elementclass.any
+#endif
+
+
 /* stackdata_t *****************************************************************
 
    This struct holds internal data during stack analysis.
@@ -309,11 +319,23 @@ struct stackdata_t {
 
 /* macro for propagating constant values ****************************/
 
-#define COPY_VAL_AND_TYPE(sd, sindex, dindex)                        \
+#if defined(ENABLE_VERIFIER)
+#define COPY_VAL_AND_TYPE_VAR(sv, dv)                                \
+    do {                                                             \
+        (dv)->type = (sv)->type;                                     \
+        (dv)->vv  = (sv)->vv;                                        \
+        (dv)->SBRSTART = (sv)->SBRSTART;                             \
+    } while (0)
+#else
+#define COPY_VAL_AND_TYPE_VAR(sv, dv)                                \
     do {                                                             \
-        (sd).var[(dindex)].type = (sd).var[(sindex)].type;           \
-        (sd).var[(dindex)].vv  = (sd).var[(sindex)].vv;              \
-    } while (0)                                                      \
+        (dv)->type = (sv)->type;                                     \
+        (dv)->vv  = (sv)->vv;                                        \
+    } while (0)
+#endif
+
+#define COPY_VAL_AND_TYPE(sd, sindex, dindex)                        \
+       COPY_VAL_AND_TYPE_VAR((sd).var + (sindex), (sd).var + (dindex))
 
 
 /* stack modelling macros *******************************************/
@@ -631,7 +653,8 @@ static void stack_create_invars(stackdata_t *sd, basicblock *b,
        stackptr sp;
        int i;
        int index;
-       varinfo *v;
+       varinfo *dv;
+       varinfo *sv;
 
        assert(sd->vartop + stackdepth <= sd->varcount);
 
@@ -644,22 +667,19 @@ static void stack_create_invars(stackdata_t *sd, basicblock *b,
        i = stackdepth;
        for (sp = curstack; i--; sp = sp->prev) {
                b->invars[i] = --index;
-               v = sd->var + index;
-               v->type = sp->type;
-               v->flags = INOUT;
-               v->vv = sd->var[sp->varnum].vv;
-#if defined(STACK_VERBOSE) && 0
-               printf("\tinvar[%d]: %d\n", i, sd->var[b->invars[i]]);
-#endif
+               dv = sd->var + index;
+               sv = sd->var + sp->varnum;
+               dv->flags = INOUT;
+               COPY_VAL_AND_TYPE_VAR(sv, dv);
        }
 
        /* copy the current state of the local variables */
        /* (one extra local is needed by the verifier)   */
 
-       v = DMNEW(varinfo, sd->localcount + VERIFIER_EXTRA_LOCALS);
-       b->inlocals = v;
+       dv = DMNEW(varinfo, sd->localcount + VERIFIER_EXTRA_LOCALS);
+       b->inlocals = dv;
        for (i=0; i<sd->localcount; ++i)
-               *v++ = sd->var[i];
+               *dv++ = sd->var[i];
 }
 
 
@@ -694,9 +714,8 @@ static void stack_create_invars_from_outvars(stackdata_t *sd, basicblock *b)
                for (i=0; i<n; ++i, ++dv) {
                        sv = sd->var + sd->bptr->outvars[i];
                        b->invars[i] = sd->vartop++;
-                       dv->type = sv->type;
                        dv->flags = INOUT;
-                       dv->vv = sv->vv;
+                       COPY_VAL_AND_TYPE_VAR(sv, dv);
                }
        }
 
@@ -734,6 +753,8 @@ static basicblock * stack_check_invars(stackdata_t *sd, basicblock *b,
        stackptr sp;
        basicblock *orig;
        bool separable;
+       varinfo *sv;
+       varinfo *dv;
 
 #if defined(STACK_VERBOSE)
        printf("stack_check_invars(L%03d)\n", b->nr);
@@ -750,10 +771,12 @@ static basicblock * stack_check_invars(stackdata_t *sd, basicblock *b,
 
        i = orig->indepth;
 
+#if defined(ENABLE_VERIFIER)
        if (i != stackdepth) {
                exceptions_throw_verifyerror(sd->m, "Stack depth mismatch");
                return NULL;
        }
+#endif
 
        do {
                separable = false;
@@ -765,14 +788,24 @@ static basicblock * stack_check_invars(stackdata_t *sd, basicblock *b,
 
                sp = curstack;
                for (i = orig->indepth; i--; sp = sp->prev) {
-                       if (sd->var[b->invars[i]].type != sp->type) {
-                               exceptions_throw_verifyerror_for_stack(sd->m, 
-                                               sd->var[b->invars[i]].type);
+                       dv = sd->var + b->invars[i];
+                       sv = sd->var + sp->varnum;
+
+#if defined(ENABLE_VERIFIER)
+                       if (dv->type != sp->type) {
+                               exceptions_throw_verifyerror_for_stack(sd->m, dv->type);
                                return NULL;
                        }
+#endif
 
                        if (sp->type == TYPE_RET) {
-                               if (sd->var[b->invars[i]].vv.retaddr != sd->var[sp->varnum].vv.retaddr) {
+#if defined(ENABLE_VERIFIER)
+                               if (dv->SBRSTART != sv->SBRSTART) {
+                                       exceptions_throw_verifyerror(sd->m, "Mismatched stack types");
+                                       return NULL;
+                               }
+#endif
+                               if (dv->vv.retaddr != sv->vv.retaddr) {
                                        separable = true;
                                        /* don't break! have to check the remaining stackslots */
                                }
@@ -781,8 +814,15 @@ static basicblock * stack_check_invars(stackdata_t *sd, basicblock *b,
 
                if (b->inlocals) {
                        for (i=0; i<sd->localcount; ++i) {
-                               if (sd->var[i].type == TYPE_RET && b->inlocals[i].type == TYPE_RET) {
-                                       if (sd->var[i].vv.retaddr != b->inlocals[i].vv.retaddr) {
+                               dv = b->inlocals + i;
+                               sv = sd->var + i;
+                               if (sv->type == TYPE_RET && dv->type == TYPE_RET) {
+                                       if (
+#if defined(ENABLE_VERIFIER)
+                                                       (sv->SBRSTART == dv->SBRSTART) &&
+#endif
+                                                       (sv->vv.retaddr != dv->vv.retaddr)) 
+                                       {
                                                separable = true;
                                                break;
                                        }
@@ -793,6 +833,22 @@ static basicblock * stack_check_invars(stackdata_t *sd, basicblock *b,
                if (!separable) {
                        /* XXX mark mixed type variables void */
                        /* XXX cascading collapse? */
+#if defined(ENABLE_VERIFIER)
+                       if (b->inlocals) {
+                               for (i=0; i<sd->localcount; ++i) {
+                                       dv = b->inlocals + i;
+                                       sv = sd->var + i;
+                                       if ((sv->type == TYPE_RET && dv->type == TYPE_RET)
+                                               && (sv->SBRSTART != dv->SBRSTART))
+                                       {
+                                               dv->type = TYPE_VOID;
+                                               b->flags = BBTYPECHECK_REACHED;
+                                               sd->repeat = true; /* This is very rare, so just repeat */
+                                       }
+                               }
+                       }
+#endif
+
 #if defined(STACK_VERBOSE)
                        printf("------> using L%03d\n", b->nr);
 #endif
@@ -848,10 +904,12 @@ static basicblock * stack_check_invars_from_outvars(stackdata_t *sd, basicblock
        i = orig->indepth;
        n = sd->bptr->outdepth;
 
+#if defined(ENABLE_VERIFIER)
        if (i != n) {
                exceptions_throw_verifyerror(sd->m, "Stack depth mismatch");
                return NULL;
        }
+#endif
 
        do {
                separable = false;
@@ -866,12 +924,21 @@ static basicblock * stack_check_invars_from_outvars(stackdata_t *sd, basicblock
 
                        for (i=0; i<n; ++i, ++dv) {
                                sv = sd->var + sd->bptr->outvars[i];
+
+#if defined(ENABLE_VERIFIER)
                                if (sv->type != dv->type) {
                                        exceptions_throw_verifyerror_for_stack(sd->m, dv->type);
                                        return NULL;
                                }
+#endif
 
                                if (dv->type == TYPE_RET) {
+#if defined(ENABLE_VERIFIER)
+                                       if (sv->SBRSTART != dv->SBRSTART) {
+                                               exceptions_throw_verifyerror(sd->m, "Mismatched stack types");
+                                               return NULL;
+                                       }
+#endif
                                        if (sv->vv.retaddr != dv->vv.retaddr) {
                                                separable = true;
                                                /* don't break! have to check the remaining stackslots */
@@ -882,8 +949,15 @@ static basicblock * stack_check_invars_from_outvars(stackdata_t *sd, basicblock
 
                if (b->inlocals) {
                        for (i=0; i<sd->localcount; ++i) {
-                               if (sd->var[i].type == TYPE_RET && b->inlocals[i].type == TYPE_RET) {
-                                       if (sd->var[i].vv.retaddr != b->inlocals[i].vv.retaddr) {
+                               dv = b->inlocals + i;
+                               sv = sd->var + i;
+                               if (
+#if defined(ENABLE_VERIFIER)
+                                               (sv->SBRSTART == dv->SBRSTART) &&
+#endif
+                                               (sv->type == TYPE_RET && dv->type == TYPE_RET))
+                               {
+                                       if (sv->vv.retaddr != dv->vv.retaddr) {
                                                separable = true;
                                                break;
                                        }
@@ -894,6 +968,22 @@ static basicblock * stack_check_invars_from_outvars(stackdata_t *sd, basicblock
                if (!separable) {
                        /* XXX mark mixed type variables void */
                        /* XXX cascading collapse? */
+#if defined(ENABLE_VERIFIER)
+                       if (b->inlocals) {
+                               for (i=0; i<sd->localcount; ++i) {
+                                       dv = b->inlocals + i;
+                                       sv = sd->var + i;
+                                       if ((sv->type == TYPE_RET && dv->type == TYPE_RET)
+                                                       && (sv->SBRSTART != dv->SBRSTART))
+                                       {
+                                               dv->type = TYPE_VOID;
+                                               b->flags = BBTYPECHECK_REACHED;
+                                               sd->repeat = true; /* This is very rare, so just repeat */
+                                       }
+                               }
+                       }
+#endif
+
 #if defined(STACK_VERBOSE)
                        printf("------> using L%03d\n", b->nr);
 #endif
@@ -1303,10 +1393,12 @@ bool stack_reanalyse_block(stackdata_t *sd)
                        case ICMD_RET:
                                j = iptr->s1.varindex;
 
+#if defined(ENABLE_VERIFIER)
                                if (sd->var[j].type != TYPE_RET) {
                                        exceptions_throw_verifyerror(sd->m, "RET with non-returnAddress value");
                                        return false;
                                }
+#endif
 
                                iptr->dst.block = stack_mark_reached_from_outvars(sd, sd->var[j].vv.retaddr);
                                superblockend = true;
@@ -1896,9 +1988,14 @@ bool stack_analyse(jitdata *jd)
        sd.localcount = jd->localcount;
        sd.var = jd->var;
        sd.handlers = DMNEW(exceptiontable *, cd->exceptiontablelength + 1);
+
+       /* prepare the variable for exception handler stacks               */
+       /* (has been reserved by STACK_EXTRA_VARS, or VERIFIER_EXTRA_VARS) */
+
        sd.exstack.type = TYPE_ADR;
        sd.exstack.prev = NULL;
-       sd.exstack.varnum = 0; /* XXX do we need a real variable index here? */
+       sd.exstack.varnum = sd.localcount;
+       sd.var[sd.exstack.varnum].type = TYPE_ADR;
 
 #if defined(ENABLE_LSRA)
        m->maxlifetimes = 0;
@@ -1968,6 +2065,14 @@ bool stack_analyse(jitdata *jd)
                                continue;
                        }
 
+                       if (sd.bptr->flags == BBTYPECHECK_REACHED) {
+                               /* re-analyse a block because its input changed */
+                               if (!stack_reanalyse_block(&sd))
+                                       return false;
+                               superblockend = true; /* XXX */
+                               continue;
+                       }
+
                        if (superblockend && (sd.bptr->flags < BBREACHED)) {
                                /* This block has not been reached so far, and we      */
                                /* don't fall into it, so we'll have to iterate again. */
@@ -1988,6 +2093,7 @@ bool stack_analyse(jitdata *jd)
                                /* analysed, yet. Analyse it on the next iteration.    */
 
                                sd.repeat = true;
+                               /* XXX superblockend? */
                                continue;
                        }
 
@@ -2132,10 +2238,12 @@ icmd_NOP:
                                                j = iptr->s1.varindex = 
                                                        jd->local_map[iptr->s1.varindex * 5 + TYPE_ADR];
 
+#if defined(ENABLE_VERIFIER)
                                                if (sd.var[j].type != TYPE_RET) {
                                                        exceptions_throw_verifyerror(m, "RET with non-returnAddress value");
                                                        return false;
                                                }
+#endif
                
                                                CLR_SX;
 
@@ -2929,10 +3037,12 @@ normal_ACONST:
                                                j = iptr->s1.varindex = 
                                                        jd->local_map[iptr->s1.varindex * 5 + i];
 
+#if defined(ENABLE_VERIFIER)
                                                if (sd.var[j].type == TYPE_RET) {
                                                        exceptions_throw_verifyerror(m, "forbidden load of returnAddress");
                                                        return false;
                                                }
+#endif
                
 #if defined(ENABLE_SSA)
                                                if (ls != NULL) {
@@ -4101,12 +4211,15 @@ normal_DCMPG:
                                        case ICMD_JSR:
                                                OP0_1(TYPE_RET);
 
-                                               assert(sd.bptr->next);  /* XXX exception */
-                                               sd.var[curstack->varnum].vv.retaddr = sd.bptr->next;
-
                                                tbptr = BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex);
                                                tbptr->type = BBTYPE_SBR;
 
+                                               assert(sd.bptr->next);  /* XXX exception */
+                                               sd.var[curstack->varnum].vv.retaddr = sd.bptr->next;
+#if defined(ENABLE_VERIFIER)
+                                               sd.var[curstack->varnum].SBRSTART = (void*) tbptr;
+#endif
+
                                                tbptr = stack_mark_reached(&sd, tbptr, curstack, stackdepth);
                                                if (!tbptr)
                                                        return false;