浏览代码

in 'luaD_precall', in vararg functions, complete missing parameters
only after moving them to final place (avoids checking the stack
again)

Roberto Ierusalimschy 9 年之前
父节点
当前提交
c5363a1b58
共有 2 个文件被更改,包括 21 次插入25 次删除
  1. 13 15
      ldo.c
  2. 8 10
      lvm.c

+ 13 - 15
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.144 2015/10/28 17:28:40 roberto Exp roberto $
+** $Id: ldo.c,v 2.145 2015/11/02 11:48:59 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -273,15 +273,15 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
   int i;
   int nfixargs = p->numparams;
   StkId base, fixed;
-  lua_assert(actual >= nfixargs);
   /* move fixed parameters to final position */
-  luaD_checkstack(L, p->maxstacksize);  /* check again for new 'base' */
   fixed = L->top - actual;  /* first fixed argument */
   base = L->top;  /* final position of first argument */
-  for (i=0; i<nfixargs; i++) {
+  for (i = 0; i < nfixargs && i < actual; i++) {
     setobjs2s(L, L->top++, fixed + i);
-    setnilvalue(fixed + i);
+    setnilvalue(fixed + i);  /* erase original copy (for GC) */
   }
+  for (; i < nfixargs; i++)
+    setnilvalue(L->top++);  /* complete missing arguments */
   return base;
 }
 
@@ -354,25 +354,23 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
       StkId base;
       Proto *p = clLvalue(func)->p;
       int n = cast_int(L->top - func) - 1;  /* number of real arguments */
-      checkstackp(L, p->maxstacksize, func);
-      for (; n < p->numparams; n++)
-        setnilvalue(L->top++);  /* complete missing arguments */
-      if (p->is_vararg != 1)  /* do not use vararg? */
+      int fsize = p->maxstacksize;  /* frame size */
+      checkstackp(L, fsize, func);
+      if (p->is_vararg != 1) {  /* do not use vararg? */
+        for (; n < p->numparams; n++)
+          setnilvalue(L->top++);  /* complete missing arguments */
         base = func + 1;
-      else {
-        ptrdiff_t funcr = savestack(L, func);
-        base = adjust_varargs(L, p, n);
-        func = restorestack(L, funcr);  /* previous call can change stack */
       }
+      else
+        base = adjust_varargs(L, p, n);
       ci = next_ci(L);  /* now 'enter' new function */
       ci->nresults = nresults;
       ci->func = func;
       ci->u.l.base = base;
-      ci->top = base + p->maxstacksize;
+      L->top = ci->top = base + fsize;
       lua_assert(ci->top <= L->stack_last);
       ci->u.l.savedpc = p->code;  /* starting point */
       ci->callstatus = CIST_LUA;
-      L->top = ci->top;
       if (L->hookmask & LUA_MASKCALL)
         callhook(L, ci);
       return 0;

+ 8 - 10
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.257 2015/10/28 14:50:09 roberto Exp roberto $
+** $Id: lvm.c,v 2.258 2015/11/02 11:43:17 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -1274,23 +1274,21 @@ void luaV_execute (lua_State *L) {
         vmbreak;
       }
       vmcase(OP_VARARG) {
-        int b = GETARG_B(i) - 1;
+        int b = GETARG_B(i) - 1;  /* required results */
         int j;
         int n = cast_int(base - ci->func) - cl->p->numparams - 1;
+        if (n < 0)  /* less arguments than parameters? */
+          n = 0;  /* no vararg arguments */
         if (b < 0) {  /* B == 0? */
           b = n;  /* get all var. arguments */
           Protect(luaD_checkstack(L, n));
           ra = RA(i);  /* previous call may change the stack */
           L->top = ra + n;
         }
-        for (j = 0; j < b; j++) {
-          if (j < n) {
-            setobjs2s(L, ra + j, base - n + j);
-          }
-          else {
-            setnilvalue(ra + j);
-          }
-        }
+        for (j = 0; j < b && j < n; j++)
+          setobjs2s(L, ra + j, base - n + j);
+        for (; j < b; j++)  /* complete required results with nil */
+          setnilvalue(ra + j);
         vmbreak;
       }
       vmcase(OP_EXTRAARG) {