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);)