aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldo.c21
-rw-r--r--ldo.h1
-rw-r--r--lgc.c7
-rw-r--r--lstate.c17
-rw-r--r--lstate.h2
5 files changed, 37 insertions, 11 deletions
diff --git a/ldo.c b/ldo.c
index c92573d6..8085b735 100644
--- a/ldo.c
+++ b/ldo.c
@@ -206,6 +206,25 @@ l_noret luaD_errerr (lua_State *L) {
206 206
207 207
208/* 208/*
209** Check whether stacks have enough space to run a simple function (such
210** as a finalizer): At least BASIC_STACK_SIZE in the Lua stack, two
211** available CallInfos, and two "slots" in the C stack.
212*/
213int luaD_checkminstack (lua_State *L) {
214 if (getCcalls(L) >= LUAI_MAXCCALLS - 2)
215 return 0; /* not enough C-stack slots */
216 if (L->ci->next == NULL && luaE_extendCI(L, 0) == NULL)
217 return 0; /* unable to allocate first ci */
218 if (L->ci->next->next == NULL && luaE_extendCI(L, 0) == NULL)
219 return 0; /* unable to allocate second ci */
220 if (L->stack_last.p - L->top.p >= BASIC_STACK_SIZE)
221 return 1; /* enough (BASIC_STACK_SIZE) free slots in the Lua stack */
222 else /* try to grow stack to a size with enough free slots */
223 return luaD_growstack(L, BASIC_STACK_SIZE, 0);
224}
225
226
227/*
209** Reallocate the stack to a new size, correcting all pointers into it. 228** Reallocate the stack to a new size, correcting all pointers into it.
210** In ISO C, any pointer use after the pointer has been deallocated is 229** In ISO C, any pointer use after the pointer has been deallocated is
211** undefined behavior. So, before the reallocation, all pointers are 230** undefined behavior. So, before the reallocation, all pointers are
@@ -503,7 +522,7 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
503 522
504 523
505 524
506#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) 525#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L, 1))
507 526
508 527
509l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, 528l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret,
diff --git a/ldo.h b/ldo.h
index 4de9540e..4c8db865 100644
--- a/ldo.h
+++ b/ldo.h
@@ -80,6 +80,7 @@ LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror);
80LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); 80LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror);
81LUAI_FUNC void luaD_shrinkstack (lua_State *L); 81LUAI_FUNC void luaD_shrinkstack (lua_State *L);
82LUAI_FUNC void luaD_inctop (lua_State *L); 82LUAI_FUNC void luaD_inctop (lua_State *L);
83LUAI_FUNC int luaD_checkminstack (lua_State *L);
83 84
84LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); 85LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode);
85LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); 86LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
diff --git a/lgc.c b/lgc.c
index c01660ab..52cea240 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1242,7 +1242,7 @@ static void finishgencycle (lua_State *L, global_State *g) {
1242 correctgraylists(g); 1242 correctgraylists(g);
1243 checkSizes(L, g); 1243 checkSizes(L, g);
1244 g->gcstate = GCSpropagate; /* skip restart */ 1244 g->gcstate = GCSpropagate; /* skip restart */
1245 if (!g->gcemergency) 1245 if (g->tobefnz != NULL && !g->gcemergency && luaD_checkminstack(L))
1246 callallpendingfinalizers(L); 1246 callallpendingfinalizers(L);
1247} 1247}
1248 1248
@@ -1632,11 +1632,12 @@ static lu_mem singlestep (lua_State *L) {
1632 break; 1632 break;
1633 } 1633 }
1634 case GCScallfin: { /* call remaining finalizers */ 1634 case GCScallfin: { /* call remaining finalizers */
1635 if (g->tobefnz && !g->gcemergency) { 1635 if (g->tobefnz && !g->gcemergency && luaD_checkminstack(L)) {
1636 g->gcstopem = 0; /* ok collections during finalizers */ 1636 g->gcstopem = 0; /* ok collections during finalizers */
1637 work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST; 1637 work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST;
1638 } 1638 }
1639 else { /* emergency mode or no more finalizers */ 1639 else { /* no more finalizers or emergency mode or no enough stack
1640 to run finalizers */
1640 g->gcstate = GCSpause; /* finish collection */ 1641 g->gcstate = GCSpause; /* finish collection */
1641 work = 0; 1642 work = 0;
1642 } 1643 }
diff --git a/lstate.c b/lstate.c
index f3f2ccfd..059be806 100644
--- a/lstate.c
+++ b/lstate.c
@@ -102,14 +102,19 @@ LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) {
102} 102}
103 103
104 104
105CallInfo *luaE_extendCI (lua_State *L) { 105CallInfo *luaE_extendCI (lua_State *L, int err) {
106 CallInfo *ci; 106 CallInfo *ci;
107 lua_assert(L->ci->next == NULL); 107 ci = luaM_reallocvector(L, NULL, 0, 1, CallInfo);
108 ci = luaM_new(L, CallInfo); 108 if (l_unlikely(ci == NULL)) { /* allocation failed? */
109 lua_assert(L->ci->next == NULL); 109 if (err)
110 L->ci->next = ci; 110 luaM_error(L); /* raise the error */
111 return NULL; /* else only report it */
112 }
113 ci->next = L->ci->next;
111 ci->previous = L->ci; 114 ci->previous = L->ci;
112 ci->next = NULL; 115 L->ci->next = ci;
116 if (ci->next)
117 ci->next->previous = ci;
113 ci->u.l.trap = 0; 118 ci->u.l.trap = 0;
114 L->nci++; 119 L->nci++;
115 return ci; 120 return ci;
diff --git a/lstate.h b/lstate.h
index 007704c8..97bb3e8f 100644
--- a/lstate.h
+++ b/lstate.h
@@ -395,7 +395,7 @@ union GCUnion {
395 395
396LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); 396LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
397LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); 397LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
398LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); 398LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L, int err);
399LUAI_FUNC void luaE_shrinkCI (lua_State *L); 399LUAI_FUNC void luaE_shrinkCI (lua_State *L);
400LUAI_FUNC void luaE_checkcstack (lua_State *L); 400LUAI_FUNC void luaE_checkcstack (lua_State *L);
401LUAI_FUNC void luaE_incCstack (lua_State *L); 401LUAI_FUNC void luaE_incCstack (lua_State *L);