Changeset: 521e02128f87 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=521e02128f87
Modified Files:
        monetdb5/mal/mal_interpreter.mx
Branch: Aug2011
Log Message:

Stack frame handling
Documentation has been fixed, we don't use the first part of the
stack frame for passing arguments aroud. They can recide anywhere
on the stacks.
In MAL function calls, the wrong stack frame was passed, which
in case of strings and BATs would cause segfaults. It may screw
up the stack frame from the caller in all other situations.


diffs (173 lines):

diff --git a/monetdb5/mal/mal_interpreter.mx b/monetdb5/mal/mal_interpreter.mx
--- a/monetdb5/mal/mal_interpreter.mx
+++ b/monetdb5/mal/mal_interpreter.mx
@@ -184,7 +184,6 @@
 Copy the constant values onto the stack frame
 Also we cannot overwrite values on the stack as this maybe part of a
 sequence of factory calls.
-BEWARE WE ASSUME THAT FIRST VARIABLES ON THE STACK ALIGN WITH THE SIGNATURE.
 @= initStack
        for (i = @1; i < mb->vtop; i++) {
                lhs = &stk->stk[i];
@@ -224,7 +223,7 @@
        stk->stksize = size;
        stk->blk = mb;
 
-       @:initStack(1)@
+       @:initStack(0)@
        return stk;
 }
 
@@ -248,7 +247,6 @@
 the minimum amount of stack space needed, some slack resources
 are included to permit code optimizers to add a few variables at run time,
 (2) copying the arguments into the new stack frame.
-Notice that arguments are always the first entries on the stack.
 
 The env stackframe is set when a MAL function is called recursively.
 Alternatively, there is no caller but a stk to be re-used for interpretation.
@@ -264,14 +262,15 @@
                if (mb->vtop > stk->stksize)
                        showScriptException(mb, 0, MAL, "stack too small\n");
                pci = pcicaller;
+               @:initStack(env->stkbot)@
        } else {
-               newStack(stk, mb->vsize);
-               stk->stktop = mb->vtop;
-               stk->stksize = mb->vsize;
+               stk= prepareMALstack(mb, mb->vsize);
+               if (stk == 0)
+                       throw(MAL,"mal.interpreter",MAL_STACK_FAIL);
                stk->blk = mb;
                stk->cmd = cntxt->itrace;    /* set debug mode */
+               /*safeguardStack*/
                if (env) {
-                       /*safeguardStack*/
                        stk->stkdepth = stk->stksize + env->stkdepth;
                        stk->calldepth = env->calldepth + 1;
                        if (stk->calldepth > 256)
@@ -280,22 +279,29 @@
                                /* we are running low on stack space */
                                throw(MAL, "mal.interpreter", MAL_STACK_FAIL);
                }
+@-
+An optimization is to copy all constant variables used in functions immediately
+onto the value stack. Then we do not have to check for their location
+later on any more. At some point, the effect is optimal, if at least several
+constants are referenced in a function (a gain on tst400a of 20% has been
+observed due the small size of the function).
+@c
        }
 
        if (env && mbcaller) {
                InstrPtr pp;
                int k;
 @-
-Beware, a function signature f(a1..an):(b1..bn) is parsed in such a way that
-the symbol table and stackframe contains the sequence
-f,a1..an,b1..bn. This slightly complicates the implementation
-of the return statement.
+Moreover, we have to copy the result types to the stack for later
+use. The stack value has been cleared to avoid misinterpretation of left-over
+information. Since a stack frame may contain values of a previous call,
+we should first remove garbage.
 @c
                pci = pcicaller;
                pp = getInstrPtr(mb, 0);
                /* set return types */
                for (i = 0; i < pci->retc; i++) {
-                       lhs = &stk->stk[i];
+                       lhs = &stk->stk[pp->argv[i]];
                        lhs->vtype = getVarGDKType(mb, i);
                }
                for (k = pp->retc; i < pci->argc; i++, k++) {
@@ -310,25 +316,6 @@
                }
                stk->up = env;
        }
-@-
-An optimization is to copy all constant variables used in functions immediately
-onto the value stack. Then we do not have to check for their location
-later on any more. At some point, the effect is optimal, if at least several
-constants are referenced in a function (a gain on tst400a of 20% has been
-observed due the small size of the function).
-
-Moreover, we have to copy the result types to the stack for later
-use. The stack value is cleared to avoid misinterpretation of left-over
-information. Since a stack frame may contain values of a previous call,
-we should first remove garbage.
-@c
-       if (env && mbcaller) {
-               @:initStack(pci->argc)@
-       } else if (env && env->stkbot) {
-               @:initStack(env->stkbot)@
-       } else {
-               @:initStack(mbcaller ? pci->argc:1)@
-       }
 
        if (stk->cmd && env && stk->cmd != 'f')
                stk->cmd = env->cmd;
@@ -388,7 +375,7 @@
        MalStkPtr stk = NULL;
        str ret = MAL_SUCCEED;
        int i;
-       ValPtr lhs, rhs;
+       ValPtr lhs;
        InstrPtr pci = getInstrPtr(mb, 0);
        @:performanceVariables@
 
@@ -405,13 +392,8 @@
 all arguments and return values.
 @c
                if (*env == NULL) {
-                       stk = newGlobalStack(mb->vsize);
-                       memset((char *)stk, 0, stackSize(mb->vtop));
-                       stk->stktop = mb->vtop;
-                       stk->stksize = mb->vsize;
-                       stk->blk = mb;
+                       stk = prepareMALstack(mb, mb->vsize);
                        stk->up = 0;
-                       @:initStack(pci->argc)@
                        *env = stk;
                } else stk = *env;
                assert(stk);
@@ -2042,10 +2024,37 @@
 
 @-
 @= functioncall
-{
+{      MalStkPtr nstk;
+       InstrPtr q;
+       int ii, arg;
+
        stk->pcup = stkpc;
        @:safeTarget(@1)@
-       ret = runMAL(cntxt, pci->blk, 1, mb, stk, pci);
+       nstk = prepareMALstack(pci->blk, pci->blk->vsize);
+       if (nstk == 0)
+               throw(MAL,"mal.interpreter",MAL_STACK_FAIL);
+
+       /*safeguardStack*/
+       nstk->stkdepth = nstk->stksize + stk->stkdepth;
+       nstk->calldepth = stk->calldepth + 1;
+       if (nstk->calldepth > 256)
+               throw(MAL, "mal.interpreter", MAL_CALLDEPTH_FAIL);
+       if ((unsigned)nstk->stkdepth > THREAD_STACK_SIZE / sizeof(mb->var[0]) / 
4 && THRhighwater())
+               /* we are running low on stack space */
+               throw(MAL, "mal.interpreter", MAL_STACK_FAIL);
+
+       /* copy arguments onto destination stack */
+       q= getInstrPtr(pci->blk,0);
+       arg = q->retc;
+       for (ii = pci->retc; ii < pci->argc; ii++,arg++) {
+               lhs = &nstk->stk[q->argv[arg]];
+               rhs = &stk->stk[pci->argv[ii]];
+               VALcopy(lhs, rhs);
+               if (lhs->vtype == TYPE_bat)
+                       BBPincref(lhs->val.bval, TRUE);
+       }
+       ret = runMALsequence(cntxt, pci->blk, 1, pci->blk->stop, nstk, stk, 
pci);
+       GDKfree(nstk);
        @:restoreTarget(@1,@3)@
        @:exceptionHndlr(@1,@2,@3)@
        @:timingHndlr(@1)@
_______________________________________________
Checkin-list mailing list
Checkin-list@monetdb.org
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to