mirror of https://github.com/rusefi/lua.git
Fixed bug for emergency collection in upvalue creation
When creating an upvalue, an emergency collection can collect the previous upvalue where the new one would be linked. The following code can trigger the bug, using valgrind on Lua compiled with the -DHARDMEMTESTS option: local x; local y (function () return y end)(); (function () return x end)()
This commit is contained in:
parent
dc07719b0d
commit
440a5ee78c
14
lfunc.c
14
lfunc.c
|
@ -82,20 +82,22 @@ static UpVal *newupval (lua_State *L, int tbc, StkId level, UpVal **prev) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Find and reuse, or create if it does not exist, a regular upvalue
|
** Find and reuse, or create if it does not exist, an upvalue
|
||||||
** at the given level.
|
** at the given level and set it to the given slot.
|
||||||
*/
|
*/
|
||||||
UpVal *luaF_findupval (lua_State *L, StkId level) {
|
void luaF_setupval (lua_State *L, StkId level, UpVal **slot) {
|
||||||
UpVal **pp = &L->openupval;
|
UpVal **pp = &L->openupval;
|
||||||
UpVal *p;
|
UpVal *p;
|
||||||
lua_assert(isintwups(L) || L->openupval == NULL);
|
lua_assert(isintwups(L) || L->openupval == NULL);
|
||||||
while ((p = *pp) != NULL && uplevel(p) >= level) { /* search for it */
|
while ((p = *pp) != NULL && uplevel(p) >= level) { /* search for it */
|
||||||
|
*slot = p;
|
||||||
if (uplevel(p) == level && !isdead(G(L), p)) /* corresponding upvalue? */
|
if (uplevel(p) == level && !isdead(G(L), p)) /* corresponding upvalue? */
|
||||||
return p; /* return it */
|
return; /* found it */
|
||||||
pp = &p->u.open.next;
|
pp = &p->u.open.next;
|
||||||
}
|
}
|
||||||
/* not found: create a new upvalue after 'pp' */
|
/* not found: create a new upvalue after 'pp' (which is
|
||||||
return newupval(L, 0, level, pp);
|
anchored in 'slot', in case of an emergency collection) */
|
||||||
|
*slot = newupval(L, 0, level, pp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
2
lfunc.h
2
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 CClosure *luaF_newCclosure (lua_State *L, int nelems);
|
||||||
LUAI_FUNC LClosure *luaF_newLclosure (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_initupvals (lua_State *L, LClosure *cl);
|
||||||
LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
|
LUAI_FUNC void luaF_setupval (lua_State *L, StkId level, UpVal **slot);
|
||||||
LUAI_FUNC void luaF_newtbcupval (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 int luaF_close (lua_State *L, StkId level, int status);
|
||||||
LUAI_FUNC void luaF_unlinkupval (UpVal *uv);
|
LUAI_FUNC void luaF_unlinkupval (UpVal *uv);
|
||||||
|
|
2
lvm.c
2
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 */
|
setclLvalue2s(L, ra, ncl); /* anchor new closure in stack */
|
||||||
for (i = 0; i < nup; i++) { /* fill in its upvalues */
|
for (i = 0; i < nup; i++) { /* fill in its upvalues */
|
||||||
if (uv[i].instack) /* upvalue refers to local variable? */
|
if (uv[i].instack) /* upvalue refers to local variable? */
|
||||||
ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx);
|
luaF_setupval(L, base + uv[i].idx, &ncl->upvals[i]);
|
||||||
else /* get upvalue from enclosing function */
|
else /* get upvalue from enclosing function */
|
||||||
ncl->upvals[i] = encup[uv[i].idx];
|
ncl->upvals[i] = encup[uv[i].idx];
|
||||||
luaC_objbarrier(L, ncl, ncl->upvals[i]);
|
luaC_objbarrier(L, ncl, ncl->upvals[i]);
|
||||||
|
|
Loading…
Reference in New Issue