aboutsummaryrefslogtreecommitdiff
path: root/lfunc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lfunc.c')
-rw-r--r--lfunc.c37
1 files changed, 16 insertions, 21 deletions
diff --git a/lfunc.c b/lfunc.c
index 13e44d46..81ac9f0a 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -155,32 +155,19 @@ static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) {
155 155
156 156
157/* 157/*
158** Try to create a to-be-closed upvalue 158** Create a to-be-closed upvalue. If there is a memory allocation error,
159** (can raise a memory-allocation error) 159** 'ptbc' keeps the object so it can be closed as soon as possible.
160*/ 160** (Since memory errors have no handler, that will happen before any
161static void trynewtbcupval (lua_State *L, void *ud) { 161** stack reallocation.)
162 newupval(L, 1, cast(StkId, ud), &L->openupval);
163}
164
165
166/*
167** Create a to-be-closed upvalue. If there is a memory error
168** when creating the upvalue, the closing method must be called here,
169** as there is no upvalue to call it later.
170*/ 162*/
171void luaF_newtbcupval (lua_State *L, StkId level) { 163void luaF_newtbcupval (lua_State *L, StkId level) {
172 TValue *obj = s2v(level); 164 TValue *obj = s2v(level);
173 lua_assert(L->openupval == NULL || uplevel(L->openupval) < level); 165 lua_assert(L->openupval == NULL || uplevel(L->openupval) < level);
174 if (!l_isfalse(obj)) { /* false doesn't need to be closed */ 166 if (!l_isfalse(obj)) { /* false doesn't need to be closed */
175 int status;
176 checkclosemth(L, level, obj); 167 checkclosemth(L, level, obj);
177 status = luaD_rawrunprotected(L, trynewtbcupval, level); 168 L->ptbc = level; /* in case of allocation error */
178 if (unlikely(status != LUA_OK)) { /* memory error creating upvalue? */ 169 newupval(L, 1, level, &L->openupval);
179 lua_assert(status == LUA_ERRMEM); 170 L->ptbc = NULL; /* no errors */
180 luaD_seterrorobj(L, LUA_ERRMEM, level + 1); /* save error message */
181 callclosemethod(L, s2v(level), s2v(level + 1), 0);
182 luaD_throw(L, LUA_ERRMEM); /* throw memory error */
183 }
184 } 171 }
185} 172}
186 173
@@ -196,11 +183,19 @@ void luaF_unlinkupval (UpVal *uv) {
196/* 183/*
197** Close all upvalues up to the given stack level. A 'status' equal 184** Close all upvalues up to the given stack level. A 'status' equal
198** to NOCLOSINGMETH closes upvalues without running any __close 185** to NOCLOSINGMETH closes upvalues without running any __close
199** metamethods. 186** metamethods. If there is a pending to-be-closed value, close
187** it before anything else.
200*/ 188*/
201void luaF_close (lua_State *L, StkId level, int status, int yy) { 189void luaF_close (lua_State *L, StkId level, int status, int yy) {
202 UpVal *uv; 190 UpVal *uv;
203 StkId upl; /* stack index pointed by 'uv' */ 191 StkId upl; /* stack index pointed by 'uv' */
192 if (unlikely(status == LUA_ERRMEM && L->ptbc != NULL)) {
193 upl = L->ptbc;
194 L->ptbc = NULL; /* remove from "list" before closing */
195 prepcallclosemth(L, upl, status, yy);
196 }
197 else
198 lua_assert(L->ptbc == NULL); /* must be empty for other status */
204 while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) { 199 while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) {
205 TValue *slot = &uv->u.value; /* new position for value */ 200 TValue *slot = &uv->u.value; /* new position for value */
206 lua_assert(uplevel(uv) < L->top); 201 lua_assert(uplevel(uv) < L->top);