commit a2a2abcba4b3a221780a4499880aa16bf76e8204
parent 2e5179259655ffd137067f5dc47803740b7937ac
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Fri, 11 Dec 2009 17:14:35 -0200
new function 'luaC_runtilstate' to advance GC until a "valid" state
Diffstat:
4 files changed, 35 insertions(+), 21 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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)