Просмотр исходного кода

C functions and strings now go to the local list; first version
of the local collector

Roberto Ierusalimschy 12 лет назад
Родитель
Сommit
50955e27f5
6 измененных файлов с 107 добавлено и 15 удалено
  1. 3 2
      lfunc.c
  2. 94 8
      lgc.c
  3. 2 1
      lgc.h
  4. 3 1
      lstate.c
  5. 3 1
      lstate.h
  6. 2 2
      lstring.c

+ 3 - 2
lfunc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.c,v 2.32 2013/08/07 12:18:11 roberto Exp roberto $
+** $Id: lfunc.c,v 2.33 2013/08/16 18:55:49 roberto Exp roberto $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
@@ -21,7 +21,8 @@
 
 
 Closure *luaF_newCclosure (lua_State *L, int n) {
-  Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n), NULL, 0)->cl;
+  Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n),
+                               &G(L)->localgc, 0)->cl;
   c->c.nupvalues = cast_byte(n);
   return c;
 }

+ 94 - 8
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.149 2013/08/21 19:21:16 roberto Exp roberto $
+** $Id: lgc.c,v 2.150 2013/08/21 20:09:51 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -24,6 +24,12 @@
 
 
 
+/*
+** How memory to allocate before a new local collection
+*/
+#define GCLOCALPAUSE	8000
+
+
 /*
 ** cost of sweeping one element (the size of a small object divided
 ** by some adjust for the sweep speed)
@@ -191,9 +197,9 @@ void luaC_checkupvalcolor (global_State *g, UpVal *uv) {
 
 void luaC_fix (lua_State *L, GCObject *o) {
   global_State *g = G(L);
-  lua_assert(g->allgc == o);
+  lua_assert(g->localgc == o);
   white2gray(o);
-  g->allgc = o->gch.next;  /* remove object from 'allgc' list */
+  g->localgc = o->gch.next;  /* remove object from 'localgc' list */
   o->gch.next = g->fixedgc;  /* link it to 'fixedgc' list */
   g->fixedgc = o;
 }
@@ -873,6 +879,72 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
 /* }====================================================== */
 
 
+/*
+** {======================================================
+** Local Collection
+** =======================================================
+*/
+
+/*
+** Traverse a thread, local marking all its collectable objects
+*/
+static void localmarkthread (lua_State *l) {
+  StkId o = l->stack;
+  if (o == NULL)
+    return;  /* stack not completely built yet */
+  for (; o < l->top; o++) {  /* mark live elements in the stack */
+    if (iscollectable(o))
+      l_setbit(gcvalue(o)->gch.marked, LOCALBLACK);
+  }
+}
+
+
+/*
+** Mark all that is locally accessible (accessible directly from
+** a thread)
+*/
+static void localmark (global_State *g) {
+  GCObject *thread = hvalue(&g->l_registry)->next;
+  for (; thread != NULL; thread = gch(thread)->next)  /* traverse all threads */
+    localmarkthread(gco2th(thread));
+  localmarkthread(g->mainthread);
+}
+
+
+static void localsweep (lua_State *L, global_State *g) {
+  GCObject **p = &g->localgc;
+  while (*p != NULL) {
+    GCObject *curr = *p;
+    if (!islocal(curr)) {  /* is 'curr' no more local? */
+      *p = curr->gch.next;  /* remove 'curr' from list */
+      curr->gch.next = g->allgc;  /* link 'curr' in 'allgc' list */
+      g->allgc = curr;
+    }
+    else {  /* still local */
+      if (testbit(curr->gch.marked, LOCALBLACK)) {  /* locally alive? */
+        resetbit(curr->gch.marked, LOCALBLACK);
+        p = &curr->gch.next;  /* go to next element */
+      }
+      else {  /* object is dead */
+        *p = curr->gch.next;  /* remove 'curr' from list */
+        freeobj(L, curr);  /* erase 'curr' */
+      }
+    }
+  }
+}
+
+
+static void luaC_localcollection (lua_State *L) {
+  global_State *g = G(L);
+  lua_assert(g->gcstate == GCSpause);
+  localmark(g);
+  localsweep(L, g);
+}
+
+/* }====================================================== */
+
+
+
 /*
 ** {======================================================
 ** GC control
@@ -885,13 +957,13 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
 ** cycle will start when memory use hits threshold
 */
 static void setpause (global_State *g, l_mem estimate) {
-  l_mem debt, threshold;
+  l_mem threshold;
   estimate = estimate / PAUSEADJ;  /* adjust 'estimate' */
   threshold = (g->gcpause < MAX_LMEM / estimate)  /* overflow? */
             ? estimate * g->gcpause  /* no overflow */
             : MAX_LMEM;  /* overflow; truncate to maximum */
-  debt = -cast(l_mem, threshold - gettotalbytes(g));
-  luaE_setdebt(g, debt);
+  g->GCthreshold = threshold;
+  luaE_setdebt(g, -GCLOCALPAUSE);
 }
 
 
