From 9e6807c3c9d5036e999f636f936df07b72284442 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 22 Jul 2019 09:41:10 -0300 Subject: [PATCH] Do not collect open upvalues Open upvalues are kept alive together with their corresponding stack. This change makes a simpler and safer fix to the issue in commit 440a5ee78c8, about upvalues in the list of open upvalues being collected while others are being created. (That previous fix may not be correct.) --- lfunc.c | 15 +++++++-------- lfunc.h | 2 +- lgc.c | 6 ++---- lvm.c | 2 +- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/lfunc.c b/lfunc.c index f7edf56b..6f2f897f 100644 --- a/lfunc.c +++ b/lfunc.c @@ -83,21 +83,20 @@ static UpVal *newupval (lua_State *L, int tbc, StkId level, UpVal **prev) { /* ** Find and reuse, or create if it does not exist, an upvalue -** at the given level and set it to the given slot. +** at the given level. */ -void luaF_setupval (lua_State *L, StkId level, UpVal **slot) { +UpVal *luaF_findupval (lua_State *L, StkId level) { UpVal **pp = &L->openupval; UpVal *p; lua_assert(isintwups(L) || L->openupval == NULL); while ((p = *pp) != NULL && uplevel(p) >= level) { /* search for it */ - *slot = p; - if (uplevel(p) == level && !isdead(G(L), p)) /* corresponding upvalue? */ - return; /* found it */ + lua_assert(!isdead(G(L), p)); + if (uplevel(p) == level) /* corresponding upvalue? */ + return p; /* return it */ pp = &p->u.open.next; } - /* not found: create a new upvalue after 'pp' (which is - anchored in 'slot', in case of an emergency collection) */ - *slot = newupval(L, 0, level, pp); + /* not found: create a new upvalue after 'pp' */ + return newupval(L, 0, level, pp); } diff --git a/lfunc.h b/lfunc.h index 72fc913a..0ed79c48 100644 --- a/lfunc.h +++ b/lfunc.h @@ -57,7 +57,7 @@ LUAI_FUNC Proto *luaF_newproto (lua_State *L); LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems); LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems); LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); -LUAI_FUNC void luaF_setupval (lua_State *L, StkId level, UpVal **slot); +LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); LUAI_FUNC int luaF_close (lua_State *L, StkId level, int status); LUAI_FUNC void luaF_unlinkupval (UpVal *uv); diff --git a/lgc.c b/lgc.c index c5babfed..b7220cf1 100644 --- a/lgc.c +++ b/lgc.c @@ -569,10 +569,8 @@ static int traversethread (global_State *g, lua_State *th) { th->openupval == NULL || isintwups(th)); for (; o < th->top; o++) /* mark live elements in the stack */ markvalue(g, s2v(o)); - for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) { - if (uv->tbc) /* to be closed? */ - markobject(g, uv); /* cannot be collected */ - } + for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) + markobject(g, uv); /* open upvalues cannot be collected */ if (g->gcstate == GCSatomic) { /* final traversal? */ StkId lim = th->stack + th->stacksize; /* real end of stack */ for (; o < lim; o++) /* clear not-marked stack slice */ diff --git a/lvm.c b/lvm.c index d3e05199..d9bd0ab3 100644 --- a/lvm.c +++ b/lvm.c @@ -697,7 +697,7 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, setclLvalue2s(L, ra, ncl); /* anchor new closure in stack */ for (i = 0; i < nup; i++) { /* fill in its upvalues */ if (uv[i].instack) /* upvalue refers to local variable? */ - luaF_setupval(L, base + uv[i].idx, &ncl->upvals[i]); + ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx); else /* get upvalue from enclosing function */ ncl->upvals[i] = encup[uv[i].idx]; luaC_objbarrier(L, ncl, ncl->upvals[i]);