@ -157,16 +157,38 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
* * Stack reallocation
* * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
static void correctstack ( lua_State * L , StkId oldstack , StkId newstack ) {
/*
* * Change all pointers to the stack into offsets .
*/
static void relstack ( lua_State * L ) {
CallInfo * ci ;
UpVal * up ;
L - > top . offset = savestack ( L , L - > top . p ) ;
L - > tbclist . offset = savestack ( L , L - > tbclist . p ) ;
for ( up = L - > openupval ; up ! = NULL ; up = up - > u . open . next )
up - > v . offset = savestack ( L , uplevel ( up ) ) ;
for ( ci = L - > ci ; ci ! = NULL ; ci = ci - > previous ) {
ci - > top . offset = savestack ( L , ci - > top . p ) ;
ci - > func . offset = savestack ( L , ci - > func . p ) ;
}
}
/*
* * Change back all offsets into pointers .
*/
static void correctstack ( lua_State * L ) {
CallInfo * ci ;
UpVal * up ;
L - > top . p = ( L - > top . p - oldstack ) + newstack ;
L - > tbclist . p = ( L - > tbclist . p - oldstack ) + newstack ;
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 )
up - > v . p = s2v ( ( uplevel ( up ) - oldstack ) + newstack ) ;
up - > v . p = s2v ( restorestack ( L , up - > v . offset ) ) ;
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 ;
ci - > top . p = restorestack ( L , ci - > top . offset ) ;
ci - > func . p = restorestack ( L , ci - > func . offset ) ;
if ( isLua ( ci ) )
ci - > u . l . trap = 1 ; /* signal to update 'trap' in 'luaV_execute' */
}
@ -177,36 +199,38 @@ static void correctstack (lua_State *L, StkId oldstack, StkId newstack) {
# define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
/*
* * Reallocate the stack to a new size , correcting all pointers into
* * it . ( There are pointers to a stack from its upvalues , from its list
* * of call infos , plus a few individual pointers . ) The reallocation is
* * done in two steps ( allocation + free ) because the correction must be
* * done while both addresses ( the old stack and the new one ) are valid .
* * ( In ISO C , any pointer use after the pointer has been deallocated is
* * undefined behavior . )
* * 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 ' .
*/
int luaD_reallocstack ( lua_State * L , int newsize , int raiseerror ) {
int oldsize = stacksize ( L ) ;
int i ;
StkId newstack = luaM_reallocvector ( L , NULL , 0 ,
newsize + EXTRA_STACK , StackValue ) ;
StkId newstack ;
int oldgcstop = G ( L ) - > gcstopem ;
lua_assert ( newsize < = LUAI_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 ,
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 */
if ( raiseerror )
luaM_error ( L ) ;
else return 0 ; /* do not raise an error */
}
/* number of elements to be copied to the new stack */
i = ( ( oldsize < = newsize ) ? oldsize : newsize ) + EXTRA_STACK ;
memcpy ( newstack , L - > stack . p , i * sizeof ( StackValue ) ) ;
for ( ; i < newsize + EXTRA_STACK ; i + + )
setnilvalue ( s2v ( newstack + i ) ) ; /* erase new segment */
correctstack ( L , L - > stack . p , newstack ) ;
luaM_freearray ( L , L - > stack . p , oldsize + EXTRA_STACK ) ;
L - > stack . p = newstack ;
correctstack ( L ) ; /* 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 */
return 1 ;
}