diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-07-22 09:41:10 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-07-22 09:41:10 -0300 |
commit | 9e6807c3c9d5036e999f636f936df07b72284442 (patch) | |
tree | 39100fb44792114905f00d1b638212f620d12a25 | |
parent | 2f22c6bb79d209a55b3fc8e0b2d9c9f89f038174 (diff) | |
download | lua-9e6807c3c9d5036e999f636f936df07b72284442.tar.gz lua-9e6807c3c9d5036e999f636f936df07b72284442.tar.bz2 lua-9e6807c3c9d5036e999f636f936df07b72284442.zip |
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.)
-rw-r--r-- | lfunc.c | 15 | ||||
-rw-r--r-- | lfunc.h | 2 | ||||
-rw-r--r-- | lgc.c | 6 | ||||
-rw-r--r-- | lvm.c | 2 |
4 files changed, 11 insertions, 14 deletions
@@ -83,21 +83,20 @@ static UpVal *newupval (lua_State *L, int tbc, StkId level, UpVal **prev) { | |||
83 | 83 | ||
84 | /* | 84 | /* |
85 | ** Find and reuse, or create if it does not exist, an upvalue | 85 | ** Find and reuse, or create if it does not exist, an upvalue |
86 | ** at the given level and set it to the given slot. | 86 | ** at the given level. |
87 | */ | 87 | */ |
88 | void luaF_setupval (lua_State *L, StkId level, UpVal **slot) { | 88 | UpVal *luaF_findupval (lua_State *L, StkId level) { |
89 | UpVal **pp = &L->openupval; | 89 | UpVal **pp = &L->openupval; |
90 | UpVal *p; | 90 | UpVal *p; |
91 | lua_assert(isintwups(L) || L->openupval == NULL); | 91 | lua_assert(isintwups(L) || L->openupval == NULL); |
92 | while ((p = *pp) != NULL && uplevel(p) >= level) { /* search for it */ | 92 | while ((p = *pp) != NULL && uplevel(p) >= level) { /* search for it */ |
93 | *slot = p; | 93 | lua_assert(!isdead(G(L), p)); |
94 | if (uplevel(p) == level && !isdead(G(L), p)) /* corresponding upvalue? */ | 94 | if (uplevel(p) == level) /* corresponding upvalue? */ |
95 | return; /* found it */ | 95 | return p; /* return it */ |
96 | pp = &p->u.open.next; | 96 | pp = &p->u.open.next; |
97 | } | 97 | } |
98 | /* not found: create a new upvalue after 'pp' (which is | 98 | /* not found: create a new upvalue after 'pp' */ |
99 | anchored in 'slot', in case of an emergency collection) */ | 99 | return newupval(L, 0, level, pp); |
100 | *slot = newupval(L, 0, level, pp); | ||
101 | } | 100 | } |
102 | 101 | ||
103 | 102 | ||
@@ -57,7 +57,7 @@ LUAI_FUNC Proto *luaF_newproto (lua_State *L); | |||
57 | LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems); | 57 | LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems); |
58 | LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems); | 58 | LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems); |
59 | LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); | 59 | LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); |
60 | LUAI_FUNC void luaF_setupval (lua_State *L, StkId level, UpVal **slot); | 60 | LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); |
61 | LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); | 61 | LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); |
62 | LUAI_FUNC int luaF_close (lua_State *L, StkId level, int status); | 62 | LUAI_FUNC int luaF_close (lua_State *L, StkId level, int status); |
63 | LUAI_FUNC void luaF_unlinkupval (UpVal *uv); | 63 | LUAI_FUNC void luaF_unlinkupval (UpVal *uv); |
@@ -569,10 +569,8 @@ static int traversethread (global_State *g, lua_State *th) { | |||
569 | th->openupval == NULL || isintwups(th)); | 569 | th->openupval == NULL || isintwups(th)); |
570 | for (; o < th->top; o++) /* mark live elements in the stack */ | 570 | for (; o < th->top; o++) /* mark live elements in the stack */ |
571 | markvalue(g, s2v(o)); | 571 | markvalue(g, s2v(o)); |
572 | for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) { | 572 | for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) |
573 | if (uv->tbc) /* to be closed? */ | 573 | markobject(g, uv); /* open upvalues cannot be collected */ |
574 | markobject(g, uv); /* cannot be collected */ | ||
575 | } | ||
576 | if (g->gcstate == GCSatomic) { /* final traversal? */ | 574 | if (g->gcstate == GCSatomic) { /* final traversal? */ |
577 | StkId lim = th->stack + th->stacksize; /* real end of stack */ | 575 | StkId lim = th->stack + th->stacksize; /* real end of stack */ |
578 | for (; o < lim; o++) /* clear not-marked stack slice */ | 576 | for (; o < lim; o++) /* clear not-marked stack slice */ |
@@ -697,7 +697,7 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, | |||
697 | setclLvalue2s(L, ra, ncl); /* anchor new closure in stack */ | 697 | setclLvalue2s(L, ra, ncl); /* anchor new closure in stack */ |
698 | for (i = 0; i < nup; i++) { /* fill in its upvalues */ | 698 | for (i = 0; i < nup; i++) { /* fill in its upvalues */ |
699 | if (uv[i].instack) /* upvalue refers to local variable? */ | 699 | if (uv[i].instack) /* upvalue refers to local variable? */ |
700 | luaF_setupval(L, base + uv[i].idx, &ncl->upvals[i]); | 700 | ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx); |
701 | else /* get upvalue from enclosing function */ | 701 | else /* get upvalue from enclosing function */ |
702 | ncl->upvals[i] = encup[uv[i].idx]; | 702 | ncl->upvals[i] = encup[uv[i].idx]; |
703 | luaC_objbarrier(L, ncl, ncl->upvals[i]); | 703 | luaC_objbarrier(L, ncl, ncl->upvals[i]); |