Fixed bug in generational collection of userdata
During generational collection, a userdatum must become gray and go to a gray list after being traversed (like tables), so that 'correctgraylist' can handle it to its next stage. This commit also added minimum tests for the generational collector, including one that would detect this bug.
This commit is contained in:
26
lgc.c
26
lgc.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
** $Id$
|
||||
** $Id: lgc.c $
|
||||
** Garbage Collector
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
@@ -212,7 +212,7 @@ void luaC_barrierback_ (lua_State *L, GCObject *o) {
|
||||
lua_assert(g->gckind != KGC_GEN || (isold(o) && getage(o) != G_TOUCHED1));
|
||||
if (getage(o) != G_TOUCHED2) /* not already in gray list? */
|
||||
linkobjgclist(o, g->grayagain); /* link it in 'grayagain' */
|
||||
black2gray(o); /* make table gray (again) */
|
||||
black2gray(o); /* make object gray (again) */
|
||||
setage(o, G_TOUCHED1); /* touched in current cycle */
|
||||
}
|
||||
|
||||
@@ -515,6 +515,19 @@ static lu_mem traversetable (global_State *g, Table *h) {
|
||||
}
|
||||
|
||||
|
||||
static int traverseudata (global_State *g, Udata *u) {
|
||||
int i;
|
||||
markobjectN(g, u->metatable); /* mark its metatable */
|
||||
for (i = 0; i < u->nuvalue; i++)
|
||||
markvalue(g, &u->uv[i].uv);
|
||||
if (g->gckind == KGC_GEN) {
|
||||
linkgclist(u, g->grayagain); /* keep it in some gray list */
|
||||
black2gray(u);
|
||||
}
|
||||
return 1 + u->nuvalue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check the cache of a prototype, to keep invariants. If the
|
||||
** cache is white, clear it. (A cache should not prevent the
|
||||
@@ -613,15 +626,6 @@ static int traversethread (global_State *g, lua_State *th) {
|
||||
}
|
||||
|
||||
|
||||
static int traverseudata (global_State *g, Udata *u) {
|
||||
int i;
|
||||
markobjectN(g, u->metatable); /* mark its metatable */
|
||||
for (i = 0; i < u->nuvalue; i++)
|
||||
markvalue(g, &u->uv[i].uv);
|
||||
return 1 + u->nuvalue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** traverse one gray object, turning it to black (except for threads,
|
||||
** which are always gray).
|
||||
|
||||
Reference in New Issue
Block a user