commit ac27b7a84287a80488e3e34d4fa179df0b67c37c
parent 81e142fc14b6412f5854ffbc25c2a23f60e2e9ba
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Mon, 11 Nov 2002 09:52:21 -0200
avoid traversing extra elements when cleaning weak tables
Diffstat:
M | lgc.c | | | 73 | ++++++++++++++++++++++++++++++++++++++++--------------------------------- |
1 file changed, 40 insertions(+), 33 deletions(-)
diff --git a/lgc.c b/lgc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.c,v 1.154 2002/10/25 20:05:28 roberto Exp roberto $
+** $Id: lgc.c,v 1.155 2002/11/07 15:37:10 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -22,7 +22,9 @@
typedef struct GCState {
Table *tmark; /* list of marked tables to be visited */
- Table *toclear; /* list of visited weak tables (to be cleared after GC) */
+ Table *wk; /* list of visited key-weak tables (to be cleared after GC) */
+ Table *wv; /* list of visited value-weak tables */
+ Table *wkv; /* list of visited key-value weak tables */
lua_State *L;
} GCState;
@@ -198,10 +200,14 @@ static void traversetable (GCState *st, Table *h) {
marktable(st, h->metatable);
lua_assert(h->lsizenode || h->node == G(st->L)->dummynode);
if (h->mode & (WEAKKEY | WEAKVALUE)) { /* weak table? */
+ Table **weaklist;
weakkey = h->mode & WEAKKEY;
weakvalue = h->mode & WEAKVALUE;
- h->gclist = st->toclear; /* must be cleared after GC, ... */
- st->toclear = h; /* ... so put in the appropriate list */
+ weaklist = (weakkey && weakvalue) ? &st->wkv :
+ (weakkey) ? &st->wk :
+ &st->wv;
+ h->gclist = *weaklist; /* must be cleared after GC, ... */
+ *weaklist = h; /* ... so put in the appropriate list */
}
if (!weakvalue) {
i = sizearray(h);
@@ -241,14 +247,12 @@ static int valismarked (const TObject *o) {
*/
static void cleartablekeys (Table *h) {
for (; h; h = h->gclist) {
- lua_assert(h->mode & (WEAKKEY | WEAKVALUE));
- if ((h->mode & WEAKKEY)) { /* table may have collected keys? */
- int i = sizenode(h);
- while (i--) {
- Node *n = node(h, i);
- if (!valismarked(key(n))) /* key was collected? */
- removekey(n); /* remove entry from table */
- }
+ int i = sizenode(h);
+ lua_assert(h->mode & WEAKKEY);
+ while (i--) {
+ Node *n = node(h, i);
+ if (!valismarked(key(n))) /* key was collected? */
+ removekey(n); /* remove entry from table */
}
}
}
@@ -259,19 +263,18 @@ static void cleartablekeys (Table *h) {
*/
static void cleartablevalues (Table *h) {
for (; h; h = h->gclist) {
- if ((h->mode & WEAKVALUE)) { /* table may have collected values? */
- int i = sizearray(h);
- while (i--) {
- TObject *o = &h->array[i];
- if (!valismarked(o)) /* value was collected? */
- setnilvalue(o); /* remove value */
- }
- i = sizenode(h);
- while (i--) {
- Node *n = node(h, i);
- if (!valismarked(val(n))) /* value was collected? */
- removekey(n); /* remove entry from table */
- }
+ int i = sizearray(h);
+ lua_assert(h->mode & WEAKVALUE);
+ while (i--) {
+ TObject *o = &h->array[i];
+ if (!valismarked(o)) /* value was collected? */
+ setnilvalue(o); /* remove value */
+ }
+ i = sizenode(h);
+ while (i--) {
+ Node *n = node(h, i);
+ if (!valismarked(val(n))) /* value was collected? */
+ removekey(n); /* remove entry from table */
}
}
}
@@ -398,22 +401,26 @@ static void markroot (GCState *st) {
static void mark (lua_State *L) {
GCState st;
- Table *toclear;
+ Table *wkv;
st.L = L;
st.tmark = NULL;
- st.toclear = NULL;
+ st.wkv = st.wk = st.wv = NULL;
markroot(&st);
propagatemarks(&st); /* mark all reachable objects */
- toclear = st.toclear; /* weak tables; to be cleared */
- st.toclear = NULL;
- cleartablevalues(toclear);
+ cleartablevalues(st.wkv);
+ cleartablevalues(st.wv);
+ wkv = st.wkv; /* keys must be cleared after preserving udata */
+ st.wkv = NULL;
+ st.wv = NULL;
separateudata(L); /* separate userdata to be preserved */
marktmu(&st); /* mark `preserved' userdata */
propagatemarks(&st); /* remark, to propagate `preserveness' */
- cleartablekeys(toclear);
+ cleartablekeys(wkv);
/* `propagatemarks' may reborne some weak tables; clear them too */
- cleartablekeys(st.toclear);
- cleartablevalues(st.toclear);
+ cleartablekeys(st.wk);
+ cleartablevalues(st.wv);
+ cleartablekeys(st.wkv);
+ cleartablevalues(st.wkv);
}