浏览代码

cleaner way to free all objects

Roberto Ierusalimschy 20 年之前
父节点
当前提交
4df8800a01
共有 4 个文件被更改,包括 40 次插入43 次删除
  1. 3 3
      lfunc.c
  2. 23 31
      lgc.c
  3. 9 5
      lgc.h
  4. 5 4
      lstate.c

+ 3 - 3
lfunc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.c,v 2.5 2004/11/24 19:20:21 roberto Exp $
+** $Id: lfunc.c,v 2.7 2005/01/19 15:54:26 roberto Exp roberto $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
@@ -57,7 +57,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
   while ((p = ngcotouv(*pp)) != NULL && p->v >= level) {
     lua_assert(p->v != &p->u.value);
     if (p->v == level) {  /* found a corresponding upvalue? */
-      if (isdead(G(L), obj2gco(p)))  /* is it dead? */
+      if (isdead(g, obj2gco(p)))  /* is it dead? */
         changewhite(obj2gco(p));  /* ressurect it */
       return p;
     }
@@ -106,7 +106,7 @@ void luaF_close (lua_State *L, StkId level) {
       setobj(L, &uv->u.value, uv->v);
       if (isgray(o)) {
         gray2black(o);  /* closed upvalues are never gray */
-        luaC_barrier(L, uv, uv->v);
+        luaC_barrier(L, uv, &uv->u.value);
       }
       uv->v = &uv->u.value;  /* now current value lives here */
       luaC_linkupval(L, uv);  /* link upvalue into `gcroot' list */

+ 23 - 31
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.21 2005/01/14 14:19:42 roberto Exp $
+** $Id: lgc.c,v 2.22 2005/01/18 17:18:09 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -29,13 +29,11 @@
 #define GCFINALIZECOST	100
 
 
-#define FIXEDMASK	bitmask(FIXEDBIT)
-
 #define maskmarks \
-	cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT)))
+	cast(lu_byte, ~(bitmask(BLACKBIT)|WHITEBITS))
 
 #define makewhite(g,x)	\
-   ((x)->gch.marked = ((x)->gch.marked & maskmarks) | g->currentwhite)
+   ((x)->gch.marked = ((x)->gch.marked & maskmarks) | luaC_white(g))
 
 #define white2gray(x)	reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
 #define gray2black(x)	setbit((x)->gch.marked, BLACKBIT)
@@ -60,6 +58,8 @@
 		reallymarkobject(g, obj2gco(t)); }
 
 
