diff options
| -rw-r--r-- | ldo.c | 68 | ||||
| -rw-r--r-- | lobject.h | 6 |
2 files changed, 52 insertions, 22 deletions
| @@ -157,16 +157,38 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |||
| 157 | ** Stack reallocation | 157 | ** Stack reallocation |
| 158 | ** =================================================================== | 158 | ** =================================================================== |
| 159 | */ | 159 | */ |
| 160 | static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { | 160 | |
| 161 | |||
| 162 | /* | ||
| 163 | ** Change all pointers to the stack into offsets. | ||
| 164 | */ | ||
| 165 | static void relstack (lua_State *L) { | ||
| 166 | CallInfo *ci; | ||
| 167 | UpVal *up; | ||
| 168 | L->top.offset = savestack(L, L->top.p); | ||
| 169 | L->tbclist.offset = savestack(L, L->tbclist.p); | ||
| 170 | for (up = L->openupval; up != NULL; up = up->u.open.next) | ||
| 171 | up->v.offset = savestack(L, uplevel(up)); | ||
| 172 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | ||
| 173 | ci->top.offset = savestack(L, ci->top.p); | ||
| 174 | ci->func.offset = savestack(L, ci->func.p); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | |||
| 179 | /* | ||
| 180 | ** Change back all offsets into pointers. | ||
| 181 | */ | ||
| 182 | static void correctstack (lua_State *L) { | ||
| 161 | CallInfo *ci; | 183 | CallInfo *ci; |
| 162 | UpVal *up; | 184 | UpVal *up; |
| 163 | L->top.p = (L->top.p - oldstack) + newstack; | 185 | L->top.p = restorestack(L, L->top.offset); |
| 164 | L->tbclist.p = (L->tbclist.p - oldstack) + newstack; | 186 | L->tbclist.p = restorestack(L, L->tbclist.offset); |
| 165 | for (up = L->openupval; up != NULL; up = up->u.open.next) | 187 | for (up = L->openupval; up != NULL; up = up->u.open.next) |
| 166 | up->v.p = s2v((uplevel(up) - oldstack) + newstack); | 188 | up->v.p = s2v(restorestack(L, up->v.offset)); |
| 167 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | 189 | for (ci = L->ci; ci != NULL; ci = ci->previous) { |
| 168 | ci->top.p = (ci->top.p - oldstack) + newstack; | 190 | ci->top.p = restorestack(L, ci->top.offset); |
| 169 | ci->func.p = (ci->func.p - oldstack) + newstack; | 191 | ci->func.p = restorestack(L, ci->func.offset); |
| 170 | if (isLua(ci)) | 192 | if (isLua(ci)) |
| 171 | ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ | 193 | ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ |
| 172 | } | 194 | } |
| @@ -177,36 +199,38 @@ static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { | |||
| 177 | #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) | 199 | #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) |
| 178 | 200 | ||
| 179 | /* | 201 | /* |
| 180 | ** Reallocate the stack to a new size, correcting all pointers into | 202 | ** Reallocate the stack to a new size, correcting all pointers into it. |
| 181 | ** it. (There are pointers to a stack from its upvalues, from its list | 203 | ** In ISO C, any pointer use after the pointer has been deallocated is |
| 182 | ** of call infos, plus a few individual pointers.) The reallocation is | 204 | ** undefined behavior. So, before the reallocation, all pointers are |
| 183 | ** done in two steps (allocation + free) because the correction must be | 205 | ** changed to offsets, and after the reallocation they are changed back |
| 184 | ** done while both addresses (the old stack and the new one) are valid. | 206 | ** to pointers. As during the reallocation the pointers are invalid, the |
| 185 | ** (In ISO C, any pointer use after the pointer has been deallocated is | 207 | ** reallocation cannot run emergency collections. |
| 186 | ** undefined behavior.) | 208 | ** |
| 187 | ** In case of allocation error, raise an error or return false according | 209 | ** In case of allocation error, raise an error or return false according |
| 188 | ** to 'raiseerror'. | 210 | ** to 'raiseerror'. |
| 189 | */ | 211 | */ |
| 190 | int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { | 212 | int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { |
| 191 | int oldsize = stacksize(L); | 213 | int oldsize = stacksize(L); |
| 192 | int i; | 214 | int i; |
| 193 | StkId newstack = luaM_reallocvector(L, NULL, 0, | 215 | StkId newstack; |
| 194 | newsize + EXTRA_STACK, StackValue); | 216 | int oldgcstop = G(L)->gcstopem; |
| 195 | lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); | 217 | lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); |
| 218 | relstack(L); /* change pointers to offsets */ | ||
| 219 | G(L)->gcstopem = 1; /* stop emergency collection */ | ||
| 220 | newstack = luaM_reallocvector(L, L->stack.p, oldsize + EXTRA_STACK, | ||
| 221 | newsize + EXTRA_STACK, StackValue); | ||
| 222 | G(L)->gcstopem = oldgcstop; /* restore emergency collection */ | ||
| 196 | if (l_unlikely(newstack == NULL)) { /* reallocation failed? */ | 223 | if (l_unlikely(newstack == NULL)) { /* reallocation failed? */ |
| 224 | correctstack(L); /* change offsets back to pointers */ | ||
| 197 | if (raiseerror) | 225 | if (raiseerror) |
| 198 | luaM_error(L); | 226 | luaM_error(L); |
| 199 | else return 0; /* do not raise an error */ | 227 | else return 0; /* do not raise an error */ |
| 200 | } | 228 | } |
| 201 | /* number of elements to be copied to the new stack */ | ||
| 202 | i = ((oldsize <= newsize) ? oldsize : newsize) + EXTRA_STACK; | ||
| 203 | memcpy(newstack, L->stack.p, i * sizeof(StackValue)); | ||
| 204 | for (; i < newsize + EXTRA_STACK; i++) | ||
| 205 | setnilvalue(s2v(newstack + i)); /* erase new segment */ | ||
| 206 | correctstack(L, L->stack.p, newstack); | ||
| 207 | luaM_freearray(L, L->stack.p, oldsize + EXTRA_STACK); | ||
| 208 | L->stack.p = newstack; | 229 | L->stack.p = newstack; |
| 230 | correctstack(L); /* change offsets back to pointers */ | ||
| 209 | L->stack_last.p = L->stack.p + newsize; | 231 | L->stack_last.p = L->stack.p + newsize; |
| 232 | for (i = oldsize + EXTRA_STACK; i < newsize + EXTRA_STACK; i++) | ||
| 233 | setnilvalue(s2v(newstack + i)); /* erase new segment */ | ||
| 210 | return 1; | 234 | return 1; |
| 211 | } | 235 | } |
| 212 | 236 | ||
| @@ -158,8 +158,13 @@ typedef union StackValue { | |||
| 158 | typedef StackValue *StkId; | 158 | typedef StackValue *StkId; |
| 159 | 159 | ||
| 160 | 160 | ||
| 161 | /* | ||
| 162 | ** When reallocating the stack, change all pointers to the stack into | ||
| 163 | ** proper offsets. | ||
| 164 | */ | ||
| 161 | typedef union { | 165 | typedef union { |
| 162 | StkId p; /* actual pointer */ | 166 | StkId p; /* actual pointer */ |
| 167 | ptrdiff_t offset; /* used while the stack is being reallocated */ | ||
| 163 | } StkIdRel; | 168 | } StkIdRel; |
| 164 | 169 | ||
| 165 | 170 | ||
| @@ -626,6 +631,7 @@ typedef struct UpVal { | |||
| 626 | lu_byte tbc; /* true if it represents a to-be-closed variable */ | 631 | lu_byte tbc; /* true if it represents a to-be-closed variable */ |
| 627 | union { | 632 | union { |
| 628 | TValue *p; /* points to stack or to its own value */ | 633 | TValue *p; /* points to stack or to its own value */ |
| 634 | ptrdiff_t offset; /* used while the stack is being reallocated */ | ||
| 629 | } v; | 635 | } v; |
| 630 | union { | 636 | union { |
| 631 | struct { /* (when open) */ | 637 | struct { /* (when open) */ |
