mirror of https://github.com/lua/lua
Added option for direct correction of stack pointers
The use of a pointer (not access, only for computations) after its deallocation is forbiden in ISO C, but seems to work fine in all platforms we are aware of. So, using that to correct stack pointers after a stack reallocation seems safe and is much simpler than the current implementation (first change all pointers to offsets and then changing the offsets back to pointers). Anyway, for now that option is disabled.
This commit is contained in:
parent
75620b45ae
commit
fd0e1f530d
54
ldo.c
54
ldo.c
|
@ -190,6 +190,16 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
|
|||
#define ERRORSTACKSIZE (MAXSTACK + STACKERRSPACE)
|
||||
|
||||
|
||||
/*
|
||||
** In ISO C, any pointer use after the pointer has been deallocated is
|
||||
** undefined behavior. So, before a stack reallocation, all pointers are
|
||||
** changed to offsets, and after the reallocation they are changed back
|
||||
** to pointers. As during the reallocation the pointers are invalid, the
|
||||
** reallocation cannot run emergency collections.
|
||||
**
|
||||
*/
|
||||
|
||||
#if 1
|
||||
/*
|
||||
** Change all pointers to the stack into offsets.
|
||||
*/
|
||||
|
@ -210,9 +220,10 @@ static void relstack (lua_State *L) {
|
|||
/*
|
||||
** Change back all offsets into pointers.
|
||||
*/
|
||||
static void correctstack (lua_State *L) {
|
||||
static void correctstack (lua_State *L, StkId oldstack) {
|
||||
CallInfo *ci;
|
||||
UpVal *up;
|
||||
UNUSED(oldstack);
|
||||
L->top.p = restorestack(L, L->top.offset);
|
||||
L->tbclist.p = restorestack(L, L->tbclist.offset);
|
||||
for (up = L->openupval; up != NULL; up = up->u.open.next)
|
||||
|
@ -225,15 +236,37 @@ static void correctstack (lua_State *L) {
|
|||
}
|
||||
}
|
||||
|
||||
#else
|
||||
/*
|
||||
** Alternatively, we can use the old address after the dealocation.
|
||||
** That is not strict ISO C, but seems to work fine everywhere.
|
||||
*/
|
||||
|
||||
static void relstack (lua_State *L) { UNUSED(L); }
|
||||
|
||||
static void correctstack (lua_State *L, StkId oldstack) {
|
||||
CallInfo *ci;
|
||||
UpVal *up;
|
||||
StkId newstack = L->stack.p;
|
||||
if (oldstack == newstack)
|
||||
return;
|
||||
L->top.p = L->top.p - oldstack + newstack;
|
||||
L->tbclist.p = L->tbclist.p - oldstack + newstack;
|
||||
for (up = L->openupval; up != NULL; up = up->u.open.next)
|
||||
up->v.p = s2v(uplevel(up) - oldstack + newstack);
|
||||
for (ci = L->ci; ci != NULL; ci = ci->previous) {
|
||||
ci->top.p = ci->top.p - oldstack + newstack;
|
||||
ci->func.p = ci->func.p - oldstack + newstack;
|
||||
if (isLua(ci))
|
||||
ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Reallocate the stack to a new size, correcting all pointers into it.
|
||||
** In ISO C, any pointer use after the pointer has been deallocated is
|
||||
** undefined behavior. So, before the reallocation, all pointers are
|
||||
** changed to offsets, and after the reallocation they are changed back
|
||||
** to pointers. As during the reallocation the pointers are invalid, the
|
||||
** reallocation cannot run emergency collections.
|
||||
**
|
||||
** In case of allocation error, raise an error or return false according
|
||||
** to 'raiseerror'.
|
||||
*/
|
||||
|
@ -241,21 +274,22 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
|
|||
int oldsize = stacksize(L);
|
||||
int i;
|
||||
StkId newstack;
|
||||
StkId oldstack = L->stack.p;
|
||||
lu_byte oldgcstop = G(L)->gcstopem;
|
||||
lua_assert(newsize <= MAXSTACK || newsize == ERRORSTACKSIZE);
|
||||
relstack(L); /* change pointers to offsets */
|
||||
G(L)->gcstopem = 1; /* stop emergency collection */
|
||||
newstack = luaM_reallocvector(L, L->stack.p, oldsize + EXTRA_STACK,
|
||||
newstack = luaM_reallocvector(L, oldstack, oldsize + EXTRA_STACK,
|
||||
newsize + EXTRA_STACK, StackValue);
|
||||
G(L)->gcstopem = oldgcstop; /* restore emergency collection */
|
||||
if (l_unlikely(newstack == NULL)) { /* reallocation failed? */
|
||||
correctstack(L); /* change offsets back to pointers */
|
||||
correctstack(L, oldstack); /* change offsets back to pointers */
|
||||
if (raiseerror)
|
||||
luaM_error(L);
|
||||
else return 0; /* do not raise an error */
|
||||
}
|
||||
L->stack.p = newstack;
|
||||
correctstack(L); /* change offsets back to pointers */
|
||||
correctstack(L, oldstack); /* change offsets back to pointers */
|
||||
L->stack_last.p = L->stack.p + newsize;
|
||||
for (i = oldsize + EXTRA_STACK; i < newsize + EXTRA_STACK; i++)
|
||||
setnilvalue(s2v(newstack + i)); /* erase new segment */
|
||||
|
|
Loading…
Reference in New Issue