Browse Source

no more 'finalize' phase in GC; finalizers are called along the
entire cycle

Roberto Ierusalimschy 15 years ago
parent
commit
0c27de2e7b
3 changed files with 33 additions and 31 deletions
  1. 28 25
      lgc.c
  2. 2 3
      lgc.h
  3. 3 3
      ltests.c

+ 28 - 25
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.83 2010/04/30 18:37:14 roberto Exp roberto $
+** $Id: lgc.c,v 2.84 2010/05/03 11:55:40 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -27,7 +27,7 @@
 #define GCSTEPSIZE	1024
 #define GCSWEEPMAX	40
 #define GCSWEEPCOST	1
-#define GCFINALIZECOST	50
+#define GCFINALIZENUM	4
 #define GCROOTCOST	10
 #define GCATOMICCOST	1000
 
@@ -115,8 +115,7 @@ static int iscleared (const TValue *o, int iskey) {
 void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
   global_State *g = G(L);
   lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
-  lua_assert(g->gckind == KGC_GEN ||
-             (g->gcstate != GCSfinalize && g->gcstate != GCSpause));
+  lua_assert(g->gckind == KGC_GEN || g->gcstate != GCSpause);
   lua_assert(gch(o)->tt != LUA_TTABLE);
   if (keepinvariant(g))  /* must keep invariant? */
     reallymarkobject(g, v);  /* restore invariant */
@@ -643,6 +642,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
 static void checkSizes (lua_State *L) {
   global_State *g = G(L);
   int hs = g->strt.size / 2;  /* half the size of the string table */
+  if (g->gcstate == KGC_EMERGENCY) return;
   if (g->strt.nuse < cast(lu_int32, hs)) {  /* using less than half its size? */
       luaS_resize(L, hs);  /* halve its size */
   }
@@ -755,10 +755,18 @@ void luaC_checkfinalizer (lua_State *L, Udata *u) {
 ** =======================================================
 */
 
+/*
+** call all pending finalizers */
+static void callallpendingfinalizers (lua_State *L, int propagateerrors) {
+  global_State *g = G(L);
+  while (g->tobefnz) GCTM(L, propagateerrors);
+}
+
+
 void luaC_freeallobjects (lua_State *L) {
   global_State *g = G(L);
   int i;
-  while (g->tobefnz) GCTM(L, 0);  /* Call all pending finalizers */
+  callallpendingfinalizers(L, 0);
   /* following "white" makes all objects look dead */
   g->currentwhite = WHITEBITS;
   sweepwholelist(L, &g->udgc);
@@ -795,7 +803,7 @@ static void atomic (lua_State *L) {
   cleartable(g->weak);
   cleartable(g->ephemeron);
   cleartable(g->allweak);
-  lua_checkmemory(L);
+  /*lua_checkmemory(L);*/
   g->currentwhite = cast_byte(otherwhite(g));  /* flip current white */
 }
 
@@ -850,19 +858,9 @@ static l_mem singlestep (lua_State *L) {
       else {
         /* sweep main thread */
         sweeplist(L, cast(GCObject **, &g->mainthread), 1);
-        g->gcstate = GCSfinalize;  /* go to next phase */
-        return GCSWEEPCOST;
-      }
-    }
-    case GCSfinalize: {
-      if (g->tobefnz) {
-        GCTM(L, 1);
-        return GCFINALIZECOST;
-      }
-      else {
         checkSizes(L);
-        g->gcstate = GCSpause;  /* end collection */
-        return 0;
+        g->gcstate = GCSpause;  /* finish collection */
+        return GCSWEEPCOST;
       }
     }
     default: lua_assert(0); return 0;
@@ -913,8 +911,11 @@ static void step (lua_State *L) {
 
 
 void luaC_step (lua_State *L) {
+  int i;
   if (G(L)->gckind == KGC_GEN) generationalcollection(L);
   else step(L);
+  for (i = 0; i < GCFINALIZENUM && G(L)->tobefnz; i++)
+    GCTM(L, 1);  /* Call a few pending finalizers */
 }
 
 
@@ -926,6 +927,8 @@ void luaC_fullgc (lua_State *L, int isemergency) {
   global_State *g = G(L);
   int origkind = g->gckind;
   lua_assert(origkind == KGC_NORMAL || origkind == KGC_GEN);
+  if (!isemergency)   /* do not run finalizers during emergency GC */
+    callallpendingfinalizers(L, 1);
   g->gckind = isemergency ? KGC_EMERGENCY : KGC_FORCED;
   if (g->gcstate == GCSpropagate) {  /* marking phase? */
     /* must sweep all objects to turn them back to white
@@ -934,16 +937,16 @@ void luaC_fullgc (lua_State *L, int isemergency) {
     g->gcstate = GCSsweepstring;
   }
   /* finish any pending sweep phase */
-  luaC_runtilstate(L, bit2mask(GCSpause, GCSfinalize));
-  g->gcstate = GCSpause;  /* start a new collection */
-  /* run collector up to finalizers */
-  luaC_runtilstate(L, bitmask(GCSfinalize));
+  luaC_runtilstate(L, bitmask(GCSpause));
+  /* run entire collector */
+  luaC_runtilstate(L, ~bitmask(GCSpause));
+  luaC_runtilstate(L, bitmask(GCSpause));
   g->gckind = origkind;
   if (!isemergency)   /* do not run finalizers during emergency GC */
-    luaC_runtilstate(L, bitmask(GCSpause));
+    callallpendingfinalizers(L, 1);
   if (origkind == KGC_GEN) {  /* generational mode? */
-    g->gcstate = GCSpause;  /* collector must be always in... */
-    luaC_runtilstate(L, bitmask(GCSpropagate));  /* ...propagate phase */
+    /* collector must be always in propagate phase */
+    luaC_runtilstate(L, bitmask(GCSpropagate));
   }
   g->GCdebt = stddebt(g);
 }

+ 2 - 3
lgc.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 2.33 2010/04/30 18:36:45 roberto Exp roberto $
+** $Id: lgc.h,v 2.34 2010/05/03 11:24:30 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -33,8 +33,7 @@
 #define GCSsweepstring	2
 #define GCSsweepudata	3
 #define GCSsweep	4
-#define GCSfinalize	5
-#define GCSpause	6
+#define GCSpause	5
 
 
 #define issweepphase(g)  \

+ 3 - 3
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 2.99 2010/04/30 18:37:14 roberto Exp roberto $
+** $Id: ltests.c,v 2.100 2010/05/03 11:55:40 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -580,9 +580,9 @@ static int get_gccolor (lua_State *L) {
 
 static int gc_state (lua_State *L) {
   static const char *statenames[] = {"", "pause", "propagate", "atomic",
-    "sweepstring", "sweepudata", "sweep", "finalize"};
+    "sweepstring", "sweepudata", "sweep"};
   static const int states[] = {0, GCSpause, GCSpropagate, GCSatomic,
-    GCSsweepstring, GCSsweepudata, GCSsweep, GCSfinalize};
+    GCSsweepstring, GCSsweepudata, GCSsweep};
   int option = luaL_checkoption(L, 1, "", statenames);
   if (option == 0) {
     lua_pushstring(L, statenames[G(L)->gcstate]);