aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-10-03 13:22:05 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-10-03 13:22:05 -0300
commitbc90cf4b8313d88adc0c6e45961e3b4881a9566a (patch)
treec9756e135aad46b17ca4a7a30293bb2e144a1a69
parentd79190e27f6b43a61e490800ccae1ea4e874e7cd (diff)
downloadlua-bc90cf4b8313d88adc0c6e45961e3b4881a9566a.tar.gz
lua-bc90cf4b8313d88adc0c6e45961e3b4881a9566a.tar.bz2
lua-bc90cf4b8313d88adc0c6e45961e3b4881a9566a.zip
retraverse all gray lists together to avoid traversing some weak
tables twice (as they may change lists when traversed)
-rw-r--r--lgc.c48
1 files changed, 34 insertions, 14 deletions
diff --git a/lgc.c b/lgc.c
index 1c741a4a..d4f23f3f 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.110 2011/09/19 17:03:38 roberto Exp roberto $ 2** $Id: lgc.c,v 2.112 2011/09/24 21:12:01 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*/
@@ -153,7 +153,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
153*/ 153*/
154void luaC_barrierback_ (lua_State *L, GCObject *o) { 154void luaC_barrierback_ (lua_State *L, GCObject *o) {
155 global_State *g = G(L); 155 global_State *g = G(L);
156 lua_assert(isblack(o) && !isdead(g, o)); 156 lua_assert(isblack(o) && !isdead(g, o) && gch(o)->tt == LUA_TTABLE);
157 black2gray(o); /* make object gray (again) */ 157 black2gray(o); /* make object gray (again) */
158 gco2t(o)->gclist = g->grayagain; 158 gco2t(o)->gclist = g->grayagain;
159 g->grayagain = o; 159 g->grayagain = o;
@@ -343,6 +343,9 @@ static void markroot (global_State *g) {
343 343
344static void traverseweakvalue (global_State *g, Table *h) { 344static void traverseweakvalue (global_State *g, Table *h) {
345 Node *n, *limit = gnode(h, sizenode(h)); 345 Node *n, *limit = gnode(h, sizenode(h));
346 /* if there is array part, assume it may have white values (do not
347 traverse it just to check) */
348 int hasclears = (h->sizearray > 0);
346 for (n = gnode(h, 0); n < limit; n++) { 349 for (n = gnode(h, 0); n < limit; n++) {
347 checkdeadkey(n); 350 checkdeadkey(n);
348 if (ttisnil(gval(n))) /* entry is empty? */ 351 if (ttisnil(gval(n))) /* entry is empty? */
@@ -350,9 +353,14 @@ static void traverseweakvalue (global_State *g, Table *h) {
350 else { 353 else {
351 lua_assert(!ttisnil(gkey(n))); 354 lua_assert(!ttisnil(gkey(n)));
352 markvalue(g, gkey(n)); /* mark key */ 355 markvalue(g, gkey(n)); /* mark key */
356 if (!hasclears && iscleared(gval(n))) /* is there a white value? */
357 hasclears = 1; /* table will have to be cleared */
353 } 358 }
354 } 359 }
355 linktable(h, &g->weak); /* link into appropriate list */ 360 if (hasclears)
361 linktable(h, &g->weak); /* has to be cleared later */
362 else /* no white values */
363 linktable(h, &g->grayagain); /* no need to clean */
356} 364}
357 365
358 366
@@ -531,11 +539,26 @@ static void propagateall (global_State *g) {
531} 539}
532 540
533 541
534static void traverselistofgrays (global_State *g, GCObject **l) { 542static void propagatelist (global_State *g, GCObject *l) {
535 lua_assert(g->gray == NULL); /* no grays left */ 543 lua_assert(g->gray == NULL); /* no grays left */
536 g->gray = *l; /* now 'l' is new gray list */ 544 g->gray = l;
537 *l = NULL; 545 propagateall(g); /* traverse all elements from 'l' */
538 propagateall(g); 546}
547
548/*
549** retraverse all gray lists. Because tables may be reinserted in other
550** lists when traversed, traverse the original lists to avoid traversing
551** twice the same table (which is not wrong, but inefficient)
552*/
553static void retraversegrays (global_State *g) {
554 GCObject *weak = g->weak; /* save original lists */
555 GCObject *grayagain = g->grayagain;
556 GCObject *ephemeron = g->ephemeron;
557 g->weak = g->grayagain = g->ephemeron = NULL;
558 propagateall(g); /* traverse main gray list */
559 propagatelist(g, grayagain);
560 propagatelist(g, weak);
561 propagatelist(g, ephemeron);
539} 562}
540 563
541 564
@@ -890,10 +913,7 @@ static void atomic (lua_State *L) {
890 /* remark occasional upvalues of (maybe) dead threads */ 913 /* remark occasional upvalues of (maybe) dead threads */
891 remarkupvals(g); 914 remarkupvals(g);
892 /* traverse objects caught by write barrier and by 'remarkupvals' */ 915 /* traverse objects caught by write barrier and by 'remarkupvals' */
893 propagateall(g); 916 retraversegrays(g);
894 traverselistofgrays(g, &g->weak); /* remark weak tables */
895 traverselistofgrays(g, &g->grayagain); /* remark gray again */
896 traverselistofgrays(g, &g->ephemeron); /* remark ephemeron tables */
897 convergeephemerons(g); 917 convergeephemerons(g);
898 /* at this point, all strongly accessible objects are marked. */ 918 /* at this point, all strongly accessible objects are marked. */
899 /* clear values from weak tables, before checking finalizers */ 919 /* clear values from weak tables, before checking finalizers */
@@ -904,11 +924,11 @@ static void atomic (lua_State *L) {
904 markbeingfnz(g); /* mark userdata that will be finalized */ 924 markbeingfnz(g); /* mark userdata that will be finalized */
905 propagateall(g); /* remark, to propagate `preserveness' */ 925 propagateall(g); /* remark, to propagate `preserveness' */
906 convergeephemerons(g); 926 convergeephemerons(g);
907 /* at this point, all accessible objects are marked. */ 927 /* at this point, all resurrected objects are marked. */
908 /* remove collected objects from weak tables */ 928 /* remove dead objects from weak tables */
909 clearkeys(g->ephemeron, NULL); /* clear keys from all ephemeron tables */ 929 clearkeys(g->ephemeron, NULL); /* clear keys from all ephemeron tables */
910 clearkeys(g->allweak, NULL); /* clear keys from all allweak tables */ 930 clearkeys(g->allweak, NULL); /* clear keys from all allweak tables */
911 /* clear values from weak tables accessible from separated objects */ 931 /* clear values from resurrected weak tables */
912 clearvalues(g->weak, origweak); 932 clearvalues(g->weak, origweak);
913 clearvalues(g->allweak, origall); 933 clearvalues(g->allweak, origall);
914 g->sweepstrgc = 0; /* prepare to sweep strings */ 934 g->sweepstrgc = 0; /* prepare to sweep strings */