瀏覽代碼

new definition for `luaD_call' and `luaD_adjusttop'

Roberto Ierusalimschy 24 年之前
父節點
當前提交
cbc59592ff
共有 9 個文件被更改,包括 94 次插入95 次删除
  1. 11 5
      lapi.c
  2. 5 3
      lcode.c
  3. 2 2
      ldebug.c
  4. 20 35
      ldo.c
  5. 3 3
      ldo.h
  6. 6 4
      lgc.c
  7. 2 2
      lopcodes.h
  8. 5 5
      lparser.c
  9. 40 36
      lvm.c

+ 11 - 5
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 1.142 2001/06/05 18:17:01 roberto Exp roberto $
+** $Id: lapi.c,v 1.143 2001/06/06 18:00:19 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -95,11 +95,13 @@ LUA_API int lua_gettop (lua_State *L) {
 
 LUA_API void lua_settop (lua_State *L, int index) {
   lua_lock(L);
-  if (index >= 0)
-    luaD_adjusttop(L, L->ci->base, index);
+  if (index >= 0) {
+    api_check(L, index <= L->stack_last - L->ci->base);
+    luaD_adjusttop(L, L->ci->base+index);
+  }
   else {
     api_check(L, -(index+1) <= (L->top - L->ci->base));
-    L->top = L->top+index+1;  /* index is negative */
+    L->top += index+1;  /* `subtract' index (index is negative) */
   }
   lua_unlock(L);
 }
@@ -545,9 +547,13 @@ LUA_API int lua_ref (lua_State *L,  int lock) {
 */
 
 LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults) {
+  StkId func;
   lua_lock(L);
   api_checknelems(L, nargs+1);
-  luaD_call(L, L->top-(nargs+1), nresults);
+  func = L->top - (nargs+1);
+  luaD_call(L, func);
+  if (nresults != LUA_MULTRET)
+    luaD_adjusttop(L, func + nresults);
   lua_unlock(L);
 }
 

+ 5 - 3
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 1.71 2001/06/07 15:01:21 roberto Exp roberto $
+** $Id: lcode.c,v 1.72 2001/06/08 12:29:27 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -261,10 +261,12 @@ static int number_constant (FuncState *fs, lua_Number r) {
 
 void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) {
   if (e->k == VCALL) {  /* expression is an open function call? */
-    SETARG_C(getcode(fs, e), nresults);  /* set number of results */
+    int a = GETARG_A(getcode(fs, e));
+    int c = (nresults == LUA_MULTRET) ? NO_REG : a + nresults;
+    SETARG_C(getcode(fs, e), c);
     if (nresults == 1) {  /* `regular' expression? */
       e->k = VNONRELOC;
-      e->u.i.info = GETARG_A(getcode(fs, e));
+      e->u.i.info = a;
     }
   }
 }

+ 2 - 2
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 1.79 2001/06/07 14:44:51 roberto Exp roberto $
+** $Id: ldebug.c,v 1.80 2001/06/08 12:29:27 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -421,7 +421,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
         }
         check(b > a);
         checkreg(pt, b-1);
-        checkreg(pt, a+c-1);
+        checkreg(pt, c-1);
         if (reg >= a) last = pc;  /* affect all registers above base */
         break;
       }

