commit 45c346645c84b0d4750b254a1547051343fb26a3
parent 68ce878292cf7c571b8bc20f567e462ae62d859d
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Mon, 19 Sep 2011 14:03:14 -0300
avoid clearing ephemeron tables that have nothing to be cleaned
(no white elements)
Diffstat:
M | lgc.c | | | 30 | +++++++++++++++++------------- |
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/lgc.c b/lgc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.c,v 2.108 2010/12/29 18:00:23 roberto Exp roberto $
+** $Id: lgc.c,v 2.109 2011/05/05 19:42:25 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -357,7 +357,8 @@ static void traverseweakvalue (global_State *g, Table *h) {
static int traverseephemeron (global_State *g, Table *h) {
int marked = 0; /* true if an object is marked in this traversal */
- int hasclears = 0; /* true if table has unmarked pairs */
+ int hasclears = 0; /* true if table has white keys */
+ int prop = 0; /* true if table has entry "white-key -> white-value" */
Node *n, *limit = gnode(h, sizenode(h));
int i;
/* traverse array part (numeric keys are 'strong') */
@@ -372,19 +373,22 @@ static int traverseephemeron (global_State *g, Table *h) {
checkdeadkey(n);
if (ttisnil(gval(n))) /* entry is empty? */
removeentry(n); /* remove it */
+ else if (iscleared(gkey(n), 1)) { /* key is not marked (yet)? */
+ hasclears = 1; /* table still have white keys */
+ if (valiswhite(gval(n))) /* value not marked yet? */
+ prop = 1;
+ }
else if (valiswhite(gval(n))) { /* value not marked yet? */
- if (iscleared(gkey(n), 1)) /* key is not marked (yet)? */
- hasclears = 1; /* may have to propagate mark from key to value */
- else { /* key is marked, so mark value */
- marked = 1; /* value was not marked */
- reallymarkobject(g, gcvalue(gval(n)));
- }
+ marked = 1; /* mark it now */
+ reallymarkobject(g, gcvalue(gval(n)));
}
}
- if (hasclears) /* does table have unmarked pairs? */
- linktable(h, &g->ephemeron); /* will have to propagate again */
- else /* nothing to propagate */
- linktable(h, &g->weak); /* avoid convergence phase */
+ if (prop)
+ linktable(h, &g->ephemeron); /* have to propagate again */
+ else if (hasclears) /* does table have white keys? */
+ linktable(h, &g->allweak); /* may have to clean white keys */
+ else /* no white keys */
+ linktable(h, &g->grayagain); /* no need to clean */
return marked;
}
@@ -868,8 +872,8 @@ static void atomic (lua_State *L) {
/* traverse objects caught by write barrier and by 'remarkupvals' */
propagateall(g);
traverselistofgrays(g, &g->weak); /* remark weak tables */
- traverselistofgrays(g, &g->ephemeron); /* remark ephemeron tables */
traverselistofgrays(g, &g->grayagain); /* remark gray again */
+ traverselistofgrays(g, &g->ephemeron); /* remark ephemeron tables */
convergeephemerons(g);
/* at this point, all strongly accessible objects are marked. */
luaC_separateudata(L, 0); /* separate userdata to be finalized */