diff --git a/lgc.c b/lgc.c index b83e6914..2d042390 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.62 2009/11/18 13:13:47 roberto Exp roberto $ +** $Id: lgc.c,v 2.63 2009/11/26 11:39:20 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -785,6 +785,21 @@ void luaC_step (lua_State *L) { } +/* +** advances the garbage collector until it reaches a "valid" state +** (defined by the caller) +*/ +void luaC_runtilstate (lua_State *L, int validstates) { + global_State *g = G(L); + while (!(g->gcstate & validstates)) + singlestep(L); +} + + +/* +** performs a full GC cycle; if "isememrgency", does not call +** finalizers (which could change stack positions) +*/ void luaC_fullgc (lua_State *L, int isemergency) { global_State *g = G(L); lua_assert(g->gckind == KGC_NORMAL); @@ -796,16 +811,13 @@ void luaC_fullgc (lua_State *L, int isemergency) { g->gcstate = GCSsweepstring; } /* finish any pending sweep phase */ - while (issweep(g)) singlestep(L); + luaC_runtilstate(L, ~(GCSsweepstring | GCSsweep)); markroot(L); /* start a new collection */ /* run collector up to finalizers */ - while (g->gcstate != GCSfinalize) - singlestep(L); + luaC_runtilstate(L, GCSfinalize); g->gckind = KGC_NORMAL; - if (!isemergency) { /* do not run finalizers during emergency GC */ - while (g->gcstate != GCSpause) - singlestep(L); - } + if (!isemergency) /* do not run finalizers during emergency GC */ + luaC_runtilstate(L, ~GCSfinalize); g->GCthreshold = (g->totalbytes/100) * g->gcpause; } diff --git a/lgc.h b/lgc.h index 7d32eab9..cc285b3e 100644 --- a/lgc.h +++ b/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.23 2009/11/18 13:13:47 roberto Exp roberto $ +** $Id: lgc.h,v 2.24 2009/11/26 11:39:20 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -14,16 +14,14 @@ /* ** Possible states of the Garbage Collector */ -#define GCSpause 0 -#define GCSpropagate 1 -#define GCSatomic 2 -#define GCSsweepstring 3 -#define GCSsweep 4 -#define GCSfinalize 5 +#define GCSpause 1 +#define GCSpropagate 2 +#define GCSatomic 4 +#define GCSsweepstring 8 +#define GCSsweep 16 +#define GCSfinalize 32 -#define issweep(g) (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) - /* ** some useful bit tricks @@ -98,6 +96,7 @@ LUAI_FUNC void luaC_separateudata (lua_State *L, int all); LUAI_FUNC void luaC_freeallobjects (lua_State *L); LUAI_FUNC void luaC_step (lua_State *L); +LUAI_FUNC void luaC_runtilstate (lua_State *L, int validstates); LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); diff --git a/lstring.c b/lstring.c index 281d35fd..b79cdb61 100644 --- a/lstring.c +++ b/lstring.c @@ -1,5 +1,5 @@ /* -** $Id: lstring.c,v 2.12 2009/04/17 14:40:13 roberto Exp roberto $ +** $Id: lstring.c,v 2.13 2009/04/29 17:09:41 roberto Exp roberto $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -22,8 +22,8 @@ void luaS_resize (lua_State *L, int newsize) { int i; stringtable *tb = &G(L)->strt; - if (G(L)->gcstate == GCSsweepstring) - return; /* cannot resize during GC traverse */ + /* cannot resize while GC is traversing strings */ + luaC_runtilstate(L, ~GCSsweepstring); if (newsize > tb->size) { luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL; diff --git a/ltests.c b/ltests.c index 29908c1c..0e1c9226 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.81 2009/12/01 16:49:48 roberto Exp roberto $ +** $Id: ltests.c,v 2.82 2009/12/10 18:21:28 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -167,6 +167,9 @@ void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) { ** ======================================================= */ +#define issweep(g) (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) + + static int testobjref1 (global_State *g, GCObject *f, GCObject *t) { if (isdead(g,t)) return 0; if (g->gcstate == GCSpropagate)