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