aboutsummaryrefslogtreecommitdiff
path: root/ldo.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldo.c')
-rw-r--r--ldo.c54
1 files changed, 44 insertions, 10 deletions
diff --git a/ldo.c b/ldo.c
index d63c8267..e75a79ab 100644
--- a/ldo.c
+++ b/ldo.c
@@ -191,6 +191,16 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
191 191
192 192
193/* 193/*
194** In ISO C, any pointer use after the pointer has been deallocated is
195** undefined behavior. So, before a stack reallocation, all pointers are
196** changed to offsets, and after the reallocation they are changed back
197** to pointers. As during the reallocation the pointers are invalid, the
198** reallocation cannot run emergency collections.
199**
200*/
201
202#if 1
203/*
194** Change all pointers to the stack into offsets. 204** Change all pointers to the stack into offsets.
195*/ 205*/
196static void relstack (lua_State *L) { 206static void relstack (lua_State *L) {
@@ -210,9 +220,10 @@ static void relstack (lua_State *L) {
210/* 220/*
211** Change back all offsets into pointers. 221** Change back all offsets into pointers.
212*/ 222*/
213static void correctstack (lua_State *L) { 223static void correctstack (lua_State *L, StkId oldstack) {
214 CallInfo *ci; 224 CallInfo *ci;
215 UpVal *up; 225 UpVal *up;
226 UNUSED(oldstack);
216 L->top.p = restorestack(L, L->top.offset); 227 L->top.p = restorestack(L, L->top.offset);
217 L->tbclist.p = restorestack(L, L->tbclist.offset); 228 L->tbclist.p = restorestack(L, L->tbclist.offset);
218 for (up = L->openupval; up != NULL; up = up->u.open.next) 229 for (up = L->openupval; up != NULL; up = up->u.open.next)
@@ -225,15 +236,37 @@ static void correctstack (lua_State *L) {
225 } 236 }
226} 237}
227 238
239#else
240/*
241** Alternatively, we can use the old address after the dealocation.
242** That is not strict ISO C, but seems to work fine everywhere.
243*/
244
245static void relstack (lua_State *L) { UNUSED(L); }
246
247static void correctstack (lua_State *L, StkId oldstack) {
248 CallInfo *ci;
249 UpVal *up;
250 StkId newstack = L->stack.p;
251 if (oldstack == newstack)
252 return;
253 L->top.p = L->top.p - oldstack + newstack;
254 L->tbclist.p = L->tbclist.p - oldstack + newstack;
255 for (up = L->openupval; up != NULL; up = up->u.open.next)
256 up->v.p = s2v(uplevel(up) - oldstack + newstack);
257 for (ci = L->ci; ci != NULL; ci = ci->previous) {
258 ci->top.p = ci->top.p - oldstack + newstack;
259 ci->func.p = ci->func.p - oldstack + newstack;
260 if (isLua(ci))
261 ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */
262 }
263}
264
265#endif
266
228 267
229/* 268/*
230** Reallocate the stack to a new size, correcting all pointers into it. 269** Reallocate the stack to a new size, correcting all pointers into it.
231** In ISO C, any pointer use after the pointer has been deallocated is
232** undefined behavior. So, before the reallocation, all pointers are
233** changed to offsets, and after the reallocation they are changed back
234** to pointers. As during the reallocation the pointers are invalid, the
235** reallocation cannot run emergency collections.
236**
237** In case of allocation error, raise an error or return false according 270** In case of allocation error, raise an error or return false according
238** to 'raiseerror'. 271** to 'raiseerror'.
239*/ 272*/
@@ -241,21 +274,22 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
241 int oldsize = stacksize(L); 274 int oldsize = stacksize(L);
242 int i; 275 int i;
243 StkId newstack; 276 StkId newstack;
277 StkId oldstack = L->stack.p;
244 lu_byte oldgcstop = G(L)->gcstopem; 278 lu_byte oldgcstop = G(L)->gcstopem;
245 lua_assert(newsize <= MAXSTACK || newsize == ERRORSTACKSIZE); 279 lua_assert(newsize <= MAXSTACK || newsize == ERRORSTACKSIZE);
246 relstack(L); /* change pointers to offsets */ 280 relstack(L); /* change pointers to offsets */
247 G(L)->gcstopem = 1; /* stop emergency collection */ 281 G(L)->gcstopem = 1; /* stop emergency collection */
248 newstack = luaM_reallocvector(L, L->stack.p, oldsize + EXTRA_STACK, 282 newstack = luaM_reallocvector(L, oldstack, oldsize + EXTRA_STACK,
249 newsize + EXTRA_STACK, StackValue); 283 newsize + EXTRA_STACK, StackValue);
250 G(L)->gcstopem = oldgcstop; /* restore emergency collection */ 284 G(L)->gcstopem = oldgcstop; /* restore emergency collection */
251 if (l_unlikely(newstack == NULL)) { /* reallocation failed? */ 285 if (l_unlikely(newstack == NULL)) { /* reallocation failed? */
252 correctstack(L); /* change offsets back to pointers */ 286 correctstack(L, oldstack); /* change offsets back to pointers */
253 if (raiseerror) 287 if (raiseerror)
254 luaM_error(L); 288 luaM_error(L);
255 else return 0; /* do not raise an error */ 289 else return 0; /* do not raise an error */
256 } 290 }
257 L->stack.p = newstack; 291 L->stack.p = newstack;
258 correctstack(L); /* change offsets back to pointers */ 292 correctstack(L, oldstack); /* change offsets back to pointers */
259 L->stack_last.p = L->stack.p + newsize; 293 L->stack_last.p = L->stack.p + newsize;
260 for (i = oldsize + EXTRA_STACK; i < newsize + EXTRA_STACK; i++) 294 for (i = oldsize + EXTRA_STACK; i < newsize + EXTRA_STACK; i++)
261 setnilvalue(s2v(newstack + i)); /* erase new segment */ 295 setnilvalue(s2v(newstack + i)); /* erase new segment */