فهرست منبع

change in the relationship between totalbytes and GCdebt - luaM_realloc_
is too critical to update two counters

Roberto Ierusalimschy 14 سال پیش
والد
کامیت
551b076f1c
5فایلهای تغییر یافته به همراه35 افزوده شده و 26 حذف شده
  1. 4 4
      lapi.c
  2. 13 10
      lgc.c
  3. 2 3
      lmem.c
  4. 9 6
      lstate.c
  5. 7 3
      lstate.h

+ 4 - 4
lapi.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lapi.c,v 2.141 2010/11/26 14:32:31 roberto Exp roberto $
+** $Id: lapi.c,v 2.142 2010/12/20 18:17:46 roberto Exp roberto $
 ** Lua API
 ** Lua API
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -964,7 +964,7 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
       break;
       break;
     }
     }
     case LUA_GCRESTART: {
     case LUA_GCRESTART: {
-      g->GCdebt = 0;
+      luaE_setdebt(g, 0);
       g->gcrunning = 1;
       g->gcrunning = 1;
       break;
       break;
     }
     }
@@ -975,11 +975,11 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
     }
     }
     case LUA_GCCOUNT: {
     case LUA_GCCOUNT: {
       /* GC values are expressed in Kbytes: #bytes/2^10 */
       /* GC values are expressed in Kbytes: #bytes/2^10 */
-      res = cast_int(g->totalbytes >> 10);
+      res = cast_int(gettotalbytes(g) >> 10);
       break;
       break;
     }
     }
     case LUA_GCCOUNTB: {
     case LUA_GCCOUNTB: {
-      res = cast_int(g->totalbytes & 0x3ff);
+      res = cast_int(gettotalbytes(g) & 0x3ff);
       break;
       break;
     }
     }
     case LUA_GCSTEP: {
     case LUA_GCSTEP: {

+ 13 - 10
lgc.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lgc.c,v 2.105 2010/12/03 11:48:25 roberto Exp roberto $
+** $Id: lgc.c,v 2.106 2010/12/20 18:17:46 roberto Exp roberto $
 ** Garbage Collector
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -51,7 +51,7 @@
 ** standard negative debt for GC; a reasonable "time" to wait before
 ** standard negative debt for GC; a reasonable "time" to wait before
 ** starting a new cycle
 ** starting a new cycle
 */
 */
-#define stddebt(g)	(-cast(l_mem, g->totalbytes/100) * g->gcpause)
+#define stddebt(g)	(-cast(l_mem, gettotalbytes(g)/100) * g->gcpause)
 
 
 
 
 /*
 /*
@@ -634,6 +634,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
   int ow = otherwhite(g);
   int ow = otherwhite(g);
   int toclear, toset;  /* bits to clear and to set in all live objects */
   int toclear, toset;  /* bits to clear and to set in all live objects */
   int tostop;  /* stop sweep when this is true */
   int tostop;  /* stop sweep when this is true */
+  l_mem debt = g->GCdebt;  /* current debt */
   if (isgenerational(g)) {  /* generational mode? */
   if (isgenerational(g)) {  /* generational mode? */
     toclear = ~0;  /* clear nothing */
     toclear = ~0;  /* clear nothing */
     toset = bitmask(OLDBIT);  /* set the old bit of all surviving objects */
     toset = bitmask(OLDBIT);  /* set the old bit of all surviving objects */
@@ -656,13 +657,15 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
         sweepthread(L, gco2th(curr));  /* sweep thread's upvalues */
         sweepthread(L, gco2th(curr));  /* sweep thread's upvalues */
       if (testbits(marked, tostop)) {
       if (testbits(marked, tostop)) {
         static GCObject *nullp = NULL;
         static GCObject *nullp = NULL;
-        return &nullp;  /* stop sweeping this list */
+        p = &nullp;  /* stop sweeping this list */
+        break;
       }
       }
       /* update marks */
       /* update marks */
       gch(curr)->marked = cast_byte((marked & toclear) | toset);
       gch(curr)->marked = cast_byte((marked & toclear) | toset);
       p = &gch(curr)->next;  /* go to next element */
       p = &gch(curr)->next;  /* go to next element */
     }
     }
   }
   }
+  luaE_setdebt(g, debt);  /* sweeping should not change debt */
   return p;
   return p;
 }
 }
 
 
