Browse Source

sweep of strings also incremental

Roberto Ierusalimschy 21 years ago
parent
commit
9db1942bac
5 changed files with 50 additions and 25 deletions
  1. 35 17
      lgc.c
  2. 4 3
      lgc.h
  3. 3 1
      lstate.c
  4. 2 1
      lstate.h
  5. 6 3
      lstring.c

+ 35 - 17
lgc.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lgc.c,v 1.183 2003/12/03 12:30:41 roberto Exp roberto $
+** $Id: lgc.c,v 1.184 2003/12/03 20:03:07 roberto Exp roberto $
 ** Garbage Collector
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -430,14 +430,14 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
   GCObject *curr;
   GCObject *curr;
   global_State *g = G(L);
   global_State *g = G(L);
   l_mem lim = *plim;
   l_mem lim = *plim;
-  int white = otherwhite(g);
+  int dead = otherwhite(g);
   while ((curr = *p) != NULL) {
   while ((curr = *p) != NULL) {
     int mark = curr->gch.marked;
     int mark = curr->gch.marked;
     lua_assert(all || !(mark & g->currentwhite));
     lua_assert(all || !(mark & g->currentwhite));
-    if (!all && (!(mark & white) || testbit(mark, FIXEDBIT))) {
+    lim -= objsize(curr);
+    if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) {
       makewhite(g, curr);
       makewhite(g, curr);
       p = &curr->gch.next;
       p = &curr->gch.next;
-      lim -= objsize(curr);
     }
     }
     else {
     else {
       *p = curr->gch.next;
       *p = curr->gch.next;
@@ -450,27 +450,32 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
 }
 }
 
 
 
 
-static void sweepstrings (lua_State *L, int all) {
+static l_mem sweepstrings (lua_State *L, int all, l_mem lim) {
   int i;
   int i;
   global_State *g = G(L);
   global_State *g = G(L);
-  int white = otherwhite(g);
-  for (i = 0; i < g->strt.size; i++) {  /* for each list */
+  int dead = otherwhite(g);
+  for (i = g->sweepstrgc; i < g->strt.size; i++) {  /* for each list */
     GCObject *curr;
     GCObject *curr;
     GCObject **p = &G(L)->strt.hash[i];
     GCObject **p = &G(L)->strt.hash[i];
     while ((curr = *p) != NULL) {
     while ((curr = *p) != NULL) {
       int mark = curr->gch.marked;
       int mark = curr->gch.marked;
+      lu_mem size = sizestring(gcotots(curr)->tsv.len);
       lua_assert(all || !(mark & g->currentwhite));
       lua_assert(all || !(mark & g->currentwhite));
-      if (!all && (!(mark & white) || testbit(mark, FIXEDBIT))) {
+      if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) {
         makewhite(g, curr);
         makewhite(g, curr);
         p = &curr->gch.next;
         p = &curr->gch.next;
       }
       }
       else {
       else {
         g->strt.nuse--;
         g->strt.nuse--;
         *p = curr->gch.next;
         *p = curr->gch.next;
-        luaM_free(L, curr, sizestring(gcotots(curr)->tsv.len));
+        luaM_free(L, curr, size);
       }
       }
+      lim -= size;
     }
     }
+    if (lim <= 0) break;
   }
   }
+  g->sweepstrgc = i+1;
+  return lim;
 }
 }
 
 
 
 
@@ -527,7 +532,8 @@ void luaC_callGCTM (lua_State *L) {
 
 
 void luaC_sweepall (lua_State *L) {
 void luaC_sweepall (lua_State *L) {
   l_mem dummy = MAXLMEM;
   l_mem dummy = MAXLMEM;
-  sweepstrings(L, 1);
+  G(L)->sweepstrgc = 0;
+  sweepstrings(L, 1, dummy);
   sweeplist(L, &G(L)->rootgc, 1, &dummy);
   sweeplist(L, &G(L)->rootgc, 1, &dummy);
 }
 }
 
 
@@ -540,7 +546,6 @@ static void markroot (lua_State *L) {
   makewhite(g, valtogco(g->mainthread));
   makewhite(g, valtogco(g->mainthread));
   markobject(g, g->mainthread);
   markobject(g, g->mainthread);
   markvalue(g, registry(L));
   markvalue(g, registry(L));
-  markobject(g, g->firstudata);
   markobject(g, L);  /* mark running thread */
   markobject(g, L);  /* mark running thread */
   g->gcstate = GCSpropagate;
   g->gcstate = GCSpropagate;
 }
 }
