aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lgc.c30
1 files changed, 17 insertions, 13 deletions
diff --git a/lgc.c b/lgc.c
index 515cb76b..1c705014 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.108 2010/12/29 18:00:23 roberto Exp roberto $ 2** $Id: lgc.c,v 2.109 2011/05/05 19:42:25 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -357,7 +357,8 @@ static void traverseweakvalue (global_State *g, Table *h) {
357 357
358static int traverseephemeron (global_State *g, Table *h) { 358static int traverseephemeron (global_State *g, Table *h) {
359 int marked = 0; /* true if an object is marked in this traversal */ 359 int marked = 0; /* true if an object is marked in this traversal */
360 int hasclears = 0; /* true if table has unmarked pairs */ 360 int hasclears = 0; /* true if table has white keys */
361 int prop = 0; /* true if table has entry "white-key -> white-value" */
361 Node *n, *limit = gnode(h, sizenode(h)); 362 Node *n, *limit = gnode(h, sizenode(h));
362 int i; 363 int i;
363 /* traverse array part (numeric keys are 'strong') */ 364 /* traverse array part (numeric keys are 'strong') */
@@ -372,19 +373,22 @@ static int traverseephemeron (global_State *g, Table *h) {
372 checkdeadkey(n); 373 checkdeadkey(n);
373 if (ttisnil(gval(n))) /* entry is empty? */ 374 if (ttisnil(gval(n))) /* entry is empty? */
374 removeentry(n); /* remove it */ 375 removeentry(n); /* remove it */
376 else if (iscleared(gkey(n), 1)) { /* key is not marked (yet)? */
377 hasclears = 1; /* table still have white keys */
378 if (valiswhite(gval(n))) /* value not marked yet? */
379 prop = 1;
380 }
375 else if (valiswhite(gval(n))) { /* value not marked yet? */ 381 else if (valiswhite(gval(n))) { /* value not marked yet? */
376 if (iscleared(gkey(n), 1)) /* key is not marked (yet)? */ 382 marked = 1; /* mark it now */
377 hasclears = 1; /* may have to propagate mark from key to value */ 383 reallymarkobject(g, gcvalue(gval(n)));
378 else { /* key is marked, so mark value */
379 marked = 1; /* value was not marked */
380 reallymarkobject(g, gcvalue(gval(n)));
381 }
382 } 384 }
383 } 385 }
384 if (hasclears) /* does table have unmarked pairs? */ 386 if (prop)
385 linktable(h, &g->ephemeron); /* will have to propagate again */ 387 linktable(h, &g->ephemeron); /* have to propagate again */
386 else /* nothing to propagate */ 388 else if (hasclears) /* does table have white keys? */
387 linktable(h, &g->weak); /* avoid convergence phase */ 389 linktable(h, &g->allweak); /* may have to clean white keys */
390 else /* no white keys */
391 linktable(h, &g->grayagain); /* no need to clean */
388 return marked; 392 return marked;
389} 393}
390 394
@@ -868,8 +872,8 @@ static void atomic (lua_State *L) {
868 /* traverse objects caught by write barrier and by 'remarkupvals' */ 872 /* traverse objects caught by write barrier and by 'remarkupvals' */
869 propagateall(g); 873 propagateall(g);
870 traverselistofgrays(g, &g->weak); /* remark weak tables */ 874 traverselistofgrays(g, &g->weak); /* remark weak tables */
871 traverselistofgrays(g, &g->ephemeron); /* remark ephemeron tables */
872 traverselistofgrays(g, &g->grayagain); /* remark gray again */ 875 traverselistofgrays(g, &g->grayagain); /* remark gray again */
876 traverselistofgrays(g, &g->ephemeron); /* remark ephemeron tables */
873 convergeephemerons(g); 877 convergeephemerons(g);
874 /* at this point, all strongly accessible objects are marked. */ 878 /* at this point, all strongly accessible objects are marked. */
875 luaC_separateudata(L, 0); /* separate userdata to be finalized */ 879 luaC_separateudata(L, 0); /* separate userdata to be finalized */