diff options
Diffstat (limited to 'lfunc.c')
| -rw-r--r-- | lfunc.c | 22 |
1 files changed, 12 insertions, 10 deletions
| @@ -133,7 +133,8 @@ static int prepclosingmethod (lua_State *L, TValue *obj, TValue *err) { | |||
| 133 | ** the 'level' of the upvalue being closed, as everything after | 133 | ** the 'level' of the upvalue being closed, as everything after |
| 134 | ** that won't be used again. | 134 | ** that won't be used again. |
| 135 | */ | 135 | */ |
| 136 | static int callclosemth (lua_State *L, TValue *uv, StkId level, int status) { | 136 | static int callclosemth (lua_State *L, StkId level, int status) { |
| 137 | TValue *uv = s2v(level); /* value being closed */ | ||
| 137 | if (likely(status == LUA_OK)) { | 138 | if (likely(status == LUA_OK)) { |
| 138 | if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */ | 139 | if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */ |
| 139 | callclose(L, NULL); /* call closing method */ | 140 | callclose(L, NULL); /* call closing method */ |
| @@ -145,9 +146,10 @@ static int callclosemth (lua_State *L, TValue *uv, StkId level, int status) { | |||
| 145 | } | 146 | } |
| 146 | } | 147 | } |
| 147 | else { /* must close the object in protected mode */ | 148 | else { /* must close the object in protected mode */ |
| 148 | ptrdiff_t oldtop = savestack(L, level + 1); | 149 | ptrdiff_t oldtop; |
| 149 | /* save error message and set stack top to 'level + 1' */ | 150 | level++; /* space for error message */ |
| 150 | luaD_seterrorobj(L, status, level); | 151 | oldtop = savestack(L, level + 1); /* top will be after that */ |
| 152 | luaD_seterrorobj(L, status, level); /* set error message */ | ||
| 151 | if (prepclosingmethod(L, uv, s2v(level))) { /* something to call? */ | 153 | if (prepclosingmethod(L, uv, s2v(level))) { /* something to call? */ |
| 152 | int newstatus = luaD_pcall(L, callclose, NULL, oldtop, 0); | 154 | int newstatus = luaD_pcall(L, callclose, NULL, oldtop, 0); |
| 153 | if (newstatus != LUA_OK && status == CLOSEPROTECT) /* first error? */ | 155 | if (newstatus != LUA_OK && status == CLOSEPROTECT) /* first error? */ |
| @@ -203,18 +205,18 @@ int luaF_close (lua_State *L, StkId level, int status) { | |||
| 203 | StkId upl = uplevel(uv); | 205 | StkId upl = uplevel(uv); |
| 204 | TValue *slot = &uv->u.value; /* new position for value */ | 206 | TValue *slot = &uv->u.value; /* new position for value */ |
| 205 | lua_assert(upl < L->top); | 207 | lua_assert(upl < L->top); |
| 208 | if (uv->tt == LUA_TUPVALTBC && status != NOCLOSINGMETH) { | ||
| 209 | /* must run closing method */ | ||
| 210 | ptrdiff_t levelrel = savestack(L, level); | ||
| 211 | status = callclosemth(L, upl, status); /* may change the stack */ | ||
| 212 | level = restorestack(L, levelrel); | ||
| 213 | } | ||
| 206 | luaF_unlinkupval(uv); | 214 | luaF_unlinkupval(uv); |
| 207 | setobj(L, slot, uv->v); /* move value to upvalue slot */ | 215 | setobj(L, slot, uv->v); /* move value to upvalue slot */ |
| 208 | uv->v = slot; /* now current value lives here */ | 216 | uv->v = slot; /* now current value lives here */ |
| 209 | if (!iswhite(uv)) | 217 | if (!iswhite(uv)) |
| 210 | gray2black(uv); /* closed upvalues cannot be gray */ | 218 | gray2black(uv); /* closed upvalues cannot be gray */ |
| 211 | luaC_barrier(L, uv, slot); | 219 | luaC_barrier(L, uv, slot); |
| 212 | if (uv->tt == LUA_TUPVALTBC && status != NOCLOSINGMETH) { | ||
| 213 | /* must run closing method */ | ||
| 214 | ptrdiff_t levelrel = savestack(L, level); | ||
| 215 | status = callclosemth(L, uv->v, upl, status); /* may change the stack */ | ||
| 216 | level = restorestack(L, levelrel); | ||
| 217 | } | ||
| 218 | } | 220 | } |
| 219 | return status; | 221 | return status; |
| 220 | } | 222 | } |
