Browse Source

bug: userdata to be collected still counts into new GC threshold,
increasing memory consumption

Roberto Ierusalimschy 22 years ago
parent
commit
a0a384a6b1
2 changed files with 16 additions and 10 deletions
  1. 14 8
      lgc.c
  2. 2 2
      lgc.h

+ 14 - 8
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.174 2003/07/07 13:32:19 roberto Exp roberto $
+** $Id: lgc.c,v 1.175 2003/07/16 20:49:02 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -108,7 +108,8 @@ static void marktmu (GCState *st) {
 
 
 /* move `dead' udata that need finalization to list `tmudata' */
-void luaC_separateudata (lua_State *L) {
+size_t luaC_separateudata (lua_State *L) {
+  size_t deadmem = 0;
   GCObject **p = &G(L)->rootudata;
   GCObject *curr;
   GCObject *collected = NULL;  /* to collect udata with gc event */
@@ -123,6 +124,7 @@ void luaC_separateudata (lua_State *L) {
       p = &curr->gch.next;
     }
     else {  /* must call its gc method */
+      deadmem += sizeudata(gcotou(curr)->uv.len);
       markfinalized(gcotou(curr));
       *p = curr->gch.next;
       curr->gch.next = NULL;  /* link `curr' at the end of `collected' list */
@@ -133,6 +135,7 @@ void luaC_separateudata (lua_State *L) {
   /* insert collected udata with gc event into `tmudata' list */
   *lastcollected = G(L)->tmudata;
   G(L)->tmudata = collected;
+  return deadmem;
 }
 
 
@@ -377,7 +380,7 @@ static void sweepstrings (lua_State *L, int all) {
 }
 
 
-static void checkSizes (lua_State *L) {
+static void checkSizes (lua_State *L, size_t deadmem) {
   /* check size of string hash */
   if (G(L)->strt.nuse < cast(lu_int32, G(L)->strt.size/4) &&
       G(L)->strt.size > MINSTRTABSIZE*2)
@@ -387,7 +390,8 @@ static void checkSizes (lua_State *L) {
     size_t newsize = luaZ_sizebuffer(&G(L)->buff) / 2;
     luaZ_resizebuffer(L, &G(L)->buff, newsize);
   }
-  G(L)->GCthreshold = 2*G(L)->nblocks;  /* new threshold */
+  lua_assert(G(L)->nblocks > deadmem);
+  G(L)->GCthreshold = 2*G(L)->nblocks - deadmem;  /* new threshold */
 }
 
 
@@ -440,24 +444,26 @@ static void markroot (GCState *st, lua_State *L) {
 }
 
 
-static void mark (lua_State *L) {
+static size_t mark (lua_State *L) {
+  size_t deadmem;
   GCState st;
   st.g = G(L);
   st.tmark = NULL;
   st.w = NULL;
   markroot(&st, L);
   propagatemarks(&st);  /* mark all reachable objects */
-  luaC_separateudata(L);  /* separate userdata to be preserved */
+  deadmem = luaC_separateudata(L);  /* separate userdata to be preserved */
   marktmu(&st);  /* mark `preserved' userdata */
   propagatemarks(&st);  /* remark, to propagate `preserveness' */
   cleartable(st.w);  /* remove collected objects from weak tables */
+  return deadmem;
 }
 
 
 void luaC_collectgarbage (lua_State *L) {
-  mark(L);
+  size_t deadmem = mark(L);
   luaC_sweep(L, 0);
-  checkSizes(L);
+  checkSizes(L, deadmem);
   luaC_callGCTM(L);
 }
 

+ 2 - 2
lgc.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 1.19 2003/02/28 19:45:15 roberto Exp $
+** $Id: lgc.h,v 1.20 2003/07/16 20:49:02 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -15,7 +15,7 @@
 	luaC_collectgarbage(L); }
 
 
-void luaC_separateudata (lua_State *L);
+size_t luaC_separateudata (lua_State *L);
 void luaC_callGCTM (lua_State *L);
 void luaC_sweep (lua_State *L, int all);
 void luaC_collectgarbage (lua_State *L);