Browse Source

'nresults' moved into 'callstatus'

That gives us more free bits in 'callstatus', for future use.
Roberto Ierusalimschy 1 year ago
parent
commit
15231d4fb2
6 changed files with 79 additions and 62 deletions
  1. 1 3
      lapi.c
  2. 2 2
      ldebug.c
  3. 38 34
      ldo.c
  4. 0 1
      lstate.c
  5. 35 19
      lstate.h
  6. 3 3
      lvm.c

+ 1 - 3
lapi.c

@@ -1103,7 +1103,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
     ci->u2.funcidx = cast_int(savestack(L, c.func));
     ci->u.c.old_errfunc = L->errfunc;
     L->errfunc = func;
-    setoah(ci->callstatus, L->allowhook);  /* save value of 'allowhook' */
+    setoah(ci, L->allowhook);  /* save value of 'allowhook' */
     ci->callstatus |= CIST_YPCALL;  /* function can do error recovery */
     luaD_call(L, c.func, nresults);  /* do the call */
     ci->callstatus &= ~CIST_YPCALL;
@@ -1280,11 +1280,9 @@ LUA_API int lua_next (lua_State *L, int idx) {
 
 
 LUA_API void lua_toclose (lua_State *L, int idx) {
-  int nresults;
   StkId o;
   lua_lock(L);
   o = index2stack(L, idx);
-  nresults = L->ci->nresults;
   api_check(L, L->tbclist.p < o, "given index below or equal a marked one");
   luaF_newtbcupval(L, o);  /* create new to-be-closed upvalue */
   L->ci->callstatus |= CIST_CLSRET;  /* mark that function has TBC slots */

+ 2 - 2
ldebug.c

@@ -346,13 +346,13 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
           ar->nparams = 0;
         }
         else {
-          ar->isvararg = f->l.p->flag & PF_ISVARARG;
+          ar->isvararg = (f->l.p->flag & PF_ISVARARG) ? 1 : 0;
           ar->nparams = f->l.p->numparams;
         }
         break;
       }
       case 't': {
-        ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0;
+        ar->istailcall = (ci != NULL && (ci->callstatus & CIST_TAIL));
         break;
       }
       case 'n': {

+ 38 - 34
ldo.c

@@ -452,16 +452,31 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
 }
 
 
+/* Generic case for 'moveresult */
+l_sinline void genmoveresults (lua_State *L, StkId res, int nres,
+                                             int wanted) {
+  StkId firstresult = L->top.p - nres;  /* index of first result */
+  int i;
+  if (nres > wanted)  /* extra results? */
+    nres = wanted;  /* don't need them */
+  for (i = 0; i < nres; i++)  /* move all results to correct place */
+    setobjs2s(L, res + i, firstresult + i);
+  for (; i < wanted; i++)  /* complete wanted number of results */
+    setnilvalue(s2v(res + i));
+  L->top.p = res + wanted;  /* top points after the last result */
+}
+
+
 /*
-** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'.
-** Handle most typical cases (zero results for commands, one result for
-** expressions, multiple results for tail calls/single parameters)
-** separated.
+** Given 'nres' results at 'firstResult', move 'fwanted-1' of them
+** to 'res'.  Handle most typical cases (zero results for commands,
+** one result for expressions, multiple results for tail calls/single
+** parameters) separated. The flag CIST_CLSRET in 'fwanted', if set,
+** forces the swicth to go to the default case.
 */
