Browse Source

no more generational collector (and no more `noinc' mode)

Roberto Ierusalimschy 20 years ago
parent
commit
5be517602e
8 changed files with 49 additions and 66 deletions
  1. 4 4
      lapi.c
  2. 5 8
      lbaselib.c
  3. 24 33
      lgc.c
  4. 1 3
      llimits.h
  5. 4 5
      lstate.c
  6. 4 5
      lstate.h
  7. 5 6
      ltests.c
  8. 2 2
      lua.h

+ 4 - 4
lapi.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lapi.c,v 2.24 2005/01/04 15:55:12 roberto Exp roberto $
+** $Id: lapi.c,v 2.25 2005/01/07 19:53:32 roberto Exp roberto $
 ** Lua API
 ** Lua API
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -872,9 +872,9 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
       g->gcpace = data;
       g->gcpace = data;
       break;
       break;
     }
     }
-    case LUA_GCSETINCMODE: {
-      res = g->incgc;
-      g->incgc = data;
+    case LUA_GCSETSTEPMUL: {
+      res = g->gcstepmul;
+      g->gcstepmul = data;
       break;
       break;
     }
     }
     default: res = -1;  /* invalid option */
     default: res = -1;  /* invalid option */

+ 5 - 8
lbaselib.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lbaselib.c,v 1.163 2004/12/13 12:15:11 roberto Exp roberto $
+** $Id: lbaselib.c,v 1.164 2005/01/07 19:53:32 roberto Exp roberto $
 ** Basic library
 ** Basic library
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -182,13 +182,13 @@ static int luaB_gcinfo (lua_State *L) {
 
 
 static int luaB_collectgarbage (lua_State *L) {
 static int luaB_collectgarbage (lua_State *L) {
   static const char *const opts[] = {"stop", "restart", "collect",
   static const char *const opts[] = {"stop", "restart", "collect",
-    "count", "step", "setpace", "setincmode", NULL};
+    "count", "step", "setpace", "setstepmul", NULL};
   static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
   static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
-    LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPACE, LUA_GCSETINCMODE};
+    LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPACE, LUA_GCSETSTEPMUL};
   int o = luaL_findstring(luaL_optstring(L, 1, "collect"), opts);
   int o = luaL_findstring(luaL_optstring(L, 1, "collect"), opts);
-  int ex = luaL_optint(L, 2, 0);
+  lua_Number ex = luaL_optnumber(L, 2, 0);
   luaL_argcheck(L, o >= 0, 1, "invalid option");
   luaL_argcheck(L, o >= 0, 1, "invalid option");
-  lua_pushinteger(L, lua_gc(L, optsnum[o], ex));
+  lua_pushinteger(L, lua_gc(L, optsnum[o], ex * 100));
   return 1;
   return 1;
 }
 }
 
 
@@ -620,9 +620,6 @@ static void base_open (lua_State *L) {
   /* create register._LOADED to track loaded modules */
   /* create register._LOADED to track loaded modules */
   lua_newtable(L);
   lua_newtable(L);
   lua_setfield(L, LUA_REGISTRYINDEX, "_LOADED");
   lua_setfield(L, LUA_REGISTRYINDEX, "_LOADED");
-  /* create register._PRELOAD to allow pre-loaded modules */
-  lua_newtable(L);
-  lua_setfield(L, LUA_REGISTRYINDEX, "_PRELOAD");
   /* set global _G */
   /* set global _G */
   lua_pushvalue(L, LUA_GLOBALSINDEX);
   lua_pushvalue(L, LUA_GLOBALSINDEX);
   lua_setglobal(L, "_G");
   lua_setglobal(L, "_G");

+ 24 - 33
lgc.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lgc.c,v 2.19 2004/12/13 12:15:11 roberto Exp roberto $
+** $Id: lgc.c,v 2.20 2005/01/05 18:20:51 roberto Exp roberto $
 ** Garbage Collector
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -23,11 +23,10 @@
 #include "ltm.h"
 #include "ltm.h"
 
 
 
 
-#define GCSTEPSIZE	1000
-#define GCSWEEPMAX	10
-#define GCSWEEPCOST	30
+#define GCSTEPSIZE	1024u
+#define GCSWEEPMAX	40
+#define GCSWEEPCOST	10
 #define GCFINALIZECOST	100
 #define GCFINALIZECOST	100
-#define GCSTEPMUL	8
 
 
 
 
 #define FIXEDMASK	bitmask(FIXEDBIT)
 #define FIXEDMASK	bitmask(FIXEDBIT)
@@ -411,12 +410,10 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_int32 count) {
   global_State *g = G(L);
   global_State *g = G(L);
   int whitebit = otherwhite(g);
   int whitebit = otherwhite(g);
   int deadmask = whitebit | FIXEDMASK;
   int deadmask = whitebit | FIXEDMASK;
-  int generational = g->gcgenerational;
   while ((curr = *p) != NULL && count-- > 0) {
   while ((curr = *p) != NULL && count-- > 0) {
     if ((curr->gch.marked ^ whitebit) & deadmask) {
     if ((curr->gch.marked ^ whitebit) & deadmask) {
       lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));
       lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));
-      if (!generational || isdead(g, curr))
-        makewhite(g, curr);
+      makewhite(g, curr);
       if (curr->gch.tt == LUA_TTHREAD)
       if (curr->gch.tt == LUA_TTHREAD)
         sweepwholelist(L, &gco2th(curr)->openupval);
         sweepwholelist(L, &gco2th(curr)->openupval);
       p = &curr->gch.next;
       p = &curr->gch.next;
@@ -532,7 +529,6 @@ static void remarkupvals (global_State *g) {
 static void atomic (lua_State *L) {
 static void atomic (lua_State *L) {
   global_State *g = G(L);
   global_State *g = G(L);
   size_t udsize;  /* total size of userdata to be finalized */
   size_t udsize;  /* total size of userdata to be finalized */
-  int aux;
   /* remark objects cautch by write barrier */
   /* remark objects cautch by write barrier */
   propagateall(g);
   propagateall(g);
   /* remark occasional upvalues of (maybe) dead threads */
   /* remark occasional upvalues of (maybe) dead threads */
@@ -556,10 +552,6 @@ static void atomic (lua_State *L) {
   g->sweepstrgc = 0;
   g->sweepstrgc = 0;
   g->sweepgc = &g->rootgc;
   g->sweepgc = &g->rootgc;
   g->gcstate = GCSsweepstring;
   g->gcstate = GCSsweepstring;
-  aux = g->gcgenerational;
-  g->gcgenerational = g->incgc && (g->estimate/2 <= g->prevestimate);
-  if (!aux)  /* last collection was full? */
-    g->prevestimate = g->estimate;  /* keep estimate of last full collection */
   g->estimate = g->totalbytes - udsize;  /* first estimate */
   g->estimate = g->totalbytes - udsize;  /* first estimate */
 }
 }
 
 
@@ -569,11 +561,7 @@ static l_mem singlestep (lua_State *L) {
   /*lua_checkmemory(L);*/
   /*lua_checkmemory(L);*/
   switch (g->gcstate) {
   switch (g->gcstate) {
     case GCSpause: {
     case GCSpause: {
-      /* start a new collection */
-      if (g->gcgenerational)
-        atomic(L);
-      else
-        markroot(L);
+      markroot(L);  /* start a new collection */
       return 0;
       return 0;
     }
     }
     case GCSpropagate: {
     case GCSpropagate: {
@@ -613,6 +601,7 @@ static l_mem singlestep (lua_State *L) {
       }
       }
       else {
       else {
         g->gcstate = GCSpause;  /* end collection */
         g->gcstate = GCSpause;  /* end collection */
+        g->gcdept = 0;
         return 0;
         return 0;
       }
       }
     }
     }
@@ -623,25 +612,31 @@ static l_mem singlestep (lua_State *L) {
 
 
 void luaC_step (lua_State *L) {
 void luaC_step (lua_State *L) {
   global_State *g = G(L);
   global_State *g = G(L);
-  l_mem lim = (g->totalbytes - (g->GCthreshold - GCSTEPSIZE)) * GCSTEPMUL;
+  l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;
+  g->gcdept += g->totalbytes - g->GCthreshold;
   do {
   do {
     lim -= singlestep(L);
     lim -= singlestep(L);
     if (g->gcstate == GCSpause)
     if (g->gcstate == GCSpause)
       break;
       break;
-  } while (lim > 0 || !g->incgc);
-  if (g->gcstate != GCSpause)
-    g->GCthreshold = g->totalbytes + GCSTEPSIZE;  /* - lim/STEPMUL; */
+  } while (lim > 0);
+  if (g->gcstate != GCSpause) {
+    if (g->gcdept < GCSTEPSIZE)
+      g->GCthreshold = g->totalbytes + GCSTEPSIZE;  /* - lim/g->gcstepmul;*/
+    else {
+      g->gcdept -= GCSTEPSIZE;
+      g->GCthreshold = g->totalbytes;
+    }
+  }
   else {
   else {
     lua_assert(g->totalbytes >= g->estimate);
     lua_assert(g->totalbytes >= g->estimate);
-    g->GCthreshold = g->estimate + ((g->estimate/GCDIV) * g->gcpace);
+    g->GCthreshold = (g->estimate/100) * g->gcpace;
   }
   }
 }
 }
 
 
 
 
 void luaC_fullgc (lua_State *L) {
 void luaC_fullgc (lua_State *L) {
   global_State *g = G(L);
   global_State *g = G(L);
-  if (g->gcstate <= GCSpropagate || g->gcgenerational) {
-    g->gcgenerational = 0;
+  if (g->gcstate <= GCSpropagate) {
     /* reset sweep marks to sweep all elements (returning them to white) */
     /* reset sweep marks to sweep all elements (returning them to white) */
     g->sweepstrgc = 0;
     g->sweepstrgc = 0;
     g->sweepgc = &g->rootgc;
     g->sweepgc = &g->rootgc;
@@ -657,10 +652,8 @@ void luaC_fullgc (lua_State *L) {
     singlestep(L);
     singlestep(L);
   }
   }
   markroot(L);
   markroot(L);
-  lua_assert(!g->gcgenerational);
   while (g->gcstate != GCSpause) {
   while (g->gcstate != GCSpause) {
     singlestep(L);
     singlestep(L);
-    g->gcgenerational = 0;  /* keep it in this mode */
   }
   }
   g->GCthreshold = 2*g->estimate;
   g->GCthreshold = 2*g->estimate;
 }
 }
@@ -669,11 +662,10 @@ void luaC_fullgc (lua_State *L) {
 void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
 void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
   global_State *g = G(L);
   global_State *g = G(L);
   lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
   lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
-  lua_assert(g->gcgenerational ||
-             (g->gcstate != GCSfinalize && g->gcstate != GCSpause));
+  lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
   lua_assert(ttype(&o->gch) != LUA_TTABLE);
   lua_assert(ttype(&o->gch) != LUA_TTABLE);
   /* must keep invariant? */
   /* must keep invariant? */
-  if (g->gcstate == GCSpropagate || g->gcgenerational)
+  if (g->gcstate == GCSpropagate)
     reallymarkobject(g, v);  /* restore invariant */
     reallymarkobject(g, v);  /* restore invariant */
   else  /* don't mind */
   else  /* don't mind */
     makewhite(g, o);  /* mark as white just to avoid other barriers */
     makewhite(g, o);  /* mark as white just to avoid other barriers */
@@ -683,8 +675,7 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
 void luaC_barrierback (lua_State *L, GCObject *o, GCObject *v) {
 void luaC_barrierback (lua_State *L, GCObject *o, GCObject *v) {
   global_State *g = G(L);
   global_State *g = G(L);
   lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
   lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
-  lua_assert(g->gcgenerational ||
-             (g->gcstate != GCSfinalize && g->gcstate != GCSpause));
+  lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
   black2gray(o);  /* make table gray (again) */
   black2gray(o);  /* make table gray (again) */
   gco2h(o)->gclist = g->grayagain;
   gco2h(o)->gclist = g->grayagain;
   g->grayagain = o;
   g->grayagain = o;
@@ -706,7 +697,7 @@ void luaC_linkupval (lua_State *L, UpVal *uv) {
   o->gch.next = g->rootgc;  /* link upvalue into `rootgc' list */
   o->gch.next = g->rootgc;  /* link upvalue into `rootgc' list */
   g->rootgc = o;
   g->rootgc = o;
   if (isgray(o)) { 
   if (isgray(o)) { 
-    if (g->gcstate == GCSpropagate || g->gcgenerational) {
+    if (g->gcstate == GCSpropagate) {
       gray2black(o);  /* closed upvalues need barrier */
       gray2black(o);  /* closed upvalues need barrier */
       luaC_barrier(L, uv, uv->v);
       luaC_barrier(L, uv, uv->v);
     }
     }

+ 1 - 3
llimits.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: llimits.h,v 1.61 2004/11/24 18:55:56 roberto Exp roberto $
+** $Id: llimits.h,v 1.62 2004/12/13 12:15:11 roberto Exp roberto $
 ** Limits, basic types, and some other `installation-dependent' definitions
 ** Limits, basic types, and some other `installation-dependent' definitions
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -73,8 +73,6 @@ typedef LUA_UACNUMBER l_uacNumber;
 typedef lu_int32 Instruction;
 typedef lu_int32 Instruction;
 
 
 
 
-/* divisor for GC pace */
-#define GCDIV		8
 
 
 /* maximum stack for a Lua function */
 /* maximum stack for a Lua function */
 #define MAXSTACK	250
 #define MAXSTACK	250

+ 4 - 5
lstate.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.c,v 2.20 2005/01/04 15:55:12 roberto Exp roberto $
+** $Id: lstate.c,v 2.21 2005/01/05 18:20:51 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -95,7 +95,6 @@ static void f_luaopen (lua_State *L, void *ud) {
   luaX_init(L);
   luaX_init(L);
   luaS_fix(luaS_newliteral(L, MEMERRMSG));
   luaS_fix(luaS_newliteral(L, MEMERRMSG));
   g->GCthreshold = 4*g->totalbytes;
   g->GCthreshold = 4*g->totalbytes;
-  g->prevestimate = g->estimate = g->totalbytes;
 }
 }
 
 
 
 
@@ -180,7 +179,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   luaZ_initbuffer(L, &g->buff);
   luaZ_initbuffer(L, &g->buff);
   g->panic = NULL;
   g->panic = NULL;
   g->gcstate = GCSpause;
   g->gcstate = GCSpause;
-  g->gcgenerational = 0;
   g->rootgc = obj2gco(L);
   g->rootgc = obj2gco(L);
   g->sweepstrgc = 0;
   g->sweepstrgc = 0;
   g->sweepgc = &g->rootgc;
   g->sweepgc = &g->rootgc;
@@ -190,8 +188,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g->weak = NULL;
   g->weak = NULL;
   g->tmudata = NULL;
   g->tmudata = NULL;
   g->totalbytes = sizeof(LG);
   g->totalbytes = sizeof(LG);
-  g->gcpace = GCDIV;
-  g->incgc = 1;
+  g->gcpace = 200;  /* 200% (wait memory to double before next collection) */
+  g->gcstepmul = 200;  /* GC runs `twice the speed' of memory allocation */
+  g->gcdept = 0;
   if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
   if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
     /* memory allocation error: free partial state */
     /* memory allocation error: free partial state */
     close_state(L);
     close_state(L);

+ 4 - 5
lstate.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.h,v 2.10 2004/12/13 12:15:11 roberto Exp roberto $
+** $Id: lstate.h,v 2.11 2005/01/05 18:20:51 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -71,7 +71,6 @@ typedef struct global_State {
   void *ud;         /* auxiliary data to `realloc' */
   void *ud;         /* auxiliary data to `realloc' */
   lu_byte currentwhite;
   lu_byte currentwhite;
   lu_byte gcstate;  /* state of garbage collector */
   lu_byte gcstate;  /* state of garbage collector */
-  lu_byte gcgenerational;
   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' */
@@ -84,9 +83,9 @@ typedef struct global_State {
   lu_mem GCthreshold;
   lu_mem GCthreshold;
   lu_mem totalbytes;  /* number of bytes currently allocated */
   lu_mem totalbytes;  /* number of bytes currently allocated */
   lu_mem estimate;  /* an estimate of number of bytes actually in use */
   lu_mem estimate;  /* an estimate of number of bytes actually in use */
-  lu_mem prevestimate;  /* previous estimate */
-  int gcpace;  /* relative `speed' of the GC */
-  int incgc;  /* 0 if GC is done non-incrementally */
+  lu_mem gcdept;  /* how much GC is `behind schedule' */
+  int gcpace;  /* size of pause between successive GCs */
+  int gcstepmul;  /* GC `granularity' */
   lua_CFunction panic;  /* to be called in unprotected errors */
   lua_CFunction panic;  /* to be called in unprotected errors */
   TValue _registry;
   TValue _registry;
   struct lua_State *mainthread;
   struct lua_State *mainthread;

+ 5 - 6
ltests.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: ltests.c,v 2.15 2004/11/01 15:06:50 roberto Exp roberto $
+** $Id: ltests.c,v 2.16 2005/01/05 18:20:51 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -153,9 +153,9 @@ void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) {
 
 
 static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
 static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
   if (isdead(g,t)) return 0;
   if (isdead(g,t)) return 0;
-  if (g->gcstate == GCSpropagate || g->gcgenerational)
+  if (g->gcstate == GCSpropagate)
     return !isblack(f) || !iswhite(t);
     return !isblack(f) || !iswhite(t);
-  else if (g->gcstate == GCSfinalize && !g->gcgenerational)
+  else if (g->gcstate == GCSfinalize)
     return iswhite(f);
     return iswhite(f);
   else
   else
     return 1;
     return 1;
@@ -175,8 +175,7 @@ static void printobj (global_State *g, GCObject *o) {
 static int testobjref (global_State *g, GCObject *f, GCObject *t) {
 static int testobjref (global_State *g, GCObject *f, GCObject *t) {
   int r = testobjref1(g,f,t);
   int r = testobjref1(g,f,t);
   if (!r) {
   if (!r) {
-    printf("%d(%02X) %c - ", g->gcstate, g->currentwhite,
-                             g->gcgenerational ? 'G' : ' ');
+    printf("%d(%02X) - ", g->gcstate, g->currentwhite);
     printobj(g, f);
     printobj(g, f);
     printf("\t-> ");
     printf("\t-> ");
     printobj(g, t);
     printobj(g, t);
@@ -295,7 +294,7 @@ static void checkobject (global_State *g, GCObject *o) {
 printf(">>> %d  %s  %02x\n", g->gcstate, luaT_typenames[o->gch.tt], o->gch.marked);
 printf(">>> %d  %s  %02x\n", g->gcstate, luaT_typenames[o->gch.tt], o->gch.marked);
 }
 }
   else {
   else {
-    if (g->gcstate == GCSfinalize && !g->gcgenerational)
+    if (g->gcstate == GCSfinalize)
       lua_assert(iswhite(o));
       lua_assert(iswhite(o));
     switch (o->gch.tt) {
     switch (o->gch.tt) {
       case LUA_TUPVAL: {
       case LUA_TUPVAL: {

+ 2 - 2
lua.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lua.h,v 1.198 2005/01/07 19:53:32 roberto Exp roberto $
+** $Id: lua.h,v 1.199 2005/01/10 17:31:50 roberto Exp roberto $
 ** Lua - An Extensible Extension Language
 ** Lua - An Extensible Extension Language
 ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
 ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
 ** http://www.lua.org	mailto:[email protected]
 ** http://www.lua.org	mailto:[email protected]
@@ -227,7 +227,7 @@ LUA_API int  (lua_status) (lua_State *L);
 #define LUA_GCCOUNT		3
 #define LUA_GCCOUNT		3
 #define LUA_GCSTEP		4
 #define LUA_GCSTEP		4
 #define LUA_GCSETPACE		5
 #define LUA_GCSETPACE		5
-#define LUA_GCSETINCMODE	6
+#define LUA_GCSETSTEPMUL	6
 
 
 LUA_API int (lua_gc) (lua_State *L, int what, int data);
 LUA_API int (lua_gc) (lua_State *L, int what, int data);