small changes to allow 'precall' to spend time preserving 'func'

only when needed (that is, when stack actually changes)
This commit is contained in:
Roberto Ierusalimschy 2015-10-21 16:40:47 -02:00
parent 48098c42ff
commit 5bdee4f810
3 changed files with 42 additions and 28 deletions

40
ldo.c
View File

@ -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 */
}

17
ldo.h
View File

@ -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);}

View File

@ -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