aboutsummaryrefslogtreecommitdiff
path: root/lfunc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lfunc.c')
-rw-r--r--lfunc.c64
1 files changed, 33 insertions, 31 deletions
diff --git a/lfunc.c b/lfunc.c
index 4f9362f3..15874f88 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -98,27 +98,29 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
98 98
99 99
100static void callclose (lua_State *L, void *ud) { 100static void callclose (lua_State *L, void *ud) {
101 luaD_callnoyield(L, cast(StkId, ud), 0); 101 UNUSED(ud);
102 luaD_callnoyield(L, L->top - 2, 0);
102} 103}
103 104
104 105
105/* 106/*
106** Prepare closing method with its argument for object at 107** Prepare closing method plus its argument for object 'obj' with
107** index 'func' in the stack. Assume there is an error message 108** error message 'err'. (This function assumes EXTRA_STACK.)
108** (or nil) just below the object.
109*/ 109*/
110static int prepclosingmethod (lua_State *L, StkId func) { 110static int prepclosingmethod (lua_State *L, TValue *obj, TValue *err) {
111 if (ttisfunction(s2v(func))) { /* object to-be-closed is a function? */ 111 StkId top = L->top;
112 setobjs2s(L, func + 1, func - 1); /* push error msg. as argument */ 112 if (ttisfunction(obj)) { /* object to-be-closed is a function? */
113 setobj2s(L, top, obj); /* push function */
114 setobj2s(L, top + 1, err); /* push error msg. as argument */
113 } 115 }
114 else { /* try '__close' metamethod */ 116 else { /* try '__close' metamethod */
115 const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CLOSE); 117 const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE);
116 if (ttisnil(tm)) /* no metamethod? */ 118 if (ttisnil(tm)) /* no metamethod? */
117 return 0; /* nothing to call */ 119 return 0; /* nothing to call */
118 setobjs2s(L, func + 1, func); /* 'self' is the argument */ 120 setobj2s(L, top, tm); /* will call metamethod... */
119 setobj2s(L, func, tm); /* will call metamethod */ 121 setobj2s(L, top + 1, obj); /* with 'self' as the argument */
120 } 122 }
121 L->top = func + 2; /* add function and argument */ 123 L->top = top + 2; /* add function and argument */
122 return 1; 124 return 1;
123} 125}
124 126
@@ -129,22 +131,24 @@ static int prepclosingmethod (lua_State *L, StkId func) {
129** will be handled there. Otherwise, a previous error already 131** will be handled there. Otherwise, a previous error already
130** activated original protected call, and so the call to the 132** activated original protected call, and so the call to the
131** closing method must be protected here. 133** closing method must be protected here.
134** If status is OK, the call to the closing method will be pushed
135** at the top of the stack. Otherwise, values are pushed after
136** the 'level' of the upvalue being closed, as everything after
137** that won't be used again.
132*/ 138*/
133static int closeupval (lua_State *L, TValue *uv, StkId level, int status) { 139static int closeupval (lua_State *L, TValue *uv, StkId level, int status) {
134 StkId func = level + 1; /* save slot for old error message */ 140 if (likely(status == LUA_OK)) {
135 if (unlikely(status != LUA_OK)) /* was there an error? */ 141 if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */
136 luaD_seterrorobj(L, status, level); /* save error message */ 142 callclose(L, NULL); /* call closing method */
137 else 143 }
138 setnilvalue(s2v(level)); /* no error message */ 144 else { /* there was an error */
139 setobj2s(L, func, uv); /* put object on top of error message */ 145 /* save error message and set stack top to 'level + 1' */
140 if (!prepclosingmethod(L, func)) 146 luaD_seterrorobj(L, status, level);
141 return status; /* nothing to call */ 147 if (prepclosingmethod(L, uv, s2v(level))) { /* something to call? */
142 if (likely(status == LUA_OK)) /* not in "error mode"? */ 148 int newstatus = luaD_pcall(L, callclose, NULL, savestack(L, level), 0);
143 callclose(L, func); /* call closing method */ 149 if (newstatus != LUA_OK) /* another error when closing? */
144 else { /* already inside error handler; cannot raise another error */ 150 status = newstatus; /* this will be the new error */
145 int newstatus = luaD_pcall(L, callclose, func, savestack(L, level), 0); 151 }
146 if (newstatus != LUA_OK) /* error when closing? */
147 status = newstatus; /* this will be the new error */
148 } 152 }
149 return status; 153 return status;
150} 154}
@@ -169,12 +173,10 @@ static void trynewtbcupval (lua_State *L, void *ud) {
169void luaF_newtbcupval (lua_State *L, StkId level) { 173void luaF_newtbcupval (lua_State *L, StkId level) {
170 int status = luaD_rawrunprotected(L, trynewtbcupval, level); 174 int status = luaD_rawrunprotected(L, trynewtbcupval, level);
171 if (unlikely(status != LUA_OK)) { /* memory error creating upvalue? */ 175 if (unlikely(status != LUA_OK)) { /* memory error creating upvalue? */
172 StkId func = level + 1;
173 lua_assert(status == LUA_ERRMEM); 176 lua_assert(status == LUA_ERRMEM);
174 setobjs2s(L, func, level); /* open space for error message */ 177 luaD_seterrorobj(L, LUA_ERRMEM, level + 1); /* save error message */
175 luaD_seterrorobj(L, status, level); /* save error message */ 178 if (prepclosingmethod(L, s2v(level), s2v(level + 1)))
176 if (prepclosingmethod(L, func)) 179 callclose(L, NULL); /* call closing method */
177 callclose(L, func); /* call closing method */
178 luaD_throw(L, LUA_ERRMEM); /* throw memory error */ 180 luaD_throw(L, LUA_ERRMEM); /* throw memory error */
179 } 181 }
180} 182}
@@ -201,7 +203,7 @@ int luaF_close (lua_State *L, StkId level, int status) {
201 luaC_barrier(L, uv, slot); 203 luaC_barrier(L, uv, slot);
202 if (status >= 0 && uv->tt == LUA_TUPVALTBC) { /* must be closed? */ 204 if (status >= 0 && uv->tt == LUA_TUPVALTBC) { /* must be closed? */
203 ptrdiff_t levelrel = savestack(L, level); 205 ptrdiff_t levelrel = savestack(L, level);
204 status = closeupval(L, uv->v, upl, status); /* may reallocate the stack */ 206 status = closeupval(L, uv->v, upl, status); /* may realloc. the stack */
205 level = restorestack(L, levelrel); 207 level = restorestack(L, levelrel);
206 } 208 }
207 } 209 }