Browse Source

corrected some checks about colors of old objects + new test function
'gcage'

Roberto Ierusalimschy 8 years ago
parent
commit
7ae180f8e8
1 changed files with 46 additions and 15 deletions
  1. 46 15
      ltests.c

+ 46 - 15
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 2.212 2017/02/23 21:07:34 roberto Exp roberto $
+** $Id: ltests.c,v 2.213 2017/04/18 19:42:12 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -189,10 +189,11 @@ void *debug_realloc (void *ud, void *b, size_t oldsize, size_t size) {
 /*
 ** Check GC invariants. For incremental mode, a black object cannot
 ** point to a white one. For generational mode, really old objects
-** cannot point to young objects. (Threads and open upvalues, despite
-** being marked "really old", continue to be visited in all collections,
-** and therefore can point to new objects. They, and only they, are
-** old but gray.)
+** cannot point to young objects. Both old1 and touched2 objects
+** cannot point to new objects (but can point to survivals).
+** (Threads and open upvalues, despite being marked "really old",
+** continue to be visited in all collections, and therefore can point to
+** new objects. They, and only they, are old but gray.)
 */
 static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
   if (isdead(g,t)) return 0;
@@ -200,8 +201,14 @@ static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
     return 1;  /* no invariants */
   else if (g->gckind == KGC_NORMAL)
     return !(isblack(f) && iswhite(t));  /* basic incremental invariant */
-  else
-    return !((getage(f) == G_OLD && isblack(f)) && !isold(t));
+  else {  /* generational mode */
+    if ((getage(f) == G_OLD && isblack(f)) && !isold(t))
+      return 0;
+    if (((getage(f) == G_OLD1 || getage(f) == G_TOUCHED2) && isblack(f)) &&
+          getage(t) == G_NEW)
+      return 0;
+    return 1;
+  }
 }
 
 
@@ -377,6 +384,17 @@ static void checkrefs (global_State *g, GCObject *o) {
 }
 
 
+/*
+** Check consistency of an object:
+** - Dead objects can only happen in the 'allgc' list during a sweep
+** phase (controled by the caller through 'maybedead').
+** - During pause, all objects must be white.
+** - In generational mode:
+**   * objects must be old enough for their lists ('listage').
+**   * old objects cannot be white.
+**   * old objects must be black, except for 'touched1', 'old0',
+** threads, and open upvalues.
+*/
 static void checkobject (global_State *g, GCObject *o, int maybedead,
                          int listage) {
   if (isdead(g, o))
@@ -389,6 +407,7 @@ static void checkobject (global_State *g, GCObject *o, int maybedead,
       if (isold(o)) {
         lua_assert(isblack(o) ||
         getage(o) == G_TOUCHED1 ||
+        getage(o) == G_OLD0 ||
         o->tt == LUA_TTHREAD ||
         (o->tt == LUA_TUPVAL && upisopen(gco2upv(o))));
       }
@@ -442,9 +461,9 @@ static void checkgray (global_State *g, GCObject *o) {
 
 
 static void checklist (global_State *g, int maybedead, int tof,
-  GCObject *new, GCObject *survival, GCObject *old, GCObject *reallyold) {
+  GCObject *newl, GCObject *survival, GCObject *old, GCObject *reallyold) {
   GCObject *o;
-  for (o = new; o != survival; o = o->next) {
+  for (o = newl; o != survival; o = o->next) {
     checkobject(g, o, maybedead, G_NEW);
     lua_assert(!tof == !tofinalize(o));
   }
@@ -668,20 +687,31 @@ static int gc_color (lua_State *L) {
   TValue *o;
   luaL_checkany(L, 1);
   o = obj_at(L, 1);
-  if (!iscollectable(o)) {
+  if (!iscollectable(o))
     lua_pushstring(L, "no collectable");
-    return 1;
-  }
   else {
-    static const char *gennames[] = {"new", "survival", "old0", "old1",
-                                     "old", "touched1", "touched2"};
     GCObject *obj = gcvalue(o);
     lua_pushstring(L, isdead(G(L), obj) ? "dead" :
                       iswhite(obj) ? "white" :
                       isblack(obj) ? "black" : "grey");
+  }
+  return 1;
+}
+
+
+static int gc_age (lua_State *L) {
+  TValue *o;
+  luaL_checkany(L, 1);
+  o = obj_at(L, 1);
+  if (!iscollectable(o))
+    lua_pushstring(L, "no collectable");
+  else {
+    static const char *gennames[] = {"new", "survival", "old0", "old1",
+                                     "old", "touched1", "touched2"};
+    GCObject *obj = gcvalue(o);
     lua_pushstring(L, gennames[getage(obj)]);
-    return 2;
   }
+  return 1;
 }
 
 
@@ -1587,6 +1617,7 @@ static const struct luaL_Reg tests_funcs[] = {
   {"doonnewstack", doonnewstack},
   {"doremote", doremote},
   {"gccolor", gc_color},
+  {"gcage", gc_age},
   {"gcstate", gc_state},
   {"pobj", gc_printobj},
   {"getref", getref},