فهرست منبع

new function 'luaC_changemode' +
bug: objects entering the 'allgc' list must have their OLDBIT cleared
(upvalues being cleared) + bug: in 'checkSizes', KGC_EMERGENCY is
stored in 'gckind' field, not in 'gcstate' + current white changes when
entering sweep phase (so there are dead objects only in that phase)

Roberto Ierusalimschy 15 سال پیش
والد
کامیت
d2ea5b00b7
1فایلهای تغییر یافته به همراه42 افزوده شده و 13 حذف شده
  1. 42 13
      lgc.c

+ 42 - 13
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.87 2010/05/04 18:09:06 roberto Exp roberto $
+** $Id: lgc.c,v 2.88 2010/05/05 13:39:58 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -170,6 +170,7 @@ void luaC_checkupvalcolor (global_State *g, UpVal *uv) {
   lua_assert(!isblack(o));  /* open upvalues are never black */
   if (isgray(o)) {
     if (keepinvariant(g)) {
+      resetbit(o->gch.marked, OLDBIT);
       gray2black(o);  /* it is being visited now */
       markvalue(g, uv->v);
     }
@@ -300,7 +301,8 @@ static void remarkupvals (global_State *g) {
 
 
 /*
-** mark root set
+** mark root set and reset all gray lists, to start a new
+** incremental (or full) collection
 */
 static void markroot (lua_State *L) {
   global_State *g = G(L);
@@ -655,12 +657,12 @@ 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? */
+  if (g->gckind != KGC_EMERGENCY) {  /* do not change sizes in emergency */
+    int hs = g->strt.size / 2;  /* half the size of the string table */
+    if (g->strt.nuse < cast(lu_int32, hs))  /* using less than that half? */
       luaS_resize(L, hs);  /* halve its size */
+    luaZ_freebuffer(L, &g->buff);  /* free concatenation buffer */
   }
-  luaZ_freebuffer(L, &g->buff);  /* free concatenation buffer */
 }
 
 
@@ -668,6 +670,7 @@ static Udata *udata2finalize (global_State *g) {
   GCObject *o = g->tobefnz;  /* get first element */
   Udata *u = rawgco2u(o);
   lua_assert(isfinalized(&u->uv));
+  lua_assert(!testbit(u->uv.marked, OLDBIT));
   g->tobefnz = u->uv.next;  /* remove it from 'tobefnz' list */
   u->uv.next = g->allgc;  /* return it to 'allgc' list */
   g->allgc = o;
@@ -769,6 +772,33 @@ void luaC_checkfinalizer (lua_State *L, Udata *u) {
 ** =======================================================
 */
 
+
+#define sweepphases  \
+	(bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep))
+
+/*
+** change GC mode
+*/
+void luaC_changemode (lua_State *L, int mode) {
+  global_State *g = G(L);
+  if (mode == g->gckind) return;  /* nothing to change */
+  if (mode == KGC_GEN) {  /* change to generational mode */
+    /* make sure gray lists are consistent */
+    luaC_runtilstate(L, bitmask(GCSpropagate));
+    g->lastmajormem = g->totalbytes;
+    g->gckind = KGC_GEN;
+  }
+  else {  /* change to incremental mode */
+    /* sweep all objects to turn them back to white
+       (as white has not changed, nothing extra will be collected) */
+    g->sweepstrgc = 0;
+    g->gcstate = GCSsweepstring;
+    g->gckind = KGC_NORMAL;
+    luaC_runtilstate(L, ~sweepphases);
+  }
+}
+
+
 /*
 ** call all pending finalizers */
 static void callallpendingfinalizers (lua_State *L, int propagateerrors) {
@@ -817,7 +847,8 @@ static void atomic (lua_State *L) {
   cleartable(g->weak);
   cleartable(g->ephemeron);
   cleartable(g->allweak);
-  lua_checkmemory(L);
+  g->sweepstrgc = 0;  /* prepare to sweep strings */
+  g->gcstate = GCSsweepstring;
   g->currentwhite = cast_byte(otherwhite(g));  /* flip current white */
 }
 
@@ -837,8 +868,6 @@ static l_mem singlestep (lua_State *L) {
       else {  /* no more `gray' objects */
         g->gcstate = GCSatomic;  /* finish mark phase */
         atomic(L);
-        g->sweepstrgc = 0;  /* prepare to sweep strings */
-        g->gcstate = GCSsweepstring;
         return GCATOMICCOST;
       }
     }
@@ -933,7 +962,7 @@ void luaC_step (lua_State *L) {
 
 
 /*
-** performs a full GC cycle; if "isememrgency", does not call
+** performs a full GC cycle; if "isemergency", does not call
 ** finalizers (which could change stack positions)
 */
 void luaC_fullgc (lua_State *L, int isemergency) {
@@ -942,14 +971,14 @@ void luaC_fullgc (lua_State *L, int isemergency) {
   lua_assert(origkind != KGC_EMERGENCY);
   if (!isemergency)   /* do not run finalizers during emergency GC */
     callallpendingfinalizers(L, 1);
-  g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL;
-  if (g->gcstate == GCSpropagate) {  /* marking phase? */
+  if (keepinvariant(g)) {  /* marking phase? */
     /* must sweep all objects to turn them back to white
        (as white has not changed, nothing will be collected) */
     g->sweepstrgc = 0;
     g->gcstate = GCSsweepstring;
   }
-  /* finish any pending sweep phase */
+  g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL;
+  /* finish any pending sweep phase to start a new cycle */
   luaC_runtilstate(L, bitmask(GCSpause));
   /* run entire collector */
   luaC_runtilstate(L, ~bitmask(GCSpause));