@@ -807,7 +810,7 @@ void luaC_changemode (lua_State *L, int mode) {
   if (mode == KGC_GEN) {  /* change to generational mode */
   if (mode == KGC_GEN) {  /* change to generational mode */
     /* make sure gray lists are consistent */
     /* make sure gray lists are consistent */
     luaC_runtilstate(L, bitmask(GCSpropagate));
     luaC_runtilstate(L, bitmask(GCSpropagate));
-    g->lastmajormem = g->totalbytes;
+    g->lastmajormem = gettotalbytes(g);
     g->gckind = KGC_GEN;
     g->gckind = KGC_GEN;
   }
   }
   else {  /* change to incremental mode */
   else {  /* change to incremental mode */
@@ -958,15 +961,15 @@ static void generationalcollection (lua_State *L) {
   global_State *g = G(L);
   global_State *g = G(L);
   if (g->lastmajormem == 0) {  /* signal for another major collection? */
   if (g->lastmajormem == 0) {  /* signal for another major collection? */
     luaC_fullgc(L, 0);  /* perform a full regular collection */
     luaC_fullgc(L, 0);  /* perform a full regular collection */
-    g->lastmajormem = g->totalbytes;  /* update control */
+    g->lastmajormem = gettotalbytes(g);  /* update control */
   }
   }
   else {
   else {
     luaC_runtilstate(L, ~bitmask(GCSpause));  /* run complete cycle */
     luaC_runtilstate(L, ~bitmask(GCSpause));  /* run complete cycle */
     luaC_runtilstate(L, bitmask(GCSpause));
     luaC_runtilstate(L, bitmask(GCSpause));
-    if (g->totalbytes > g->lastmajormem/100 * g->gcmajorinc)
+    if (gettotalbytes(g) > g->lastmajormem/100 * g->gcmajorinc)
       g->lastmajormem = 0;  /* signal for a major collection */
       g->lastmajormem = 0;  /* signal for a major collection */
   }
   }
-  g->GCdebt = stddebt(g);
+  luaE_setdebt(g, stddebt(g));
 }
 }
 
 
 
 
@@ -977,9 +980,9 @@ static void step (lua_State *L) {
     lim -= singlestep(L);
     lim -= singlestep(L);
   } while (lim > 0 && g->gcstate != GCSpause);
   } while (lim > 0 && g->gcstate != GCSpause);
   if (g->gcstate != GCSpause)
   if (g->gcstate != GCSpause)
-    g->GCdebt -= GCSTEPSIZE;
+    luaE_setdebt(g, g->GCdebt - GCSTEPSIZE);
   else
   else
-    g->GCdebt = stddebt(g);
+    luaE_setdebt(g, stddebt(g));
 }
 }
 
 
 
 
@@ -1022,7 +1025,7 @@ void luaC_fullgc (lua_State *L, int isemergency) {
     luaC_runtilstate(L, bitmask(GCSpropagate));
     luaC_runtilstate(L, bitmask(GCSpropagate));
   }
   }
   g->gckind = origkind;
   g->gckind = origkind;
-  g->GCdebt = stddebt(g);
+  luaE_setdebt(g, stddebt(g));
   if (!isemergency)   /* do not run finalizers during emergency GC */
   if (!isemergency)   /* do not run finalizers during emergency GC */
     callallpendingfinalizers(L, 1);
     callallpendingfinalizers(L, 1);
 }
 }

+ 2 - 3
lmem.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lmem.c,v 1.79 2010/05/05 18:49:56 roberto Exp roberto $
+** $Id: lmem.c,v 1.80 2010/12/20 18:17:46 roberto Exp roberto $
 ** Interface to Memory Manager
 ** Interface to Memory Manager
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -94,8 +94,7 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
       luaD_throw(L, LUA_ERRMEM);
       luaD_throw(L, LUA_ERRMEM);
   }
   }
   lua_assert((nsize == 0) == (newblock == NULL));
   lua_assert((nsize == 0) == (newblock == NULL));
