From 398811a3131cb025ca61d1a0839e3f99ba632ae9 Mon Sep 17 00:00:00 2001
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Mon, 21 May 2012 10:18:10 -0300
Subject: simpler macro 'luaC_condGC' + better 'step' in 'lua_gc' + micro bug
 in 'luaC_checkfinalizer' (current sweep object could be removed from 'allgc'
 list)

---
 lapi.c | 18 +++++++++---------
 lgc.c  | 30 ++++++++++++++++++++++++------
 lgc.h  |  4 ++--
 3 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/lapi.c b/lapi.c
index 93616244..be4449f8 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.159 2011/11/30 12:32:05 roberto Exp roberto $
+** $Id: lapi.c,v 2.160 2012/05/11 19:22:33 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -1046,16 +1046,16 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
     case LUA_GCSTEP: {
       if (g->gckind == KGC_GEN) {  /* generational mode? */
         res = (g->lastmajormem == 0);  /* 1 if will do major collection */
-        luaC_step(L);  /* do a single step */
+        luaC_forcestep(L);  /* do a single step */
       }
       else {
-        while (data-- >= 0) {
-          luaC_step(L);
-          if (g->gcstate == GCSpause) {  /* end of cycle? */
-            res = 1;  /* signal it */
-            break;
-          }
-        }
+       lu_mem debt = cast(lu_mem, data) * 1024;  /* count in Kbytes */
+       if (g->gcrunning)
+         debt += g->GCdebt;  /* include current debt */
+       luaE_setdebt(g, debt);
+       luaC_forcestep(L);
+       if (g->gcstate == GCSpause)  /* end of cycle? */
+         res = 1;  /* signal it */
       }
       break;
     }
diff --git a/lgc.c b/lgc.c
index 219d86d9..435c5e48 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.122 2012/05/14 17:52:56 roberto Exp roberto $
+** $Id: lgc.c,v 2.123 2012/05/20 20:36:44 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -863,11 +863,18 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
     return;  /* nothing to be done */
   else {  /* move 'o' to 'finobj' list */
     GCObject **p;
-    for (p = &g->allgc; *p != o; p = &gch(*p)->next) ;
-    *p = gch(o)->next;  /* remove 'o' from root list */
-    gch(o)->next = g->finobj;  /* link it in list 'finobj' */
+    GCheader *ho = gch(o);
+    /* avoid removing current sweep object */
+    if (g->gcstate == GCSsweep && g->sweepgc == &ho->next) {
+      /* step to next object in the list */
+      g->sweepgc = (ho->next == NULL) ? NULL : &gch(ho->next)->next;
+    }
+    /* search for pointer pointing to 'o' */
+    for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ }
+    *p = ho->next;  /* remove 'o' from root list */
+    ho->next = g->finobj;  /* link it in list 'finobj' */
     g->finobj = o;
-    l_setbit(gch(o)->marked, SEPARATED);  /* mark it as such */
+    l_setbit(ho->marked, SEPARATED);  /* mark it as such */
     resetoldbit(o);  /* see MOVE OLD rule */
   }
 }
@@ -1085,7 +1092,7 @@ static void step (lua_State *L) {
 /*
 ** performs a basic GC step
 */
-void luaC_step (lua_State *L) {
+void luaC_forcestep (lua_State *L) {
   global_State *g = G(L);
   int i;
   if (isgenerational(g)) generationalcollection(L);
@@ -1096,6 +1103,17 @@ void luaC_step (lua_State *L) {
 }
 
 
+/*
+** performs a basic GC step only if collector is running
+*/
+void luaC_step (lua_State *L) {
+  global_State *g = G(L);
+  if (g->gcrunning) luaC_forcestep(L);
+  else luaE_setdebt(g, -GCSTEPSIZE);  /* avoid being called too often */
+}
+
+
+
 /*
 ** performs a full GC cycle; if "isemergency", does not call
 ** finalizers (which could change stack positions)
diff --git a/lgc.h b/lgc.h
index bc63ab98..f1c5eec5 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 2.53 2012/01/23 20:29:12 roberto Exp roberto $
+** $Id: lgc.h,v 2.54 2012/05/11 19:22:33 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -104,7 +104,7 @@
 
 
 #define luaC_condGC(L,c) \
-	{if (G(L)->GCdebt > 0 && G(L)->gcrunning) {c;}; condchangemem(L);}
+	{if (G(L)->GCdebt > 0) {c;}; condchangemem(L);}
 #define luaC_checkGC(L)		luaC_condGC(L, luaC_step(L);)
 
 
-- 
cgit v1.2.3-55-g6feb