Browse Source

corrected some places where an old object could end up in front
of a new one + minimal documentation about this problem

Roberto Ierusalimschy 15 years ago
parent
commit
1c1a98e872
4 changed files with 15 additions and 10 deletions
  1. 5 3
      lfunc.c
  2. 4 5
      lgc.c
  3. 4 1
      lgc.h
  4. 2 1
      lstring.c

+ 5 - 3
lfunc.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lfunc.c,v 2.22 2010/04/29 17:34:35 roberto Exp roberto $
+** $Id: lfunc.c,v 2.23 2010/04/29 21:43:36 roberto Exp roberto $
 ** Auxiliary functions to manipulate prototypes and closures
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -52,12 +52,14 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
   UpVal *p;
   UpVal *p;
   UpVal *uv;
   UpVal *uv;
   while (*pp != NULL && (p = gco2uv(*pp))->v >= level) {
   while (*pp != NULL && (p = gco2uv(*pp))->v >= level) {
+    GCObject *o = obj2gco(p);
     lua_assert(p->v != &p->u.value);
     lua_assert(p->v != &p->u.value);
     if (p->v == level) {  /* found a corresponding upvalue? */
     if (p->v == level) {  /* found a corresponding upvalue? */
-      if (isdead(g, obj2gco(p)))  /* is it dead? */
-        changewhite(obj2gco(p));  /* ressurrect it */
+      if (isdead(g, o))  /* is it dead? */
+        changewhite(o);  /* ressurrect it */
       return p;
       return p;
     }
     }
+    resetoldbit(o);  /* may create a newer upval after this one */
     pp = &p->next;
     pp = &p->next;
   }
   }
   /* not found: create a new one */
   /* not found: create a new one */

+ 4 - 5
lgc.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lgc.c,v 2.92 2010/05/07 18:43:24 roberto Exp roberto $
+** $Id: lgc.c,v 2.93 2010/05/10 16:46:49 roberto Exp roberto $
 ** Garbage Collector
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -164,7 +164,7 @@ void luaC_checkupvalcolor (global_State *g, UpVal *uv) {
   lua_assert(!isblack(o));  /* open upvalues are never black */
   lua_assert(!isblack(o));  /* open upvalues are never black */
   if (isgray(o)) {
   if (isgray(o)) {
     if (keepinvariant(g)) {
     if (keepinvariant(g)) {
-      resetoldbit(o);
+      resetoldbit(o);  /* see MOVE OLD rule */
       gray2black(o);  /* it is being visited now */
       gray2black(o);  /* it is being visited now */
       markvalue(g, uv->v);
       markvalue(g, uv->v);
     }
     }
@@ -670,6 +670,7 @@ static Udata *udata2finalize (global_State *g) {
   u->uv.next = g->allgc;  /* return it to 'allgc' list */
   u->uv.next = g->allgc;  /* return it to 'allgc' list */
   g->allgc = o;
   g->allgc = o;
   resetbit(u->uv.marked, SEPARATED);  /* mark that it is not in 'tobefnz' */
   resetbit(u->uv.marked, SEPARATED);  /* mark that it is not in 'tobefnz' */
+  resetoldbit(o); /* see MOVE OLD rule */
   if (!keepinvariant(g))  /* not keeping invariant? */
   if (!keepinvariant(g))  /* not keeping invariant? */
     makewhite(g, o);  /* "sweep" object */
     makewhite(g, o);  /* "sweep" object */
   return u;
   return u;
@@ -729,7 +730,6 @@ void luaC_separateudata (lua_State *L, int all) {
       p = &gch(curr)->next;  /* don't bother with it */
       p = &gch(curr)->next;  /* don't bother with it */
     else {
     else {
       l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */
       l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */
-      resetoldbit(curr); /* may be old when 'all' is true */
       *p = gch(curr)->next;  /* remove 'curr' from 'udgc' list */
       *p = gch(curr)->next;  /* remove 'curr' from 'udgc' list */
       gch(curr)->next = *lastnext;  /* link at the end of 'tobefnz' list */
       gch(curr)->next = *lastnext;  /* link at the end of 'tobefnz' list */
       *lastnext = curr;
       *lastnext = curr;
@@ -756,7 +756,7 @@ void luaC_checkfinalizer (lua_State *L, Udata *u) {
     u->uv.next = g->udgc;  /* link it in list 'udgc' */
     u->uv.next = g->udgc;  /* link it in list 'udgc' */
     g->udgc = obj2gco(u);
     g->udgc = obj2gco(u);
     l_setbit(u->uv.marked, SEPARATED);  /* mark it as such */
     l_setbit(u->uv.marked, SEPARATED);  /* mark it as such */
-    resetoldbit(obj2gco(u));
+    resetoldbit(obj2gco(u));  /* see MOVE OLD rule */
   }
   }
 }
 }
 
 
@@ -854,7 +854,6 @@ static void atomic (lua_State *L) {
 
 
 static l_mem singlestep (lua_State *L) {
 static l_mem singlestep (lua_State *L) {
   global_State *g = G(L);
   global_State *g = G(L);
-  /*lua_checkmemory(L);*/
   switch (g->gcstate) {
   switch (g->gcstate) {
     case GCSpause: {
     case GCSpause: {
       if (!isgenerational(g))
       if (!isgenerational(g))

+ 4 - 1
lgc.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lgc.h,v 2.39 2010/05/07 18:43:51 roberto Exp roberto $
+** $Id: lgc.h,v 2.40 2010/05/10 16:46:49 roberto Exp roberto $
 ** Garbage Collector
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -91,6 +91,9 @@
 	(!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT)))
 	(!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT)))
 
 
 #define isold(x)	testbit((x)->gch.marked, OLDBIT)
 #define isold(x)	testbit((x)->gch.marked, OLDBIT)
+
+/* MOVE OLD rule: whenever an object is moved to the beginning of
+   a GC list, its old bit must be cleared */
 #define resetoldbit(o)	resetbit((o)->gch.marked, OLDBIT)
 #define resetoldbit(o)	resetbit((o)->gch.marked, OLDBIT)
 
 
 #define otherwhite(g)	(g->currentwhite ^ WHITEBITS)
 #define otherwhite(g)	(g->currentwhite ^ WHITEBITS)

+ 2 - 1
lstring.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstring.c,v 2.16 2009/12/16 16:42:58 roberto Exp roberto $
+** $Id: lstring.c,v 2.17 2010/04/03 20:24:18 roberto Exp roberto $
 ** String table (keeps all strings handled by Lua)
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -37,6 +37,7 @@ void luaS_resize (lua_State *L, int newsize) {
       unsigned int h = lmod(gco2ts(p)->hash, newsize);  /* new position */
       unsigned int h = lmod(gco2ts(p)->hash, newsize);  /* new position */
       gch(p)->next = tb->hash[h];  /* chain it */
       gch(p)->next = tb->hash[h];  /* chain it */
       tb->hash[h] = p;
       tb->hash[h] = p;
+      resetoldbit(p);  /* see MOVE OLD rule */
       p = next;
       p = next;
     }
     }
   }
   }