From 236bcc6e10f59b9336603571f1683cbe4aa411a9 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Fri, 22 Jan 2021 17:54:39 +0800 Subject: update included Lua. --- src/lua/lfunc.c | 117 +++++++++++++++++++++++--------------------------------- 1 file changed, 47 insertions(+), 70 deletions(-) (limited to 'src/lua/lfunc.c') diff --git a/src/lua/lfunc.c b/src/lua/lfunc.c index c4360f0..13e44d4 100644 --- a/src/lua/lfunc.c +++ b/src/lua/lfunc.c @@ -100,80 +100,57 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { } -static void callclose (lua_State *L, void *ud) { - UNUSED(ud); - luaD_callnoyield(L, L->top - 3, 0); -} - - /* -** Prepare closing method plus its arguments for object 'obj' with -** error message 'err'. (This function assumes EXTRA_STACK.) +** Call closing method for object 'obj' with error message 'err'. The +** boolean 'yy' controls whether the call is yieldable. +** (This function assumes EXTRA_STACK.) */ -static int prepclosingmethod (lua_State *L, TValue *obj, TValue *err) { +static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { StkId top = L->top; const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); - if (ttisnil(tm)) /* no metamethod? */ - return 0; /* nothing to call */ setobj2s(L, top, tm); /* will call metamethod... */ setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ L->top = top + 3; /* add function and arguments */ - return 1; + if (yy) + luaD_call(L, top, 0); + else + luaD_callnoyield(L, top, 0); } /* -** Raise an error with message 'msg', inserting the name of the -** local variable at position 'level' in the stack. +** Check whether 'obj' has a close metamethod and raise an error +** if not. */ -static void varerror (lua_State *L, StkId level, const char *msg) { - int idx = cast_int(level - L->ci->func); - const char *vname = luaG_findlocal(L, L->ci, idx, NULL); - if (vname == NULL) vname = "?"; - luaG_runerror(L, msg, vname); +static void checkclosemth (lua_State *L, StkId level, const TValue *obj) { + const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); + if (ttisnil(tm)) { /* no metamethod? */ + int idx = cast_int(level - L->ci->func); /* variable index */ + const char *vname = luaG_findlocal(L, L->ci, idx, NULL); + if (vname == NULL) vname = "?"; + luaG_runerror(L, "variable '%s' got a non-closable value", vname); + } } /* -** Prepare and call a closing method. If status is OK, code is still -** inside the original protected call, and so any error will be handled -** there. Otherwise, a previous error already activated the original -** protected call, and so the call to the closing method must be -** protected here. (A status == CLOSEPROTECT behaves like a previous -** error, to also run the closing method in protected mode). -** If status is OK, the call to the closing method will be pushed -** at the top of the stack. Otherwise, values are pushed after -** the 'level' of the upvalue being closed, as everything after -** that won't be used again. +** Prepare and call a closing method. +** If status is CLOSEKTOP, the call to the closing method will be pushed +** at the top of the stack. Otherwise, values can be pushed right after +** the 'level' of the upvalue being closed, as everything after that +** won't be used again. */ -static int callclosemth (lua_State *L, StkId level, int status) { +static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) { TValue *uv = s2v(level); /* value being closed */ - if (likely(status == LUA_OK)) { - if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */ - callclose(L, NULL); /* call closing method */ - else if (!l_isfalse(uv)) /* non-closable non-false value? */ - varerror(L, level, "attempt to close non-closable variable '%s'"); + TValue *errobj; + if (status == CLOSEKTOP) + errobj = &G(L)->nilvalue; /* error object is nil */ + else { /* 'luaD_seterrorobj' will set top to level + 2 */ + errobj = s2v(level + 1); /* error object goes after 'uv' */ + luaD_seterrorobj(L, status, level + 1); /* set error object */ } - else { /* must close the object in protected mode */ - ptrdiff_t oldtop; - level++; /* space for error message */ - oldtop = savestack(L, level + 1); /* top will be after that */ - luaD_seterrorobj(L, status, level); /* set error message */ - if (prepclosingmethod(L, uv, s2v(level))) { /* something to call? */ - int newstatus = luaD_pcall(L, callclose, NULL, oldtop, 0); - if (newstatus != LUA_OK && status == CLOSEPROTECT) /* first error? */ - status = newstatus; /* this will be the new error */ - else { - if (newstatus != LUA_OK) /* suppressed error? */ - luaE_warnerror(L, "__close metamethod"); - /* leave original error (or nil) on top */ - L->top = restorestack(L, oldtop); - } - } - /* else no metamethod; ignore this case and keep original error */ - } - return status; + callclosemethod(L, uv, errobj, yy); } @@ -196,16 +173,12 @@ void luaF_newtbcupval (lua_State *L, StkId level) { lua_assert(L->openupval == NULL || uplevel(L->openupval) < level); if (!l_isfalse(obj)) { /* false doesn't need to be closed */ int status; - const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); - if (ttisnil(tm)) /* no metamethod? */ - varerror(L, level, "variable '%s' got a non-closable value"); + checkclosemth(L, level, obj); status = luaD_rawrunprotected(L, trynewtbcupval, level); if (unlikely(status != LUA_OK)) { /* memory error creating upvalue? */ lua_assert(status == LUA_ERRMEM); luaD_seterrorobj(L, LUA_ERRMEM, level + 1); /* save error message */ - /* next call must succeed, as object is closable */ - prepclosingmethod(L, s2v(level), s2v(level + 1)); - callclose(L, NULL); /* call closing method */ + callclosemethod(L, s2v(level), s2v(level + 1), 0); luaD_throw(L, LUA_ERRMEM); /* throw memory error */ } } @@ -220,26 +193,30 @@ void luaF_unlinkupval (UpVal *uv) { } -int luaF_close (lua_State *L, StkId level, int status) { +/* +** Close all upvalues up to the given stack level. A 'status' equal +** to NOCLOSINGMETH closes upvalues without running any __close +** metamethods. +*/ +void luaF_close (lua_State *L, StkId level, int status, int yy) { UpVal *uv; - while ((uv = L->openupval) != NULL && uplevel(uv) >= level) { + StkId upl; /* stack index pointed by 'uv' */ + while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) { TValue *slot = &uv->u.value; /* new position for value */ lua_assert(uplevel(uv) < L->top); - if (uv->tbc && status != NOCLOSINGMETH) { - /* must run closing method, which may change the stack */ - ptrdiff_t levelrel = savestack(L, level); - status = callclosemth(L, uplevel(uv), status); - level = restorestack(L, levelrel); - } - luaF_unlinkupval(uv); + luaF_unlinkupval(uv); /* remove upvalue from 'openupval' list */ setobj(L, slot, uv->v); /* move value to upvalue slot */ uv->v = slot; /* now current value lives here */ if (!iswhite(uv)) { /* neither white nor dead? */ nw2black(uv); /* closed upvalues cannot be gray */ luaC_barrier(L, uv, slot); } + if (uv->tbc && status != NOCLOSINGMETH) { + ptrdiff_t levelrel = savestack(L, level); + prepcallclosemth(L, upl, status, yy); /* may change the stack */ + level = restorestack(L, levelrel); + } } - return status; } -- cgit v1.2.3-55-g6feb