-  g->totalbytes = (g->totalbytes - realosize) + nsize;
-  g->GCdebt += nsize;  /* give some credit to garbage collector */
+  g->GCdebt = (g->GCdebt + nsize) - realosize;
 #if defined(TRACEMEM)
 #if defined(TRACEMEM)
   { /* auxiliary patch to monitor garbage collection.
   { /* auxiliary patch to monitor garbage collection.
     ** To plot, gnuplot with following command:
     ** To plot, gnuplot with following command:

+ 9 - 6
lstate.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.c,v 2.87 2010/11/26 14:32:31 roberto Exp roberto $
+** $Id: lstate.c,v 2.88 2010/12/20 18:17:46 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -65,11 +65,14 @@ typedef struct LG {
 #define fromstate(L)	(cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
 #define fromstate(L)	(cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
 
 
 
 
-
 /*
 /*
-** maximum number of nested calls made by error-handling function
+** set GCdebt to a new value keeping the value (totalbytes + GCdebt)
+** invariant
 */
 */
-#define LUAI_EXTRACALLS		10
+void luaE_setdebt (global_State *g, l_mem debt) {
+  g->totalbytes -= (debt - g->GCdebt);
+  g->GCdebt = debt;
+}
 
 
 
 
 CallInfo *luaE_extendCI (lua_State *L) {
 CallInfo *luaE_extendCI (lua_State *L) {
@@ -154,7 +157,6 @@ static void f_luaopen (lua_State *L, void *ud) {
   /* pre-create memory-error message */
   /* pre-create memory-error message */
   g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
   g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
   luaS_fix(g->memerrmsg);  /* it should never be collected */
   luaS_fix(g->memerrmsg);  /* it should never be collected */
-  g->GCdebt = 0;
   g->gcrunning = 1;  /* allow gc */
   g->gcrunning = 1;  /* allow gc */
 }
 }
 
 
@@ -188,7 +190,7 @@ static void close_state (lua_State *L) {
   luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
   luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
   luaZ_freebuffer(L, &g->buff);
   luaZ_freebuffer(L, &g->buff);
   freestack(L);
   freestack(L);
-  lua_assert(g->totalbytes == sizeof(LG));
+  lua_assert(gettotalbytes(g) == sizeof(LG));
   (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0);
   (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0);
 }
 }
 
 
@@ -258,6 +260,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g->gray = g->grayagain = NULL;
   g->gray = g->grayagain = NULL;
   g->weak = g->ephemeron = g->allweak = NULL;
   g->weak = g->ephemeron = g->allweak = NULL;
   g->totalbytes = sizeof(LG);
   g->totalbytes = sizeof(LG);
+  g->GCdebt = 0;
   g->gcpause = LUAI_GCPAUSE;
   g->gcpause = LUAI_GCPAUSE;
   g->gcmajorinc = LUAI_GCMAJOR;
   g->gcmajorinc = LUAI_GCMAJOR;
   g->gcstepmul = LUAI_GCMUL;
   g->gcstepmul = LUAI_GCMUL;

+ 7 - 3
lstate.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lstate.h,v 2.69 2010/11/26 14:32:31 roberto Exp roberto $
+** $Id: lstate.h,v 2.70 2010/12/20 18:17:46 roberto Exp roberto $
 ** Global State
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -114,8 +114,8 @@ typedef struct CallInfo {
 typedef struct global_State {
 typedef struct global_State {
   lua_Alloc frealloc;  /* function to reallocate memory */
   lua_Alloc frealloc;  /* function to reallocate memory */
   void *ud;         /* auxiliary data to `frealloc' */
   void *ud;         /* auxiliary data to `frealloc' */
-  lu_mem totalbytes;  /* number of bytes currently allocated */
-  l_mem GCdebt;  /* when positive, run a GC step */
+  lu_mem totalbytes;  /* number of bytes currently allocated - GCdebt */
+  l_mem GCdebt;  /* bytes allocated not yet compensated by the collector */
   lu_mem lastmajormem;  /* memory in use after last major collection */
   lu_mem lastmajormem;  /* memory in use after last major collection */
   stringtable strt;  /* hash table for strings */
   stringtable strt;  /* hash table for strings */
   TValue l_registry;
   TValue l_registry;
@@ -210,6 +210,10 @@ union GCObject {
 #define obj2gco(v)	(cast(GCObject *, (v)))
 #define obj2gco(v)	(cast(GCObject *, (v)))
 
 
 
 
+/* actual number of total bytes allocated */
+#define gettotalbytes(g)	((g)->totalbytes + (g)->GCdebt)
+
+LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt);
 LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
 LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);
 LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
 LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L);
 LUAI_FUNC void luaE_freeCI (lua_State *L);
 LUAI_FUNC void luaE_freeCI (lua_State *L);