+ 20 - 35
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.134 2001/04/11 18:39:37 roberto Exp roberto $
+** $Id: ldo.c,v 1.135 2001/06/05 19:27:32 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -62,19 +62,12 @@ void luaD_stackerror (lua_State *L) {
 
 
 /*
-** Adjust stack. Set top to base+extra, pushing NILs if needed.
-** (we cannot add base+extra unless we are sure it fits in the stack;
-**  otherwise the result of such operation on pointers is undefined)
+** adjust top to new value; assume that new top is valid
 */
-void luaD_adjusttop (lua_State *L, StkId base, int extra) {
-  int diff = extra-(L->top-base);
-  if (diff <= 0)
-    L->top = base+extra;
-  else {
-    luaD_checkstack(L, diff);
-    while (diff--)
-      setnilvalue(L->top++);
-  }
+void luaD_adjusttop (lua_State *L, StkId newtop) {
+  while (L->top < newtop)
+    setnilvalue(L->top++);
+  L->top = newtop;  /* `newtop' could be lower than `top' */
 }
 
 
@@ -140,11 +133,10 @@ static StkId callCclosure (lua_State *L, const struct Closure *cl) {
 /*
 ** Call a function (C or Lua). The function to be called is at *func.
 ** The arguments are on the stack, right after the function.
-** When returns, the results are on the stack, starting at the original
+** When returns, all the results are on the stack, starting at the original
 ** function position.
-** The number of results is nResults, unless nResults=LUA_MULTRET.
 */ 
-void luaD_call (lua_State *L, StkId func, int nResults) {
+void luaD_call (lua_State *L, StkId func) {
   lua_Hook callhook;
   StkId firstResult;
   CallInfo ci;
@@ -168,20 +160,9 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
     luaD_callHook(L, callhook, l_s("return"));
   L->ci = ci.prev;  /* unchain callinfo */
   /* move results to `func' (to erase parameters and function) */
-  if (nResults == LUA_MULTRET) {
-    while (firstResult < L->top)  /* copy all results */
-      setobj(func++, firstResult++);
-    L->top = func;
-  }
-  else {  /* copy at most `nResults' */
-    for (; nResults > 0 && firstResult < L->top; nResults--)
-      setobj(func++, firstResult++);
-    L->top = func;
-    for (; nResults > 0; nResults--) {  /* if there are not enough results */
-      setnilvalue(L->top);  /* adjust the stack */
-      incr_top;  /* must check stack space */
-    }
-  }
+  while (firstResult < L->top)
+    setobj(func++, firstResult++);
+  L->top = func;
   luaC_checkGC(L);
 }
 
@@ -196,7 +177,9 @@ struct CallS {  /* data to `f_call' */
 
 static void f_call (lua_State *L, void *ud) {
   struct CallS *c = (struct CallS *)ud;
-  luaD_call(L, c->func, c->nresults);
+  luaD_call(L, c->func);
+  if (c->nresults != LUA_MULTRET)
+    luaD_adjusttop(L, c->func + c->nresults);
 }
 
 
@@ -307,12 +290,14 @@ struct lua_longjmp {
 
 
 static void message (lua_State *L, const l_char *s) {
-  luaV_getglobal(L, luaS_newliteral(L, l_s(LUA_ERRORMESSAGE)), L->top);
-  if (ttype(L->top) == LUA_TFUNCTION) {
+  StkId top = L->top;
+  luaV_getglobal(L, luaS_newliteral(L, l_s(LUA_ERRORMESSAGE)), top);
+  if (ttype(top) == LUA_TFUNCTION) {
     incr_top;
-    setsvalue(L->top, luaS_new(L, s));
+    setsvalue(top+1, luaS_new(L, s));
     incr_top;
-    luaD_call(L, L->top-2, 0);
+    luaD_call(L, top);
+    L->top = top;
   }
 }
 

+ 3 - 3
ldo.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 1.32 2001/03/07 18:09:25 roberto Exp roberto $
+** $Id: ldo.h,v 1.33 2001/06/05 19:41:24 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -23,9 +23,9 @@
 
 
 void luaD_init (lua_State *L, int stacksize);
-void luaD_adjusttop (lua_State *L, StkId base, int extra);
+void luaD_adjusttop (lua_State *L, StkId newtop);
 void luaD_lineHook (lua_State *L, int line, lua_Hook linehook);
-void luaD_call (lua_State *L, StkId func, int nResults);
+void luaD_call (lua_State *L, StkId func);
 void luaD_stackerror (lua_State *L);
 
 void luaD_error (lua_State *L, const l_char *s);

+ 6 - 4
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.100 2001/06/06 18:00:19 roberto Exp roberto $
+** $Id: lgc.c,v 1.101 2001/06/07 15:01:21 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -338,12 +338,14 @@ static void callgcTM (lua_State *L, const TObject *obj) {
   Closure *tm = luaT_gettmbyObj(G(L), obj, TM_GC);
   if (tm != NULL) {
     int oldah = L->allowhooks;
+    StkId top = L->top;
     L->allowhooks = 0;  /* stop debug hooks during GC tag methods */
     luaD_checkstack(L, 2);
-    setclvalue(L->top, tm);
-    setobj(L->top+1, obj);
+    setclvalue(top, tm);
+    setobj(top+1, obj);
     L->top += 2;
-    luaD_call(L, L->top-2, 0);
+    luaD_call(L, top);
+    L->top = top;  /* restore top */
     L->allowhooks = oldah;  /* restore hooks */
   }
 }

+ 2 - 2
lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.72 2001/04/06 18:25:00 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.73 2001/06/05 18:17:01 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -165,7 +165,7 @@ OP_TESTF,/*	A B	test := not R(B); if (test) R(A) := nil		*/
 
 OP_NILJMP,/*	A	R(A) := nil; PC++;				*/
 
-OP_CALL,/*	A B C	R(A), ... ,R(A+C-1) := R(A)(R(A+1), ... ,R(B-1))*/
+OP_CALL,/*	A B C	R(A), ... ,R(C-1) := R(A)(R(A+1), ... ,R(B-1))	*/
 OP_RETURN,/*	A B	return R(A), ... ,R(B-1)	(see (3))	*/
 
 OP_FORPREP,/*	A sBc							*/

+ 5 - 5
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.145 2001/06/07 14:44:51 roberto Exp roberto $
+** $Id: lparser.c,v 1.146 2001/06/08 12:29:27 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -424,7 +424,7 @@ static void funcargs (LexState *ls, expdesc *f) {
         args.k = VVOID;
       else {
         explist1(ls, &args);
-        luaK_setcallreturns(fs, &args, NO_REG);
+        luaK_setcallreturns(fs, &args, LUA_MULTRET);
       }
       check_match(ls, l_c(')'), l_c('('), line);
       break;
@@ -452,7 +452,7 @@ static void funcargs (LexState *ls, expdesc *f) {
       luaK_exp2nextreg(fs, &args);  /* close last argument */
     top = fs->freereg;
   }
-  init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, top, 1));
+  init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, top, base+1));
   fs->freereg = base+1;  /* call remove function and arguments and leaves
                             (unless changed) one result */
 }
@@ -530,7 +530,7 @@ static int listfields (LexState *ls, expdesc *t) {
     n++;
   }
   if (v.k == VCALL) {
-    luaK_setcallreturns(fs, &v, NO_REG);
+    luaK_setcallreturns(fs, &v, LUA_MULTRET);
     luaK_codeABc(fs, OP_SETLISTO, t->u.i.info, n-1);
   }
   else {
@@ -1098,7 +1098,7 @@ static void retstat (LexState *ls) {
   else {
     int n = explist1(ls, &e);  /* optional return values */
     if (e.k == VCALL) {
-      luaK_setcallreturns(fs, &e, NO_REG);
+      luaK_setcallreturns(fs, &e, LUA_MULTRET);
       first = fs->nactloc;
       last1 = NO_REG;  /* return all values */
     }

+ 40 - 36
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.180 2001/06/05 19:27:32 roberto Exp roberto $
+** $Id: lvm.c,v 1.181 2001/06/08 12:29:27 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -106,33 +106,35 @@ void luaV_Lclosure (lua_State *L, Proto *l, int nelems) {
 }
 
 
-static void callTM (lua_State *L, const l_char *fmt, ...) {
+static void callTM (lua_State *L, Closure *f, const l_char *fmt, ...) {
   va_list argp;
   StkId base = L->top;
-  int has_result = 0;
+  StkId result = NULL;  /* result position */
   va_start(argp, fmt);
+  setclvalue(L->top, f);  /* push function */
+  incr_top;
+  if (*fmt == l_c('r')) {
+    fmt++;
+    result = va_arg(argp, TObject *);  /* result position */
+  }
   while (*fmt) {
-    switch (*fmt++) {
-      case l_c('c'):
-        setclvalue(L->top, va_arg(argp, Closure *));
-        break;
-      case l_c('o'):
+    if (*fmt++ == l_c('o')) {
         setobj(L->top, va_arg(argp, TObject *));
-        break;
-      case l_c('s'):
-        setsvalue(L->top, va_arg(argp, TString *));
-        break;
-      case l_c('r'):
-        has_result = 1;
-        continue;
+    }
+    else {
+      lua_assert(*(fmt-1) == l_c('s'));
+      setsvalue(L->top, va_arg(argp, TString *));
     }
     incr_top;
   }
-  luaD_call(L, base, has_result);
-  if (has_result) {
-    L->top--;
-    setobj(va_arg(argp, TObject *), L->top);
+  luaD_call(L, base);
+  if (result) {  /* need result? */
+    if (L->top == base)  /* are there valid results? */
+      setnilvalue(result);  /* function had no results */
+    else
+      setobj(result, base);  /* get first result */
   }
+  L->top = base;  /* restore top */
   va_end(argp);
 }
 
@@ -162,7 +164,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res) {
     if (tm == NULL)  /* no tag method? */
       luaG_typeerror(L, t, l_s("index"));
   }
-  callTM(L, l_s("coor"), tm, t, key, res);
+  callTM(L, tm, l_s("roo"), res, t, key);
 }
 
 
@@ -185,7 +187,7 @@ void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val) {
     if (tm == NULL)  /* no tag method? */
       luaG_typeerror(L, t, l_s("index"));
   }
-  callTM(L, l_s("cooo"), tm, t, key, val);
+  callTM(L, tm, l_s("ooo"), t, key, val);
 }
 
 
@@ -196,7 +198,7 @@ void luaV_getglobal (lua_State *L, TString *name, StkId res) {
       (tm = luaT_gettmbyObj(G(L), value, TM_GETGLOBAL)) == NULL) {
     setobj(res, value);  /* default behavior */
   } else
-    callTM(L, l_s("csor"), tm, name, value, res);
+    callTM(L, tm, l_s("rso"), res, name, value);
 }
 
 
@@ -207,7 +209,7 @@ void luaV_setglobal (lua_State *L, TString *name, StkId val) {
      (tm = luaT_gettmbyObj(G(L), oldvalue, TM_SETGLOBAL)) == NULL) {
     setobj(oldvalue, val);  /* raw set */
   } else
-    callTM(L, l_s("csoo"), tm, name, oldvalue, val);
+    callTM(L, tm, l_s("soo"), name, oldvalue, val);
 }
 
 
@@ -224,7 +226,7 @@ static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,
     }
   }
   opname = luaS_new(L, luaT_eventname[event]);
-  callTM(L, l_s("coosr"), tm, p1, p2, opname, res);
+  callTM(L, tm, l_s("roos"), res, p1, p2, opname);
   return 1;
 }
 
