فهرست منبع

small changes to allow 'precall' to spend time preserving 'func'
only when needed (that is, when stack actually changes)

Roberto Ierusalimschy 10 سال پیش
والد
کامیت
5bdee4f810
3فایلهای تغییر یافته به همراه42 افزوده شده و 28 حذف شده
  1. 21 19
      ldo.c
  2. 14 3
      ldo.h
  3. 7 6
      llimits.h

+ 21 - 19
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.139 2015/06/18 14:19:52 roberto Exp roberto $
+** $Id: ldo.c,v 2.140 2015/09/08 15:41:05 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -221,11 +221,11 @@ void luaD_shrinkstack (lua_State *L) {
     luaE_freeCI(L);  /* free all CIs (list grew because of an error) */
   else
     luaE_shrinkCI(L);  /* shrink list */
-  if (inuse > LUAI_MAXSTACK ||  /* still handling stack overflow? */
-      goodsize >= L->stacksize)  /* would grow instead of shrink? */
-    condmovestack(L);  /* don't change stack (change only for debugging) */
-  else
+  if (inuse <= LUAI_MAXSTACK &&  /* not handling stack overflow? */
+      goodsize < L->stacksize)  /* trying to shrink? */
     luaD_reallocstack(L, goodsize);  /* shrink it */
+  else
+    condmovestack(L,,);  /* don't change stack (change only for debugging) */
 }
 
 
@@ -308,6 +308,13 @@ static void tryfuncTM (lua_State *L, StkId func) {
 #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
 
 
+/* macro to check stack size, preserving 'p' */
+#define checkstackp(L,n,p)  \
+  luaD_checkstackaux(L, n, \
+    ptrdiff_t t__ = savestack(L, p);  /* save 'p' */ \
+    luaC_checkGC(L),  /* stack grow uses memory */ \
+    p = restorestack(L, t__))  /* 'pos' part: restore 'p' */
+
 /*
 ** returns true if function has been executed (C function)
 */
@@ -315,19 +322,17 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
   lua_CFunction f;
   CallInfo *ci;
   int n;  /* number of arguments (Lua) or returns (C) */
-  ptrdiff_t funcr = savestack(L, func);
   switch (ttype(func)) {
-    case LUA_TLCF:  /* light C function */
-      f = fvalue(func);
-      goto Cfunc;
     case LUA_TCCL: {  /* C closure */
       f = clCvalue(func)->f;
+      goto Cfunc;
+    case LUA_TLCF:  /* light C function */
+      f = fvalue(func);
      Cfunc:
-      luaC_checkGC(L);  /* stack grow uses memory */
-      luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
+      checkstackp(L, LUA_MINSTACK, func);  /* ensure minimum stack size */
       ci = next_ci(L);  /* now 'enter' new function */
       ci->nresults = nresults;
-      ci->func = restorestack(L, funcr);
+      ci->func = func;
       ci->top = L->top + LUA_MINSTACK;
       lua_assert(ci->top <= L->stack_last);
       ci->callstatus = 0;
@@ -344,15 +349,13 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
       StkId base;
       Proto *p = clLvalue(func)->p;
       n = cast_int(L->top - func) - 1;  /* number of real arguments */
-      luaC_checkGC(L);  /* stack grow uses memory */
-      luaD_checkstack(L, p->maxstacksize);
+      checkstackp(L, p->maxstacksize, func);
       for (; n < p->numparams; n++)
         setnilvalue(L->top++);  /* complete missing arguments */
-      if (!p->is_vararg) {
-        func = restorestack(L, funcr);
+      if (!p->is_vararg)
         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 */
       }
@@ -370,8 +373,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
       return 0;
     }
     default: {  /* not a function */
-      luaD_checkstack(L, 1);  /* ensure space for metamethod */
-      func = restorestack(L, funcr);  /* previous call may change stack */
+      checkstackp(L, 1, func);  /* ensure space for metamethod */
       tryfuncTM(L, func);  /* try to get '__call' metamethod */
       return luaD_precall(L, func, nresults);  /* now it must be a function */
     }

+ 14 - 3
ldo.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 2.21 2014/10/25 11:50:46 roberto Exp roberto $
+** $Id: ldo.h,v 2.22 2015/05/22 17:48:19 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -13,8 +13,19 @@
 #include "lzio.h"
 
 
-#define luaD_checkstack(L,n)	if (L->stack_last - L->top <= (n)) \
-				    luaD_growstack(L, n); else condmovestack(L);
+/*
+** Macro to check stack size and grow stack if needed.  Parameters
+** 'pre'/'pos' allow the macro to preserve a pointer into the
+** stack across realalocations, doing the work only when needed.
+** 'condmovestack' is used in heavy tests to force a stack reallocation
+** at every check.
+*/
+#define luaD_checkstackaux(L,n,pre,pos)  \
+	if (L->stack_last - L->top <= (n)) \
+	  { pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); }
+
+/* In general, 'pre'/'pos' are empty (nothing to save) */
+#define luaD_checkstack(L,n)	luaD_checkstackaux(L,n,,)
 
 
 #define incr_top(L) {L->top++; luaD_checkstack(L,0);}

+ 7 - 6
llimits.h

@@ -1,5 +1,5 @@
 /*
-** $Id: llimits.h,v 1.138 2015/09/22 14:18:24 roberto Exp roberto $
+** $Id: llimits.h,v 1.139 2015/10/06 14:29:49 roberto Exp roberto $
 ** Limits, basic types, and some other 'installation-dependent' definitions
 ** See Copyright Notice in lua.h
 */
@@ -306,17 +306,18 @@ typedef unsigned long Instruction;
 ** macro to control inclusion of some hard tests on stack reallocation
 */
 #if !defined(HARDSTACKTESTS)
-#define condmovestack(L)	((void)0)
+#define condmovestack(L,pre,pos)	((void)0)
 #else
 /* realloc stack keeping its size */
-#define condmovestack(L)	luaD_reallocstack((L), (L)->stacksize)
+#define condmovestack(L,pre,pos)  \
+	{ int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_); pos; }
 #endif
 
 #if !defined(HARDMEMTESTS)
-#define condchangemem(L)	condmovestack(L)
+#define condchangemem(L,pre,pos)	((void)0)
 #else
-#define condchangemem(L)  \
-	((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1)))
+#define condchangemem(L,pre,pos)  \
+	{ if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } }
 #endif
 
 #endif