Преглед на файлове

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

Roberto Ierusalimschy преди 9 години
родител
ревизия
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