@@ -552,14 +557,25 @@ static void atomic (lua_State *L) {
   marktmu(g);  /* mark `preserved' userdata */
   marktmu(g);  /* mark `preserved' userdata */
   propagatemarks(g, MAXLMEM);  /* remark, to propagate `preserveness' */
   propagatemarks(g, MAXLMEM);  /* remark, to propagate `preserveness' */
   cleartable(g->weak);  /* remove collected objects from weak tables */
   cleartable(g->weak);  /* remove collected objects from weak tables */
-  /* echange current white */
+  /* flip current white */
   g->currentwhite = otherwhite(g);
   g->currentwhite = otherwhite(g);
   /* first element of root list will be used as temporary head for sweep
   /* first element of root list will be used as temporary head for sweep
-     phase, so it won't be seeped */
+     phase, so it won't be swept */
   makewhite(g, g->rootgc);
   makewhite(g, g->rootgc);
   g->sweepgc = &g->rootgc->gch.next;
   g->sweepgc = &g->rootgc->gch.next;
-  sweepstrings(L, 0);
-  g->gcstate = GCSsweep;
+  g->sweepstrgc = 0;
+  g->gcstate = GCSsweepstring;
+}
+
+
+static void sweepstringstep (lua_State *L) {
+  global_State *g = G(L);
+  l_mem lim = sweepstrings(L, 0, GCSTEPSIZE);
+  if (lim == GCSTEPSIZE) {  /* nothing more to sweep? */
+    lua_assert(g->sweepstrgc > g->strt.size);
+    g->sweepstrgc = 0;
+    g->gcstate = GCSsweep;  /* end sweep-string phase */
+  }
 }
 }
 
 
 
 
@@ -567,9 +583,8 @@ static void sweepstep (lua_State *L) {
   global_State *g = G(L);
   global_State *g = G(L);
   l_mem lim = GCSTEPSIZE;
   l_mem lim = GCSTEPSIZE;
   g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim);
   g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim);
-  if (lim == GCSTEPSIZE) {  /* nothing more to sweep? */
+  if (lim == GCSTEPSIZE)  /* nothing more to sweep? */
     g->gcstate = GCSfinalize;  /* end sweep phase */
     g->gcstate = GCSfinalize;  /* end sweep phase */
-  }
 }
 }
 
 
 
 