@@ -320,9 +322,12 @@ static void luaV_pack (lua_State *L, StkId firstelem) {
 
 static void adjust_varargs (lua_State *L, StkId base, int nfixargs) {
   int nvararg = (L->top-base) - nfixargs;
-  if (nvararg < 0)
-    luaD_adjusttop(L, base, nfixargs);
-  luaV_pack(L, base+nfixargs);
+  StkId firstvar = base + nfixargs;  /* position of first vararg */
+  if (nvararg < 0) {
+    luaD_checkstack(L, -nvararg);
+    luaD_adjusttop(L, firstvar);
+  }
+  luaV_pack(L, firstvar);
 }
 
 
@@ -368,7 +373,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
     luaD_stackerror(L);
   while (L->top < base+tf->maxstacksize)
     setnilvalue(L->top++);
-  L->top = base+tf->maxstacksize;
+  L->top = base + tf->maxstacksize;
   pc = tf->code;
   L->ci->pc = &pc;
   linehook = L->linehook;
@@ -544,16 +549,15 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
         break;
       }
       case OP_CALL: {
-        int nres;
+        int c;
         int b = GETARG_B(i);
         if (b != NO_REG)
           L->top = base+b;
-        nres = GETARG_C(i);
-        if (nres == NO_REG) nres = LUA_MULTRET;
-        luaD_call(L, ra, nres);
-        if (nres != LUA_MULTRET) {
-          lua_assert(L->top == ra+nres);
-          L->top = base+tf->maxstacksize;
+        luaD_call(L, ra);
+        c = GETARG_C(i);
+        if (c != NO_REG) {
+          while (L->top < base+c) setnilvalue(L->top++);
+          L->top = base + tf->maxstacksize;
         }
         break;
       }
@@ -637,7 +641,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
         luaV_checkGC(L, ra+nup);
         L->top = ra+nup;
         luaV_Lclosure(L, p, nup);
-        L->top = base+tf->maxstacksize;
+        L->top = base + tf->maxstacksize;
         break;
       }
     }