Fixed bugs of stack reallocation x GC

Macro 'checkstackGC' was doing a GC step after resizing the stack;
the GC could shrink the stack and undo the resize. Moreover, macro
'checkstackp' also does a GC step, which could remove the preallocated
CallInfo when calling a function. (Its name has been changed to
'checkstackGCp' to emphasize that it calls the GC.)
This commit is contained in:
Roberto Ierusalimschy 2020-07-07 18:03:48 -03:00
parent 314c6057b7
commit eb41999461
4 changed files with 14 additions and 11 deletions

13
ldo.c
View File

@ -465,13 +465,13 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
f = fvalue(s2v(func)); f = fvalue(s2v(func));
Cfunc: { Cfunc: {
int n; /* number of returns */ int n; /* number of returns */
CallInfo *ci = next_ci(L); CallInfo *ci;
checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
L->ci = ci = next_ci(L);
ci->nresults = nresults; ci->nresults = nresults;
ci->callstatus = CIST_C; ci->callstatus = CIST_C;
ci->top = L->top + LUA_MINSTACK; ci->top = L->top + LUA_MINSTACK;
ci->func = func; ci->func = func;
L->ci = ci;
lua_assert(ci->top <= L->stack_last); lua_assert(ci->top <= L->stack_last);
if (L->hookmask & LUA_MASKCALL) { if (L->hookmask & LUA_MASKCALL) {
int narg = cast_int(L->top - func) - 1; int narg = cast_int(L->top - func) - 1;
@ -485,12 +485,13 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
break; break;
} }
case LUA_VLCL: { /* Lua function */ case LUA_VLCL: { /* Lua function */
CallInfo *ci = next_ci(L); CallInfo *ci;
Proto *p = clLvalue(s2v(func))->p; Proto *p = clLvalue(s2v(func))->p;
int narg = cast_int(L->top - func) - 1; /* number of real arguments */ int narg = cast_int(L->top - func) - 1; /* number of real arguments */
int nfixparams = p->numparams; int nfixparams = p->numparams;
int fsize = p->maxstacksize; /* frame size */ int fsize = p->maxstacksize; /* frame size */
checkstackp(L, fsize, func); checkstackGCp(L, fsize, func);
L->ci = ci = next_ci(L);
ci->nresults = nresults; ci->nresults = nresults;
ci->u.l.savedpc = p->code; /* starting point */ ci->u.l.savedpc = p->code; /* starting point */
ci->callstatus = 0; ci->callstatus = 0;
@ -504,7 +505,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
break; break;
} }
default: { /* not a function */ default: { /* not a function */
checkstackp(L, 1, func); /* space for metamethod */ checkstackGCp(L, 1, func); /* space for metamethod */
luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
goto retry; /* try again with metamethod */ goto retry; /* try again with metamethod */
} }

6
ldo.h
View File

@ -17,6 +17,8 @@
** Macro to check stack size and grow stack if needed. Parameters ** Macro to check stack size and grow stack if needed. Parameters
** 'pre'/'pos' allow the macro to preserve a pointer into the ** 'pre'/'pos' allow the macro to preserve a pointer into the
** stack across reallocations, doing the work only when needed. ** stack across reallocations, doing the work only when needed.
** It also allows the running of one GC step when the stack is
** reallocated.
** 'condmovestack' is used in heavy tests to force a stack reallocation ** 'condmovestack' is used in heavy tests to force a stack reallocation
** at every check. ** at every check.
*/ */
@ -35,7 +37,7 @@
/* macro to check stack size, preserving 'p' */ /* macro to check stack size, preserving 'p' */
#define checkstackp(L,n,p) \ #define checkstackGCp(L,n,p) \
luaD_checkstackaux(L, n, \ luaD_checkstackaux(L, n, \
ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \
luaC_checkGC(L), /* stack grow uses memory */ \ luaC_checkGC(L), /* stack grow uses memory */ \
@ -44,7 +46,7 @@
/* macro to check stack size and GC */ /* macro to check stack size and GC */
#define checkstackGC(L,fsize) \ #define checkstackGC(L,fsize) \
luaD_checkstackaux(L, (fsize), (void)0, luaC_checkGC(L)) luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0)
/* type of protected functions, to be ran by 'runprotected' */ /* type of protected functions, to be ran by 'runprotected' */

4
ltm.c
View File

@ -240,7 +240,7 @@ void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci,
int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */ int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */
int nextra = actual - nfixparams; /* number of extra arguments */ int nextra = actual - nfixparams; /* number of extra arguments */
ci->u.l.nextraargs = nextra; ci->u.l.nextraargs = nextra;
checkstackGC(L, p->maxstacksize + 1); luaD_checkstack(L, p->maxstacksize + 1);
/* copy function to the top of the stack */ /* copy function to the top of the stack */
setobjs2s(L, L->top++, ci->func); setobjs2s(L, L->top++, ci->func);
/* move fixed parameters to the top of the stack */ /* move fixed parameters to the top of the stack */
@ -259,7 +259,7 @@ void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) {
int nextra = ci->u.l.nextraargs; int nextra = ci->u.l.nextraargs;
if (wanted < 0) { if (wanted < 0) {
wanted = nextra; /* get all extra arguments available */ wanted = nextra; /* get all extra arguments available */
checkstackp(L, nextra, where); /* ensure stack space */ checkstackGCp(L, nextra, where); /* ensure stack space */
L->top = where + nextra; /* next instruction will need top */ L->top = where + nextra; /* next instruction will need top */
} }
for (i = 0; i < wanted && i < nextra; i++) for (i = 0; i < wanted && i < nextra; i++)

2
lvm.c
View File

@ -1634,7 +1634,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
while (!ttisfunction(s2v(ra))) { /* not a function? */ while (!ttisfunction(s2v(ra))) { /* not a function? */
luaD_tryfuncTM(L, ra); /* try '__call' metamethod */ luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
b++; /* there is now one extra argument */ b++; /* there is now one extra argument */
checkstackp(L, 1, ra); checkstackGCp(L, 1, ra);
} }
if (!ttisLclosure(s2v(ra))) { /* C function? */ if (!ttisLclosure(s2v(ra))) { /* C function? */
luaD_call(L, ra, LUA_MULTRET); /* call it */ luaD_call(L, ra, LUA_MULTRET); /* call it */