Sfoglia il codice sorgente

Better tests for gray lists

Test uses an extra bit in 'marked' to mark all elements in gray lists
and then check against elements colored gray.
Roberto Ierusalimschy 5 anni fa
parent
commit
f13dc59416
3 ha cambiato i file con 37 aggiunte e 10 eliminazioni
  1. 4 1
      lgc.h
  2. 31 9
      ltests.c
  3. 2 0
      testes/nextvar.lua

+ 4 - 1
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)

+ 31 - 9
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);
   }

+ 2 - 0
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