aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-07-07 18:03:48 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-07-07 18:03:48 -0300
commiteb41999461b6f428186c55abd95f4ce1a76217d5 (patch)
tree577e56c4ad5999b34966232b1e2a2bf9a63f7cc2
parent314c6057b785cd94ac88905ccfce61724107d66b (diff)
downloadlua-eb41999461b6f428186c55abd95f4ce1a76217d5.tar.gz
lua-eb41999461b6f428186c55abd95f4ce1a76217d5.tar.bz2
lua-eb41999461b6f428186c55abd95f4ce1a76217d5.zip
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.)
-rw-r--r--ldo.c13
-rw-r--r--ldo.h6
-rw-r--r--ltm.c4
-rw-r--r--lvm.c2
4 files changed, 14 insertions, 11 deletions
diff --git a/ldo.c b/ldo.c
index 66217a4b..e3db1f74 100644
--- a/ldo.c
+++ b/ldo.c
@@ -465,13 +465,13 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
465 f = fvalue(s2v(func)); 465 f = fvalue(s2v(func));
466 Cfunc: { 466 Cfunc: {
467 int n; /* number of returns */ 467 int n; /* number of returns */
468 CallInfo *ci = next_ci(L); 468 CallInfo *ci;
469 checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ 469 checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
470 L->ci = ci = next_ci(L);
470 ci->nresults = nresults; 471 ci->nresults = nresults;
471 ci->callstatus = CIST_C; 472 ci->callstatus = CIST_C;
472 ci->top = L->top + LUA_MINSTACK; 473 ci->top = L->top + LUA_MINSTACK;
473 ci->func = func; 474 ci->func = func;
474 L->ci = ci;
475 lua_assert(ci->top <= L->stack_last); 475 lua_assert(ci->top <= L->stack_last);
476 if (L->hookmask & LUA_MASKCALL) { 476 if (L->hookmask & LUA_MASKCALL) {
477 int narg = cast_int(L->top - func) - 1; 477 int narg = cast_int(L->top - func) - 1;
@@ -485,12 +485,13 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
485 break; 485 break;
486 } 486 }
487 case LUA_VLCL: { /* Lua function */ 487 case LUA_VLCL: { /* Lua function */
488 CallInfo *ci = next_ci(L); 488 CallInfo *ci;
489 Proto *p = clLvalue(s2v(func))->p; 489 Proto *p = clLvalue(s2v(func))->p;
490 int narg = cast_int(L->top - func) - 1; /* number of real arguments */ 490 int narg = cast_int(L->top - func) - 1; /* number of real arguments */
491 int nfixparams = p->numparams; 491 int nfixparams = p->numparams;
492 int fsize = p->maxstacksize; /* frame size */ 492 int fsize = p->maxstacksize; /* frame size */
493 checkstackp(L, fsize, func); 493 checkstackGCp(L, fsize, func);
494 L->ci = ci = next_ci(L);
494 ci->nresults = nresults; 495 ci->nresults = nresults;
495 ci->u.l.savedpc = p->code; /* starting point */ 496 ci->u.l.savedpc = p->code; /* starting point */
496 ci->callstatus = 0; 497 ci->callstatus = 0;
@@ -504,7 +505,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
504 break; 505 break;
505 } 506 }
506 default: { /* not a function */ 507 default: { /* not a function */
507 checkstackp(L, 1, func); /* space for metamethod */ 508 checkstackGCp(L, 1, func); /* space for metamethod */
508 luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ 509 luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */
509 goto retry; /* try again with metamethod */ 510 goto retry; /* try again with metamethod */
510 } 511 }
diff --git a/ldo.h b/ldo.h
index 7760f853..6c6cb285 100644
--- a/ldo.h
+++ b/ldo.h
@@ -17,6 +17,8 @@
17** Macro to check stack size and grow stack if needed. Parameters 17** Macro to check stack size and grow stack if needed. Parameters
18** 'pre'/'pos' allow the macro to preserve a pointer into the 18** 'pre'/'pos' allow the macro to preserve a pointer into the
19** stack across reallocations, doing the work only when needed. 19** stack across reallocations, doing the work only when needed.
20** It also allows the running of one GC step when the stack is
21** reallocated.
20** 'condmovestack' is used in heavy tests to force a stack reallocation 22** 'condmovestack' is used in heavy tests to force a stack reallocation
21** at every check. 23** at every check.
22*/ 24*/
@@ -35,7 +37,7 @@
35 37
36 38
37/* macro to check stack size, preserving 'p' */ 39/* macro to check stack size, preserving 'p' */
38#define checkstackp(L,n,p) \ 40#define checkstackGCp(L,n,p) \
39 luaD_checkstackaux(L, n, \ 41 luaD_checkstackaux(L, n, \
40 ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ 42 ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \
41 luaC_checkGC(L), /* stack grow uses memory */ \ 43 luaC_checkGC(L), /* stack grow uses memory */ \
@@ -44,7 +46,7 @@
44 46
45/* macro to check stack size and GC */ 47/* macro to check stack size and GC */
46#define checkstackGC(L,fsize) \ 48#define checkstackGC(L,fsize) \
47 luaD_checkstackaux(L, (fsize), (void)0, luaC_checkGC(L)) 49 luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0)
48 50
49 51
50/* type of protected functions, to be ran by 'runprotected' */ 52/* type of protected functions, to be ran by 'runprotected' */
diff --git a/ltm.c b/ltm.c
index ae60983f..4770f96b 100644
--- a/ltm.c
+++ b/ltm.c
@@ -240,7 +240,7 @@ void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci,
240 int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */ 240 int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */
241 int nextra = actual - nfixparams; /* number of extra arguments */ 241 int nextra = actual - nfixparams; /* number of extra arguments */
242 ci->u.l.nextraargs = nextra; 242 ci->u.l.nextraargs = nextra;
243 checkstackGC(L, p->maxstacksize + 1); 243 luaD_checkstack(L, p->maxstacksize + 1);
244 /* copy function to the top of the stack */ 244 /* copy function to the top of the stack */
245 setobjs2s(L, L->top++, ci->func); 245 setobjs2s(L, L->top++, ci->func);
246 /* move fixed parameters to the top of the stack */ 246 /* 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) {
259 int nextra = ci->u.l.nextraargs; 259 int nextra = ci->u.l.nextraargs;
260 if (wanted < 0) { 260 if (wanted < 0) {
261 wanted = nextra; /* get all extra arguments available */ 261 wanted = nextra; /* get all extra arguments available */
262 checkstackp(L, nextra, where); /* ensure stack space */ 262 checkstackGCp(L, nextra, where); /* ensure stack space */
263 L->top = where + nextra; /* next instruction will need top */ 263 L->top = where + nextra; /* next instruction will need top */
264 } 264 }
265 for (i = 0; i < wanted && i < nextra; i++) 265 for (i = 0; i < wanted && i < nextra; i++)
diff --git a/lvm.c b/lvm.c
index ccbfbab5..d78d6be2 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1634,7 +1634,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1634 while (!ttisfunction(s2v(ra))) { /* not a function? */ 1634 while (!ttisfunction(s2v(ra))) { /* not a function? */
1635 luaD_tryfuncTM(L, ra); /* try '__call' metamethod */ 1635 luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
1636 b++; /* there is now one extra argument */ 1636 b++; /* there is now one extra argument */
1637 checkstackp(L, 1, ra); 1637 checkstackGCp(L, 1, ra);
1638 } 1638 }
1639 if (!ttisLclosure(s2v(ra))) { /* C function? */ 1639 if (!ttisLclosure(s2v(ra))) { /* C function? */
1640 luaD_call(L, ra, LUA_MULTRET); /* call it */ 1640 luaD_call(L, ra, LUA_MULTRET); /* call it */