@@ -582,6 +597,9 @@ void luaC_collectgarbage (lua_State *L) {
     propagatemarks(g, GCSTEPSIZE);
     propagatemarks(g, GCSTEPSIZE);
   /* atomic */
   /* atomic */
   atomic(L);
   atomic(L);
+  /* GCSsweepstring */
+  while (g->gcstate == GCSsweepstring)
+    sweepstringstep(L);
   /* GCSsweep */
   /* GCSsweep */
   while (g->gcstate == GCSsweep)
   while (g->gcstate == GCSsweep)
     sweepstep(L);
     sweepstep(L);

+ 4 - 3
lgc.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lgc.h,v 1.25 2003/12/01 16:33:30 roberto Exp roberto $
+** $Id: lgc.h,v 1.26 2003/12/03 20:03:07 roberto Exp roberto $
 ** Garbage Collector
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -17,8 +17,9 @@
 #define GCSroot		0
 #define GCSroot		0
 #define GCSpropagate	1
 #define GCSpropagate	1
 #define GCSatomic	2
 #define GCSatomic	2
-#define GCSsweep	3
-#define GCSfinalize	4
+#define GCSsweepstring	3
+#define GCSsweep	4
+#define GCSfinalize	5
 
 
 
 
 /*
 /*

+ 3 - 1
lstate.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.c,v 1.131 2003/12/03 12:30:41 roberto Exp roberto $
+** $Id: lstate.c,v 1.132 2003/12/03 20:03:07 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -81,6 +81,7 @@ static void f_luaopen (lua_State *L, void *ud) {
   u->uv.metatable = NULL;
   u->uv.metatable = NULL;
   G(L)->firstudata = valtogco(u);
   G(L)->firstudata = valtogco(u);
   luaC_link(L, valtogco(u), LUA_TUSERDATA);
   luaC_link(L, valtogco(u), LUA_TUSERDATA);
+  setbit(u->uv.marked, FIXEDBIT);
   stack_init(L, L);  /* init stack */
   stack_init(L, L);  /* init stack */
   sethvalue(gt(L), luaH_new(L, 0, 4));  /* table of globals */
   sethvalue(gt(L), luaH_new(L, 0, 4));  /* table of globals */
   sethvalue(registry(L), luaH_new(L, 4, 4));  /* registry */
   sethvalue(registry(L), luaH_new(L, 4, 4));  /* registry */
@@ -167,6 +168,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g->panic = NULL;
   g->panic = NULL;
   g->gcstate = 0;
   g->gcstate = 0;
   g->rootgc = NULL;
   g->rootgc = NULL;
+  g->sweepstrgc = 0;
   g->currentwhite = bitmask(WHITE0BIT);
   g->currentwhite = bitmask(WHITE0BIT);
   g->firstudata = NULL;
   g->firstudata = NULL;
   g->gray = NULL;
   g->gray = NULL;

+ 2 - 1
lstate.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.h,v 1.116 2003/12/03 12:30:41 roberto Exp roberto $
+** $Id: lstate.h,v 1.117 2003/12/03 20:03:07 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -101,6 +101,7 @@ typedef struct global_State {
   GCObject *rootgc;  /* list of all collectable objects */
   GCObject *rootgc;  /* list of all collectable objects */
   GCObject *firstudata;   /* udata go to the end of `rootgc' */
   GCObject *firstudata;   /* udata go to the end of `rootgc' */
   GCObject **sweepgc;  /* position of sweep in `rootgc' */
   GCObject **sweepgc;  /* position of sweep in `rootgc' */
+  int sweepstrgc;  /* position of sweep in `strt' */
   GCObject *gray;  /* list of gray objects */
   GCObject *gray;  /* list of gray objects */
   GCObject *weak;  /* list of weak tables (to be cleared) */
   GCObject *weak;  /* list of weak tables (to be cleared) */
   GCObject *tmudata;  /* list of userdata to be GC */
   GCObject *tmudata;  /* list of userdata to be GC */

+ 6 - 3
lstring.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstring.c,v 1.82 2003/12/03 12:30:41 roberto Exp roberto $
+** $Id: lstring.c,v 1.83 2003/12/03 20:03:07 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
 */
 */
@@ -25,9 +25,12 @@ void luaS_freeall (lua_State *L) {
 
 
 
 
 void luaS_resize (lua_State *L, int newsize) {
 void luaS_resize (lua_State *L, int newsize) {
-  GCObject **newhash = luaM_newvector(L, newsize, GCObject *);
-  stringtable *tb = &G(L)->strt;
+  GCObject **newhash;
+  stringtable *tb;
   int i;
   int i;
+  if (G(L)->sweepstrgc > 0) return;  /* cannot resize during GC traverse */
+  newhash = luaM_newvector(L, newsize, GCObject *);
+  tb = &G(L)->strt;
   for (i=0; i<newsize; i++) newhash[i] = NULL;
   for (i=0; i<newsize; i++) newhash[i] = NULL;
   /* rehash */
   /* rehash */
   for (i=0; i<tb->size; i++) {
   for (i=0; i<tb->size; i++) {