+#define setthreshold(g)  (g->GCthreshold = (g->estimate/100) * g->gcpace)
+
 
 static void removeentry (Node *n) {
   lua_assert(ttisnil(gval(n)));
@@ -400,24 +400,23 @@ static void freeobj (lua_State *L, GCObject *o) {
 
 
 
-#define sweepwholelist(L,p)	sweeplist(L,p,LUA_MAXINT32)
+#define sweepwholelist(L,p)	sweeplist(L,p,MAX_LUMEM)
 
 
-static GCObject **sweeplist (lua_State *L, GCObject **p, lu_int32 count) {
+static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
   GCObject *curr;
   global_State *g = G(L);
-  int whitebit = otherwhite(g);
-  int deadmask = whitebit | FIXEDMASK;
+  int deadmask = otherwhite(g);
   while ((curr = *p) != NULL && count-- > 0) {
-    if ((curr->gch.marked ^ whitebit) & deadmask) {
+    if (curr->gch.tt == LUA_TTHREAD)  /* sweep open upvalues of each thread */
+      sweepwholelist(L, &gco2th(curr)->openupval);
+    if ((curr->gch.marked ^ WHITEBITS) & deadmask) {  /* not dead? */
       lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));
-      makewhite(g, curr);
-      if (curr->gch.tt == LUA_TTHREAD)
-        sweepwholelist(L, &gco2th(curr)->openupval);
+      makewhite(g, curr);  /* make it white (for next cycle) */
       p = &curr->gch.next;
     }
-    else {
-      lua_assert(isdead(g, curr));
+    else {  /* must erase `curr' */
+      lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));
       *p = curr->gch.next;
       if (curr == g->rootgc)  /* is the first element of the list? */
         g->rootgc = curr->gch.next;  /* adjust first */
@@ -428,21 +427,10 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_int32 count) {
 }
 
 
-
-static void freelist (lua_State *L, GCObject **p) {
-  while (*p) {
-    GCObject *curr = *p;
-    *p = (*p)->gch.next;
-    if (curr != obj2gco(L))
-      freeobj(L, curr);
-  }
-}
-
-
 static void checkSizes (lua_State *L) {
   global_State *g = G(L);
   /* check size of string hash */
-  if (g->strt.nuse < cast(lu_int32, G(L)->strt.size/4) &&
+  if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&
       g->strt.size > MINSTRTABSIZE*2)
     luaS_resize(L, g->strt.size/2);  /* table is too big */
   /* check size of buffer */
@@ -487,9 +475,10 @@ void luaC_callGCTM (lua_State *L) {
 void luaC_freeall (lua_State *L) {
   global_State *g = G(L);
   int i;
-  freelist(L, &g->rootgc);
+  g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT);  /* mask to collect all elements */
+  sweepwholelist(L, &g->rootgc);
   for (i = 0; i < g->strt.size; i++)  /* free all string lists */
-    freelist(L, &G(L)->strt.hash[i]);
+    sweepwholelist(L, &g->strt.hash[i]);
 }
 
 
@@ -604,6 +593,8 @@ static l_mem singlestep (lua_State *L) {
 void luaC_step (lua_State *L) {
   global_State *g = G(L);
   l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
+  if (lim == 0)
+    lim = (MAX_LUMEM-1)/2;  /* no limit */
   g->gcdept += g->totalbytes - g->GCthreshold;
   do {
     lim -= singlestep(L);
@@ -620,7 +611,7 @@ void luaC_step (lua_State *L) {
   }
   else {
     lua_assert(g->totalbytes >= g->estimate);
-    g->GCthreshold = (g->estimate/100) * g->gcpace;
+    setthreshold(g);
   }
 }
 
@@ -637,6 +628,7 @@ void luaC_fullgc (lua_State *L) {
     g->weak = NULL;
     g->gcstate = GCSsweepstring;
   }
+  lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate);
   /* finish any pending sweep phase */
   while (g->gcstate != GCSfinalize) {
     lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
@@ -646,7 +638,7 @@ void luaC_fullgc (lua_State *L) {
   while (g->gcstate != GCSpause) {
     singlestep(L);
   }
-  g->GCthreshold = 2*g->estimate;
+  setthreshold(g);
 }
 
 

+ 9 - 5
lgc.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 2.9 2004/09/15 20:38:15 roberto Exp $
+** $Id: lgc.h,v 2.10 2005/01/19 15:54:26 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -47,8 +47,10 @@
 ** bit 3 - for tables: has weak keys
 ** bit 4 - for tables: has weak values
 ** bit 5 - object is fixed (should not be collected)
+** bit 6 - object is "super" fixed (only the main thread)
 */
 
+
 #define WHITE0BIT	0
 #define WHITE1BIT	1
 #define BLACKBIT	2
@@ -56,21 +58,23 @@
 #define KEYWEAKBIT	3
 #define VALUEWEAKBIT	4
 #define FIXEDBIT	5
+#define SFIXEDBIT	6
+#define WHITEBITS	bit2mask(WHITE0BIT, WHITE1BIT)
 
 
 #define iswhite(x)      test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
 #define isblack(x)      testbit((x)->gch.marked, BLACKBIT)
 #define isgray(x)	(!isblack(x) && !iswhite(x))
 
-#define otherwhite(g)	(g->currentwhite ^ bit2mask(WHITE0BIT, WHITE1BIT))
-#define isdead(g,v)	((v)->gch.marked & otherwhite(g))
+#define otherwhite(g)	(g->currentwhite ^ WHITEBITS)
+#define isdead(g,v)	((v)->gch.marked & otherwhite(g) & WHITEBITS)
 
-#define changewhite(x)	((x)->gch.marked ^= bit2mask(WHITE0BIT, WHITE1BIT))
+#define changewhite(x)	((x)->gch.marked ^= WHITEBITS)
 #define gray2black(x)	setbit((x)->gch.marked, BLACKBIT)
 
 #define valiswhite(x)	(iscollectable(x) && iswhite(gcvalue(x)))
 
-#define luaC_white(g)	cast(lu_byte, (g)->currentwhite)
+#define luaC_white(g)	cast(lu_byte, (g)->currentwhite & WHITEBITS)
 
 
 #define luaC_checkGC(L) { if (G(L)->totalbytes >= G(L)->GCthreshold) \

+ 5 - 4
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 2.22 2005/01/14 14:19:42 roberto Exp $
+** $Id: lstate.c,v 2.23 2005/01/18 17:18:09 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -114,7 +114,7 @@ static void close_state (lua_State *L) {
   global_State *g = G(L);
   luaF_close(L, L->stack);  /* close all upvalues for this thread */
   luaC_freeall(L);  /* collect all objects */
-  lua_assert(g->rootgc == NULL);
+  lua_assert(g->rootgc == obj2gco(L));
   lua_assert(g->strt.nuse == 0);
   luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
   luaZ_freebuffer(L, &g->buff);
@@ -156,8 +156,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g = &((LG *)L)->g;
   L->next = NULL;
   L->tt = LUA_TTHREAD;
-  L->marked = g->currentwhite = bitmask(WHITE0BIT);
-  setbit(L->marked, FIXEDBIT);
+  g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
+  L->marked = luaC_white(g);
+  set2bits(L->marked, FIXEDBIT, SFIXEDBIT);
   preinit_state(L, g);
   g->realloc = f;
   g->ud = ud;