فهرست منبع

when running Lua code, there is no need to keep 'L->top' "correct";
set it only when needed.

Roberto Ierusalimschy 7 سال پیش
والد
کامیت
1d5b885437
5فایلهای تغییر یافته به همراه53 افزوده شده و 41 حذف شده
  1. 10 9
      ldebug.c
  2. 6 3
      ldo.c
  3. 12 2
      lgc.c
  4. 19 7
      ltm.c
  5. 6 20
      lvm.c

+ 10 - 9
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.148 2017/12/13 18:32:09 roberto Exp roberto $
+** $Id: ldebug.c,v 2.149 2017/12/15 13:07:10 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -189,14 +189,10 @@ static const char *upvalname (Proto *p, int uv) {
 
 static const char *findlocal (lua_State *L, CallInfo *ci, int n,
                               StkId *pos) {
-  const char *name = NULL;
-  StkId base;
-  if (isLua(ci)) {
-    base = ci->func + 1;
-    name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
-  }
-  else
-    base = ci->func + 1;
+  StkId base = ci->func + 1;
+  const char *name = (isLua(ci))
+                     ? luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci))
+                     : NULL;
   if (name == NULL) {  /* no 'standard' name? */
     StkId limit = (ci == L->ci) ? L->top : ci->next->func;
     if (limit - base >= n && n > 0)  /* is 'n' inside 'ci' stack? */
@@ -741,6 +737,8 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
   const char *msg;
   va_list argp;
   luaC_checkGC(L);  /* error message uses memory */
+  if (isLuacode(ci))
+    L->top = ci->top;  /* prepare top */
   va_start(argp, fmt);
   msg = luaO_pushvfstring(L, fmt, argp);  /* format message */
   va_end(argp);
@@ -764,6 +762,7 @@ static int changedline (Proto *p, int oldpc, int newpc) {
 
 
 void luaG_traceexec (lua_State *L) {
+  ptrdiff_t oldtop = savestack(L, L->top);
   CallInfo *ci = L->ci;
   lu_byte mask = L->hookmask;
   int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT));
@@ -775,6 +774,7 @@ void luaG_traceexec (lua_State *L) {
     ci->callstatus &= ~CIST_HOOKYIELD;  /* erase mark */
     return;  /* do not call hook again (VM yielded, so it did not move) */
   }
+  L->top = ci->top;  /* prepare top */
   if (counthook)
     luaD_hook(L, LUA_HOOKCOUNT, -1);  /* call count hook */
   if (mask & LUA_MASKLINE) {
@@ -789,6 +789,7 @@ void luaG_traceexec (lua_State *L) {
     }
     L->oldpc = npc;
   }
+  L->top = restorestack(L, oldtop);
   if (L->status == LUA_YIELD) {  /* did hook yield? */
     if (counthook)
       L->hookcount = 1;  /* undo decrement to zero */

+ 6 - 3
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.181 2017/12/15 13:07:10 roberto Exp roberto $
+** $Id: ldo.c,v 2.182 2017/12/19 16:40:17 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -299,6 +299,7 @@ static void callhook (lua_State *L, CallInfo *ci, int istail) {
   ci->u.l.trap = 1;
   if (!(L->hookmask & LUA_MASKCALL))
     return;  /* some other hook */
+  L->top = ci->top;  /* prepare top */
   ci->u.l.savedpc++;  /* hooks assume 'pc' is already incremented */
   if (istail) {
     ci->callstatus |= CIST_TAIL;
@@ -312,6 +313,8 @@ static void callhook (lua_State *L, CallInfo *ci, int istail) {
 
 
 static void rethook (lua_State *L, CallInfo *ci) {
+  if (isLuacode(ci))
+    L->top = ci->top;  /* prepare top */
   if (L->hookmask & LUA_MASKRET)  /* is return hook on? */
     luaD_hook(L, LUA_HOOKRET, -1);  /* call it */
   if (isLua(ci->previous))
@@ -421,7 +424,7 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n) {
     L->top -= (func - ci->func);  /* move down top */
     luaT_adjustvarargs(L, p, n - 1);
   }
-  L->top = ci->top = ci->func + 1 + fsize;  /* top for new function */
+  ci->top = ci->func + 1 + fsize;  /* top for new function */
   lua_assert(ci->top <= L->stack_last);
   ci->u.l.savedpc = p->code;  /* starting point */
   ci->callstatus |= CIST_TAIL;
@@ -476,7 +479,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
       ci = next_ci(L);  /* now 'enter' new function */
       ci->nresults = nresults;
       ci->func = func;
-      L->top = ci->top = func + 1 + fsize;
+      ci->top = func + 1 + fsize;
       lua_assert(ci->top <= L->stack_last);
       ci->u.l.savedpc = p->code;  /* starting point */
       ci->callstatus = 0;

+ 12 - 2
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.241 2017/12/01 17:38:49 roberto Exp roberto $
+** $Id: lgc.c,v 2.242 2017/12/08 17:28:25 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -569,13 +569,23 @@ static int traverseLclosure (global_State *g, LClosure *cl) {
 }
 
 
+/*
+** Traverse a thread, marking the elements in the stack up to its top
+** and cleaning the rest of the stack in the last traversal.
+** That ensures that the entire stack have valid (non-dead) objects.
+** In an emergency collection running Lua code, 'L->top' may not be
+** update. In that case, traverse at least up to 'ci->top'.
+*/
 static int traversethread (global_State *g, lua_State *th) {
   StkId o = th->stack;
+  StkId top = th->top;
   if (o == NULL)
     return 1;  /* stack not completely built yet */
   lua_assert(g->gcstate == GCSatomic ||
              th->openupval == NULL || isintwups(th));
-  for (; o < th->top; o++)  /* mark live elements in the stack */
+  if (g->gcemergency && isLuacode(th->ci) && top < th->ci->top)
+    top = th->ci->top;
+  for (; o < top; o++)  /* mark live elements in the stack */
     markvalue(g, s2v(o));
   if (g->gcstate == GCSatomic) {  /* final traversal? */
     StkId lim = th->stack + th->stacksize;  /* real end of stack */

+ 19 - 7
ltm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 2.53 2017/12/15 13:07:10 roberto Exp roberto $
+** $Id: ltm.c,v 2.54 2017/12/19 16:40:17 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -101,12 +101,12 @@ const char *luaT_objtypename (lua_State *L, const TValue *o) {
 
 void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
                   const TValue *p2, const TValue *p3) {
-  StkId func = L->top;
+  StkId func = (isLuacode(L->ci)) ? L->ci->top : L->top;
   setobj2s(L, func, f);  /* push function (assume EXTRA_STACK) */
   setobj2s(L, func + 1, p1);  /* 1st argument */
   setobj2s(L, func + 2, p2);  /* 2nd argument */
   setobj2s(L, func + 3, p3);  /* 3rd argument */
-  L->top += 4;
+  L->top = func + 4;
   /* metamethod may yield only when called from Lua code */
   if (isLuacode(L->ci))
     luaD_call(L, func, 0);
@@ -115,8 +115,8 @@ void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
 }
 
 
-void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1,
-                     const TValue *p2, StkId res) {
+static void reallycallTMres (lua_State *L, const TValue *f, const TValue *p1,
+                             const TValue *p2, StkId res) {
   ptrdiff_t result = savestack(L, res);
   StkId func = L->top;
   setobj2s(L, func, f);  /* push function (assume EXTRA_STACK) */
@@ -129,7 +129,15 @@ void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1,
   else
     luaD_callnoyield(L, func, 1);
   res = restorestack(L, result);
-  setobjs2s(L, res, --L->top);  /* more result to its place */
+  setobjs2s(L, res, --L->top);  /* move result to its place */
+}
+
+
+void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1,
+                     const TValue *p2, StkId res) {
+  if (isLuacode(L->ci))
+    L->top = L->ci->top;  /* prepare top */
+  reallycallTMres(L, f, p1, p2, res);
 }
 
 
@@ -139,13 +147,15 @@ static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
   if (ttisnil(tm))
     tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
   if (ttisnil(tm)) return 0;
-  luaT_callTMres(L, tm, p1, p2, res);
+  reallycallTMres(L, tm, p1, p2, res);
   return 1;
 }
 
 
 void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
                     StkId res, TMS event) {
+  if (event != TM_CONCAT && isLuacode(L->ci))
+    L->top = L->ci->top;  /* prepare top */
   if (!callbinTM(L, p1, p2, res, event)) {
     switch (event) {
       case TM_CONCAT:
@@ -185,6 +195,8 @@ void luaT_trybiniTM (lua_State *L, const TValue *p1, int i2,
 
 int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2,
                       TMS event) {
+  if (isLuacode(L->ci))
+    L->top = L->ci->top;  /* prepare top */
   if (callbinTM(L, p1, p2, L->top, event))  /* try original event */
     return !l_isfalse(s2v(L->top));
   else if (event == TM_LE) {

+ 6 - 20
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.326 2017/12/18 17:53:50 roberto Exp roberto $
+** $Id: lvm.c,v 2.327 2017/12/19 16:18:04 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -464,6 +464,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
   }
   if (tm == NULL)  /* no TM? */
     return 0;  /* objects are different */
+  if (isLuacode(L->ci))
+    L->top = L->ci->top;  /* prepare top */
   luaT_callTMres(L, tm, t1, t2, L->top);  /* call TM */
   return !l_isfalse(s2v(L->top));
 }
@@ -726,20 +728,10 @@ void luaV_finishOp (lua_State *L) {
       }
       /* move final result to final position */
       setobjs2s(L, ci->func + 1 + GETARG_A(inst), L->top - 1);
-      L->top = ci->top;  /* restore top */
       break;
     }
-    case OP_TFORCALL: {
-      lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP);
-      L->top = ci->top;  /* correct top */
-      break;
-    }
-    case OP_CALL: {
-      if (GETARG_C(inst) - 1 >= 0)  /* nresults >= 0? */
-        L->top = ci->top;  /* adjust results */
-      break;
-    }
-    case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE:
+    case OP_TFORCALL: case OP_CALL: case OP_TAILCALL:
+    case OP_SETTABUP: case OP_SETTABLE:
     case OP_SETI: case OP_SETFIELD:
       break;
     default: lua_assert(0);
@@ -808,7 +800,7 @@ void luaV_finishOp (lua_State *L) {
 
 #define checkGC(L,c)  \
 	{ luaC_condGC(L, L->top = (c),  /* limit of live values */ \
-                   (L->top = ci->top, updatetrap(ci)));  /* restore top */ \
+                         updatetrap(ci)); \
            luai_threadyield(L); }
 
 
@@ -1387,7 +1379,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
         rb = base + b;
         setobjs2s(L, ra, rb);
         checkGC(L, (ra >= rb ? ra + 1 : rb));
-        L->top = ci->top;  /* restore top */
         vmbreak;
       }
       vmcase(OP_CLOSE) {
@@ -1491,9 +1482,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
           L->top = ra + b;  /* top signals number of arguments */
         /* else previous instruction set top */
         Protect(luaD_call(L, ra, nresults));
-        if (nresults >= 0)  /* fixed number of results? */
-          L->top = ci->top;  /* correct top */
-        /* else leave top for next instruction */
         vmbreak;
       }
       vmcase(OP_TAILCALL) {
@@ -1651,7 +1639,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
         setobjs2s(L, cb, ra);
         L->top = cb + 3;  /* func. + 2 args (state and index) */
         Protect(luaD_call(L, cb, GETARG_C(i)));
-        L->top = ci->top;
         if (trap)  /* keep 'base' correct for next instruction */
           updatebase(ci);
         i = *(pc++);  /* go to next instruction */
@@ -1686,7 +1673,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
           last--;
           luaC_barrierback(L, h, val);
         }
-        L->top = ci->top;  /* correct top (in case of previous open call) */
         vmbreak;
       }
       vmcase(OP_CLOSURE) {