diff --git a/lgc.h b/lgc.h index f571fd2b..0508cd1d 100644 --- a/lgc.h +++ b/lgc.h @@ -69,13 +69,16 @@ /* ** Layout for bit use in 'marked' field. First three bits are -** used for object "age" in generational mode. +** used for object "age" in generational mode. Last bit is used +** by tests. */ #define WHITE0BIT 3 /* object is white (type 0) */ #define WHITE1BIT 4 /* object is white (type 1) */ #define BLACKBIT 5 /* object is black */ #define FINALIZEDBIT 6 /* object has been marked for finalization */ +#define TESTBIT 7 + #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) diff --git a/ltests.c b/ltests.c index c0421781..04e8a00a 100644 --- a/ltests.c +++ b/ltests.c @@ -522,7 +522,11 @@ static lu_mem checkgraylist (global_State *g, GCObject *o) { int total = 0; /* count number of elements in the list */ ((void)g); /* better to keep it available if we need to print an object */ while (o) { - lua_assert(isgray(o) || getage(o) == G_TOUCHED2); + lua_assert(!!isgray(o) ^ (getage(o) == G_TOUCHED2)); + //lua_assert(isgray(o) || getage(o) == G_TOUCHED2); + lua_assert(!testbit(o->marked, TESTBIT)); + if (keepinvariant(g)) + l_setbit(o->marked, TESTBIT); /* mark that object is in a gray list */ total++; switch (o->tt) { case LUA_VTABLE: o = gco2t(o)->gclist; break; @@ -556,9 +560,27 @@ static lu_mem checkgrays (global_State *g) { } -/* Increment 't' if 'o' should be in a gray list */ -#define incifingray(o,t) \ - if (isgray(o) || getage(o) == G_TOUCHED2) (t)++ +/* +** Check whether 'o' should be in a gray list. If so, increment +** 'count' and check its TESTBIT. (It must have been previously set by +** 'checkgraylist'.) +*/ +static void incifingray (global_State *g, GCObject *o, lu_mem *count) { + if (!keepinvariant(g)) + return; /* gray lists not being kept in these phases */ + if (o->tt == LUA_VUPVAL) { + /* only open upvalues can be gray */ + lua_assert(!isgray(o) || upisopen(gco2upv(o))); + return; /* upvalues are never in gray lists */ + } + /* these are the ones that must be in gray lists */ + if (isgray(o) || getage(o) == G_TOUCHED2) { + (*count)++; + lua_assert(testbit(o->marked, TESTBIT)); + resetbit(o->marked, TESTBIT); /* prepare for next cycle */ + } +} + static lu_mem checklist (global_State *g, int maybedead, int tof, GCObject *newl, GCObject *survival, GCObject *old, GCObject *reallyold) { @@ -566,22 +588,22 @@ static lu_mem checklist (global_State *g, int maybedead, int tof, lu_mem total = 0; /* number of object that should be in gray lists */ for (o = newl; o != survival; o = o->next) { checkobject(g, o, maybedead, G_NEW); - incifingray(o, total); + incifingray(g, o, &total); lua_assert(!tof == !tofinalize(o)); } for (o = survival; o != old; o = o->next) { checkobject(g, o, 0, G_SURVIVAL); - incifingray(o, total); + incifingray(g, o, &total); lua_assert(!tof == !tofinalize(o)); } for (o = old; o != reallyold; o = o->next) { checkobject(g, o, 0, G_OLD1); - incifingray(o, total); + incifingray(g, o, &total); lua_assert(!tof == !tofinalize(o)); } for (o = reallyold; o != NULL; o = o->next) { checkobject(g, o, 0, G_OLD); - incifingray(o, total); + incifingray(g, o, &total); lua_assert(!tof == !tofinalize(o)); } return total; @@ -619,7 +641,7 @@ int lua_checkmemory (lua_State *L) { /* check 'tobefnz' list */ for (o = g->tobefnz; o != NULL; o = o->next) { checkobject(g, o, 0, G_NEW); - incifingray(o, totalshould); + incifingray(g, o, &totalshould); lua_assert(tofinalize(o)); lua_assert(o->tt == LUA_VUSERDATA || o->tt == LUA_VTABLE); } diff --git a/testes/nextvar.lua b/testes/nextvar.lua index 73af77dd..a16d557b 100644 --- a/testes/nextvar.lua +++ b/testes/nextvar.lua @@ -88,6 +88,7 @@ for _, sa in ipairs(sizes) do -- 'sa' is size of the array part arr[1 + sa + sh + 1] = "}" local prog = table.concat(arr) local f = assert(load(prog)) + collectgarbage("stop") f() -- call once to ensure stack space -- make sure table is not resized after being created if sa == 0 or sh == 0 then @@ -97,6 +98,7 @@ for _, sa in ipairs(sizes) do -- 'sa' is size of the array part end local t = f() T.alloccount(); + collectgarbage("restart") assert(#t == sa) check(t, sa, mp2(sh)) end