From 5aa36e894f5a0348dfd19bd9cdcdd27ce8aa5f05 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 6 Oct 2020 15:50:24 -0300 Subject: [PATCH] No more field 'lua_State.stacksize' The stack size is derived from 'stack_last', when needed. Moreover, the handling of stack sizes is more consistent, always excluding the extra space except when allocating/deallocating the array. --- ldo.c | 19 +++++++++---------- lgc.c | 5 ++--- lstate.c | 8 +++----- lstate.h | 13 ++++++++++--- ltests.c | 8 ++++---- lvm.c | 2 +- 6 files changed, 29 insertions(+), 26 deletions(-) diff --git a/ldo.c b/ldo.c index 755db693..3202490e 100644 --- a/ldo.c +++ b/ldo.c @@ -182,10 +182,10 @@ static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { - int lim = L->stacksize; - StkId newstack = luaM_reallocvector(L, L->stack, lim, newsize, StackValue); + int lim = stacksize(L); + StkId newstack = luaM_reallocvector(L, L->stack, + lim + EXTRA_STACK, newsize + EXTRA_STACK, StackValue); lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); if (unlikely(newstack == NULL)) { /* reallocation failed? */ if (raiseerror) luaM_error(L); @@ -195,8 +195,7 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { setnilvalue(s2v(newstack + lim)); /* erase new segment */ correctstack(L, L->stack, newstack); L->stack = newstack; - L->stacksize = newsize; - L->stack_last = L->stack + newsize - EXTRA_STACK; + L->stack_last = L->stack + newsize; return 1; } @@ -206,19 +205,19 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { ** is true, raises any error; otherwise, return 0 in case of errors. */ int luaD_growstack (lua_State *L, int n, int raiseerror) { - int size = L->stacksize; + int size = stacksize(L); if (unlikely(size > LUAI_MAXSTACK)) { /* if stack is larger than maximum, thread is already using the extra space reserved for errors, that is, thread is handling a stack error; cannot grow further than that. */ - lua_assert(L->stacksize == ERRORSTACKSIZE); + lua_assert(stacksize(L) == ERRORSTACKSIZE); if (raiseerror) luaD_throw(L, LUA_ERRERR); /* error inside message handler */ return 0; /* if not 'raiseerror', just signal it */ } else { int newsize = 2 * size; /* tentative new size */ - int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; + int needed = cast_int(L->top - L->stack) + n; if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */ newsize = LUAI_MAXSTACK; if (newsize < needed) /* but must respect what was asked for */ @@ -257,7 +256,7 @@ static int stackinuse (lua_State *L) { ** previous size, and half of its entries are empty.) ** As a particular case, if stack was handling a stack overflow and now ** it is not, 'max' (limited by LUAI_MAXSTACK) will be smaller than -** 'stacksize' (equal to ERRORSTACKSIZE in this case), and so the stack +** stacksize (equal to ERRORSTACKSIZE in this case), and so the stack ** will be reduced to a "regular" size. */ void luaD_shrinkstack (lua_State *L) { @@ -271,7 +270,7 @@ void luaD_shrinkstack (lua_State *L) { } /* if thread is currently not handling a stack overflow and its size is larger than maximum "reasonable" size, shrink it */ - if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && L->stacksize > max) + if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) luaD_reallocstack(L, nsize, 0); /* ok if that fails */ else /* don't change stack */ condmovestack(L,{},{}); /* (change only for debugging) */ diff --git a/lgc.c b/lgc.c index 4a7bcaed..3b8d0ed6 100644 --- a/lgc.c +++ b/lgc.c @@ -633,8 +633,7 @@ static int traversethread (global_State *g, lua_State *th) { for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) markobject(g, uv); /* open upvalues cannot be collected */ if (g->gcstate == GCSatomic) { /* final traversal? */ - StkId lim = th->stack + th->stacksize; /* real end of stack */ - for (; o < lim; o++) /* clear not-marked stack slice */ + for (; o < th->stack_last; o++) /* clear not-marked stack slice */ setnilvalue(s2v(o)); /* 'remarkupvals' may have removed thread from 'twups' list */ if (!isintwups(th) && th->openupval != NULL) { @@ -644,7 +643,7 @@ static int traversethread (global_State *g, lua_State *th) { } else if (!g->gcemergency) luaD_shrinkstack(th); /* do not change stack in emergency cycle */ - return 1 + th->stacksize; + return 1 + stacksize(th); } diff --git a/lstate.c b/lstate.c index 13c1ff0f..76df6a20 100644 --- a/lstate.c +++ b/lstate.c @@ -180,12 +180,11 @@ LUAI_FUNC void luaE_incCstack (lua_State *L) { static void stack_init (lua_State *L1, lua_State *L) { int i; CallInfo *ci; /* initialize stack array */ - L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, StackValue); - L1->stacksize = BASIC_STACK_SIZE; + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); for (i = 0; i < BASIC_STACK_SIZE; i++) setnilvalue(s2v(L1->stack + i)); /* erase new stack */ L1->top = L1->stack; - L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; + L1->stack_last = L1->stack + BASIC_STACK_SIZE; /* initialize first ci */ ci = &L1->base_ci; ci->next = ci->previous = NULL; @@ -206,7 +205,7 @@ static void freestack (lua_State *L) { L->ci = &L->base_ci; /* free the entire 'ci' list */ luaE_freeCI(L); lua_assert(L->nci == 0); - luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ + luaM_freearray(L, L->stack, stacksize(L) + EXTRA_STACK); /* free stack */ } @@ -256,7 +255,6 @@ static void preinit_thread (lua_State *L, global_State *g) { L->stack = NULL; L->ci = NULL; L->nci = 0; - L->stacksize = 0; L->twups = L; /* thread has no upvalues */ L->errorJmp = NULL; L->hook = NULL; diff --git a/lstate.h b/lstate.h index 5573898c..cbcf07e2 100644 --- a/lstate.h +++ b/lstate.h @@ -127,12 +127,20 @@ struct lua_longjmp; /* defined in ldo.c */ #endif -/* extra stack space to handle TM calls and some other extras */ +/* +** Extra stack space to handle TM calls and some other extras. This +** space is not included in 'stack_last'. It is used only to avoid stack +** checks, either because the element will be promptly popped or because +** there will be a stack check soon after the push. Function frames +** never use this extra space, so it does not need to be kept clean. +*/ #define EXTRA_STACK 5 #define BASIC_STACK_SIZE (2*LUA_MINSTACK) +#define stacksize(th) cast_int((th)->stack_last - (th)->stack) + /* kinds of Garbage Collection */ #define KGC_INC 0 /* incremental gc */ @@ -270,7 +278,7 @@ struct lua_State { StkId top; /* first free slot in the stack */ global_State *l_G; CallInfo *ci; /* call info for current function */ - StkId stack_last; /* last free slot in the stack */ + StkId stack_last; /* end of stack (last element + 1) */ StkId stack; /* stack base */ UpVal *openupval; /* list of open upvalues in this stack */ GCObject *gclist; @@ -281,7 +289,6 @@ struct lua_State { ptrdiff_t errfunc; /* current error handling function (stack index) */ l_uint32 nCcalls; /* number of nested (non-yieldable | C) calls */ int oldpc; /* last pc traced */ - int stacksize; int basehookcount; int hookcount; volatile l_signalT hookmask; diff --git a/ltests.c b/ltests.c index 04e8a00a..99456159 100644 --- a/ltests.c +++ b/ltests.c @@ -430,17 +430,17 @@ static void checkstack (global_State *g, lua_State *L1) { UpVal *uv; lua_assert(!isdead(g, L1)); if (L1->stack == NULL) { /* incomplete thread? */ - lua_assert(L1->stacksize == 0 && L1->openupval == NULL && - L1->ci == NULL); + lua_assert(L1->openupval == NULL && L1->ci == NULL); return; } for (uv = L1->openupval; uv != NULL; uv = uv->u.open.next) lua_assert(upisopen(uv)); /* must be open */ + lua_assert(L1->top <= L1->stack_last); for (ci = L1->ci; ci != NULL; ci = ci->previous) { lua_assert(ci->top <= L1->stack_last); lua_assert(lua_checkpc(ci)); } - for (o = L1->stack; o < L1->stack_last + EXTRA_STACK; o++) + for (o = L1->stack; o < L1->stack_last; o++) checkliveness(L1, s2v(o)); /* entire stack must have valid values */ } @@ -969,7 +969,7 @@ static int hash_query (lua_State *L) { static int stacklevel (lua_State *L) { unsigned long a = 0; lua_pushinteger(L, (L->top - L->stack)); - lua_pushinteger(L, (L->stack_last - L->stack)); + lua_pushinteger(L, stacksize(L)); lua_pushinteger(L, L->nCcalls); lua_pushinteger(L, L->nci); lua_pushinteger(L, (unsigned long)&a); diff --git a/lvm.c b/lvm.c index 51b22d81..72d3e695 100644 --- a/lvm.c +++ b/lvm.c @@ -1151,7 +1151,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { StkId ra; /* instruction's A register */ vmfetch(); lua_assert(base == ci->func + 1); - lua_assert(base <= L->top && L->top < L->stack + L->stacksize); + lua_assert(base <= L->top && L->top < L->stack_last); /* invalidate top for instructions not expecting it */ lua_assert(isIT(i) || (cast_void(L->top = base), 1)); vmdispatch (GET_OPCODE(i)) {