@@ -936,6 +1008,7 @@ void luaC_freeallobjects (lua_State *L) {
   g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */
   g->gckind = KGC_NORMAL;
   sweepwholelist(L, &g->finobj);  /* finalizers can create objs. in 'finobj' */
+  sweepwholelist(L, &g->localgc);
   sweepwholelist(L, &g->allgc);
   sweepwholelist(L, &g->fixedgc);  /* collect fixed objects */
   lua_assert(g->strt.nuse == 0);
@@ -1017,8 +1090,9 @@ static lu_mem singlestep (lua_State *L) {
         return GCSWEEPMAX*GCSWEEPCOST;
       }
       else {
+        sweepwholelist(L, &g->localgc);
         g->gcstate = GCSsweep;
-        return 0;
+        return GCLOCALPAUSE / 4;  /* some magic for now */
       }
     }
     case GCSsweep: {
@@ -1090,7 +1164,19 @@ void luaC_forcestep (lua_State *L) {
 */
 void luaC_step (lua_State *L) {
   global_State *g = G(L);
-  if (g->gcrunning) luaC_forcestep(L);
+  if (g->gcrunning) {
+    if (g->gcstate != GCSpause) {
+      luaC_forcestep(L);
+    }
+    else {
+      luaC_localcollection(L);
+      if (gettotalbytes(g) > g->GCthreshold) {
+        luaC_forcestep(L);  /* restart collection */
+      }
+      else
+        luaE_setdebt(g, -GCLOCALPAUSE);
+    }
+  }
   else luaE_setdebt(g, -GCSTEPSIZE);  /* avoid being called too often */
 }
 

+ 2 - 1
lgc.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 2.64 2013/08/21 19:21:16 roberto Exp roberto $
+** $Id: lgc.h,v 2.65 2013/08/21 20:09:51 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -77,6 +77,7 @@
 #define BLACKBIT	2  /* object is black */
 #define FINALIZEDBIT	3  /* object has been marked for finalization */
 #define LOCALBIT	4  /* object is not local */
+#define LOCALBLACK	5  /* object is 'locally black' */
 /* bit 7 is currently used by tests (luaL_checkmemory) */
 
 #define WHITEBITS	bit2mask(WHITE0BIT, WHITE1BIT)

+ 3 - 1
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 2.103 2013/08/21 19:21:16 roberto Exp roberto $
+** $Id: lstate.c,v 2.104 2013/08/21 20:09:51 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -280,6 +280,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g->seed = makeseed(L);
   g->gcrunning = 0;  /* no GC while building state */
   g->GCestimate = 0;
+  g->GCthreshold = 10000;
   g->strt.size = g->strt.nuse = g->strt.empty = 0;
   g->strt.hash = NULL;
   setnilvalue(&g->l_registry);
@@ -288,6 +289,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g->version = lua_version(NULL);
   g->gcstate = GCSpause;
   g->allgc = NULL;
+  g->localgc = NULL;
   g->finobj = NULL;
   g->tobefnz = NULL;
   g->fixedgc = NULL;

+ 3 - 1
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 2.87 2013/08/21 20:09:51 roberto Exp roberto $
+** $Id: lstate.h,v 2.88 2013/08/22 15:21:48 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -118,6 +118,7 @@ typedef struct global_State {
   l_mem GCdebt;  /* bytes allocated not yet compensated by the collector */
   lu_mem GCmemtrav;  /* memory traversed by the GC */
   lu_mem GCestimate;  /* an estimate of the non-garbage memory in use */
+  lu_mem GCthreshold;  /* threshold to start a new GC cycle */
   stringtable strt;  /* hash table for strings */
   TValue l_registry;
   unsigned int seed;  /* randomized seed for hashes */
@@ -126,6 +127,7 @@ typedef struct global_State {
   lu_byte gckind;  /* kind of GC running */
   lu_byte gcrunning;  /* true if GC is running */
   GCObject *allgc;  /* list of all collectable objects */
+  GCObject *localgc;  /* list of local objects */
   GCObject *finobj;  /* list of collectable objects with finalizers */
   GCObject **sweepgc;  /* current position of sweep in list 'allgc' */
   GCObject **sweepfin;  /* current position of sweep in list 'finobj' */

+ 2 - 2
lstring.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 2.29 2013/08/21 19:21:16 roberto Exp roberto $
+** $Id: lstring.c,v 2.30 2013/08/22 15:21:48 roberto Exp roberto $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -106,7 +106,7 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l,
   TString *ts;
   size_t totalsize;  /* total size of TString object */
   totalsize = sizeof(TString) + ((l + 1) * sizeof(char));
-  ts = &luaC_newobj(L, tag, totalsize, NULL, 0)->ts;
+  ts = &luaC_newobj(L, tag, totalsize, &G(L)->localgc, 0)->ts;
   ts->tsv.len = l;
   ts->tsv.hash = h;
   ts->tsv.extra = 0;