-l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) {
-  StkId firstresult;
-  int i;
-  switch (wanted) {  /* handle typical cases separately */
+l_sinline void moveresults (lua_State *L, StkId res, int nres,
+                                          l_uint32 fwanted) {
+  switch (fwanted) {  /* handle typical cases separately */
     case 0 + 1:  /* no values needed */
       L->top.p = res;
       return;
@@ -473,12 +488,11 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) {
       L->top.p = res + 1;
       return;
     case LUA_MULTRET + 1:
-      wanted = nres;  /* we want all results */
+      genmoveresults(L, res, nres, nres);  /* we want all results */
       break;
-    default:  /* two/more results and/or to-be-closed variables */
-      if (!(wanted & CIST_CLSRET))
-        wanted--;
-      else {  /* to-be-closed variables? */
+    default: {  /* two/more results and/or to-be-closed variables */
+      int wanted = get_nresults(fwanted);
+      if (fwanted & CIST_CLSRET) {  /* to-be-closed variables? */
         L->ci->u2.nres = nres;
         res = luaF_close(L, res, CLOSEKTOP, 1);
         L->ci->callstatus &= ~CIST_CLSRET;
@@ -487,21 +501,13 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) {
           rethook(L, L->ci, nres);
           res = restorestack(L, savedres);  /* hook can move stack */
         }
-        wanted = (wanted & ~CIST_CLSRET) - 1;
         if (wanted == LUA_MULTRET)
           wanted = nres;  /* we want all results */
       }
+      genmoveresults(L, res, nres, wanted);
       break;
+    }
   }
-  /* generic case */
-  firstresult = L->top.p - nres;  /* index of first result */
-  if (nres > wanted)  /* extra results? */
-    nres = wanted;  /* don't need them */
-  for (i = 0; i < nres; i++)  /* move all results to correct place */
-    setobjs2s(L, res + i, firstresult + i);
-  for (; i < wanted; i++)  /* complete wanted number of results */
-    setnilvalue(s2v(res + i));
-  L->top.p = res + wanted;  /* top points after the last result */
 }
 
 
@@ -512,13 +518,11 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) {
 ** that.
 */
 void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
-  int wanted = ci->nresults + 1;
-  if (ci->callstatus & CIST_CLSRET)
-    wanted |= CIST_CLSRET;  /* don't check hook in this case */
-  else if (l_unlikely(L->hookmask))
+  l_uint32 fwanted = ci->callstatus & (CIST_CLSRET | CIST_NRESULTS);
+  if (l_unlikely(L->hookmask) && !(fwanted & CIST_CLSRET))
     rethook(L, ci, nres);
   /* move results to proper place */
-  moveresults(L, ci->func.p, nres, wanted);
+  moveresults(L, ci->func.p, nres, fwanted);
   /* function cannot be in any of these cases when returning */
   lua_assert(!(ci->callstatus &
         (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET)));
@@ -530,12 +534,12 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
 #define next_ci(L)  (L->ci->next ? L->ci->next : luaE_extendCI(L))
 
 
-l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret,
-                                                int mask, StkId top) {
+l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nresults,
+                                                l_uint32 mask, StkId top) {
   CallInfo *ci = L->ci = next_ci(L);  /* new frame */
   ci->func.p = func;
-  ci->nresults = nret;
-  ci->callstatus = mask;
+  lua_assert(((nresults + 1) & ~CIST_NRESULTS) == 0);
+  ci->callstatus = mask | cast(l_uint32, nresults + 1);
   ci->top.p = top;
   return ci;
 }
@@ -664,7 +668,7 @@ l_sinline void ccall (lua_State *L, StkId func, int nResults, l_uint32 inc) {
     luaE_checkcstack(L);
   }
   if ((ci = luaD_precall(L, func, nResults)) != NULL) {  /* Lua function? */
-    ci->callstatus = CIST_FRESH;  /* mark that it is a "fresh" execute */
+    ci->callstatus |= CIST_FRESH;  /* mark that it is a "fresh" execute */
     luaV_execute(L, ci);  /* call it */
   }
   L->nCcalls -= inc;
@@ -709,7 +713,7 @@ static int finishpcallk (lua_State *L,  CallInfo *ci) {
     status = LUA_YIELD;  /* was interrupted by an yield */
   else {  /* error */
     StkId func = restorestack(L, ci->u2.funcidx);
-    L->allowhook = getoah(ci->callstatus);  /* restore 'allowhook' */
+    L->allowhook = getoah(ci);  /* restore 'allowhook' */
     func = luaF_close(L, func, status, 1);  /* can yield or raise an error */
     luaD_seterrorobj(L, status, func);
     luaD_shrinkstack(L);   /* restore stack size in case of overflow */

+ 0 - 1
lstate.c

@@ -177,7 +177,6 @@ static void stack_init (lua_State *L1, lua_State *L) {
   ci->callstatus = CIST_C;
   ci->func.p = L1->top.p;
   ci->u.c.k = NULL;
-  ci->nresults = 0;
   setnilvalue(s2v(L1->top.p));  /* 'function' entry for this 'ci' */
   L1->top.p++;
   ci->top.p = L1->top.p + LUA_MINSTACK;

+ 35 - 19
lstate.h

@@ -211,31 +211,45 @@ struct CallInfo {
       int ntransfer;  /* number of values transferred */
     } transferinfo;
   } u2;
-  short nresults;  /* expected number of results from this function */
-  unsigned short callstatus;
+  l_uint32 callstatus;
 };
 
 
 /*
 ** Bits in CallInfo status
 */
-#define CIST_OAH	(1<<0)	/* original value of 'allowhook' */
-#define CIST_C		(1<<1)	/* call is running a C function */
-#define CIST_FRESH	(1<<2)	/* call is on a fresh "luaV_execute" frame */
-#define CIST_HOOKED	(1<<3)	/* call is running a debug hook */
-#define CIST_YPCALL	(1<<4)	/* doing a yieldable protected call */
-#define CIST_TAIL	(1<<5)	/* call was tail called */
-#define CIST_HOOKYIELD	(1<<6)	/* last hook called yielded */
-#define CIST_FIN	(1<<7)	/* function "called" a finalizer */
-#define CIST_TRAN	(1<<8)	/* 'ci' has transfer information */
-#define CIST_CLSRET	(1<<9)  /* function is closing tbc variables */
-/* Bits 10-12 are used for CIST_RECST (see below) */
-#define CIST_RECST	10
+/* bits 0-7 are the expected number of results from this function + 1 */
+#define CIST_NRESULTS	0xff
+/* original value of 'allowhook' */
+#define CIST_OAH	(cast(l_uint32, 1) << 8)
+/* call is running a C function */
+#define CIST_C		(cast(l_uint32, 1) << 9)
+/* call is on a fresh "luaV_execute" frame */
+#define CIST_FRESH	(cast(l_uint32, 1) << 10)
+/* call is running a debug hook */
+#define CIST_HOOKED	(cast(l_uint32, 1) << 11)
+/* doing a yieldable protected call */
+#define CIST_YPCALL	(cast(l_uint32, 1) << 12)
+/* call was tail called */
+#define CIST_TAIL	(cast(l_uint32, 1) << 13)
+/* last hook called yielded */
+#define CIST_HOOKYIELD	(cast(l_uint32, 1) << 14)
+/* function "called" a finalizer */
+#define CIST_FIN	(cast(l_uint32, 1) << 15)
+/* 'ci' has transfer information */
+#define CIST_TRAN	(cast(l_uint32, 1) << 16)
+ /* function is closing tbc variables */
+#define CIST_CLSRET	(cast(l_uint32, 1) << 17)
+/* Bits 18-20 are used for CIST_RECST (see below) */
+#define CIST_RECST	18  /* the offset, not the mask */
 #if defined(LUA_COMPAT_LT_LE)
-#define CIST_LEQ	(1<<13)  /* using __lt for __le */
+/* using __lt for __le */
+#define CIST_LEQ	(cast(l_uint32, 1) << 21)
 #endif
 
 
+#define get_nresults(cs)  (cast_int((cs) & CIST_NRESULTS) - 1)
+
 /*
 ** Field CIST_RECST stores the "recover status", used to keep the error
 ** status while closing to-be-closed variables in coroutines, so that
@@ -246,7 +260,7 @@ struct CallInfo {
 #define setcistrecst(ci,st)  \
   check_exp(((st) & 7) == (st),   /* status must fit in three bits */  \
             ((ci)->callstatus = ((ci)->callstatus & ~(7 << CIST_RECST))  \
-                                                  | ((st) << CIST_RECST)))
+                                | (cast(l_uint32, st) << CIST_RECST)))
 
 
 /* active function is a Lua function */
@@ -255,9 +269,11 @@ struct CallInfo {
 /* call is running Lua code (not a hook) */
 #define isLuacode(ci)	(!((ci)->callstatus & (CIST_C | CIST_HOOKED)))
 
-/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */
-#define setoah(st,v)	((st) = ((st) & ~CIST_OAH) | (v))
-#define getoah(st)	((st) & CIST_OAH)
+
+#define setoah(ci,v)  \
+  ((ci)->callstatus = ((v) ? (ci)->callstatus | CIST_OAH  \
+                           : (ci)->callstatus & ~CIST_OAH))
+#define getoah(ci)  (((ci)->callstatus & CIST_OAH) ? 1 : 0)
 
 
 /*

+ 3 - 3
lvm.c

@@ -1742,10 +1742,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
           trap = 1;
         }
         else {  /* do the 'poscall' here */
-          int nres;
+          int nres = get_nresults(ci->callstatus);
           L->ci = ci->previous;  /* back to caller */
           L->top.p = base - 1;
-          for (nres = ci->nresults; l_unlikely(nres > 0); nres--)
+          for (; l_unlikely(nres > 0); nres--)
             setnilvalue(s2v(L->top.p++));  /* all results are nil */
         }
         goto ret;
@@ -1759,7 +1759,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
           trap = 1;
         }
         else {  /* do the 'poscall' here */
-          int nres = ci->nresults;
+          int nres = get_nresults(ci->callstatus);
           L->ci = ci->previous;  /* back to caller */
           if (nres == 0)
             L->top.p = base - 1;  /* asked for no results */