aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-09-24 18:00:40 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-09-24 18:00:40 -0300
commit95ed6c1127e3d2902ea460947c69a1c14096508a (patch)
tree36a0672a38ece126177ad061e8e734820757f7d3
parent12ab78aca654a45a9409d732b335dd541d8bb488 (diff)
downloadlua-95ed6c1127e3d2902ea460947c69a1c14096508a.tar.gz
lua-95ed6c1127e3d2902ea460947c69a1c14096508a.tar.bz2
lua-95ed6c1127e3d2902ea460947c69a1c14096508a.zip
better(?) scheme for cleaning weak tables; all ressurected objects
are removed from weak values before finalization
-rw-r--r--lgc.c62
1 files changed, 44 insertions, 18 deletions
diff --git a/lgc.c b/lgc.c
index 1c705014..89cdd2c5 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.109 2011/05/05 19:42:25 roberto Exp roberto $ 2** $Id: lgc.c,v 2.110 2011/09/19 17:03:38 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*/
@@ -116,13 +116,13 @@ static void removeentry (Node *n) {
116** other objects: if really collected, cannot keep them; for objects 116** other objects: if really collected, cannot keep them; for objects
117** being finalized, keep them in keys, but not in values 117** being finalized, keep them in keys, but not in values
118*/ 118*/
119static int iscleared (const TValue *o, int iskey) { 119static int iscleared (const TValue *o) {
120 if (!iscollectable(o)) return 0; 120 if (!iscollectable(o)) return 0;
121 else if (ttisstring(o)) { 121 else if (ttisstring(o)) {
122 stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ 122 stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */
123 return 0; 123 return 0;
124 } 124 }
125 else return iswhite(gcvalue(o)) || (!iskey && isfinalized(gcvalue(o))); 125 else return iswhite(gcvalue(o));
126} 126}
127 127
128 128
@@ -373,14 +373,14 @@ static int traverseephemeron (global_State *g, Table *h) {
373 checkdeadkey(n); 373 checkdeadkey(n);
374 if (ttisnil(gval(n))) /* entry is empty? */ 374 if (ttisnil(gval(n))) /* entry is empty? */
375 removeentry(n); /* remove it */ 375 removeentry(n); /* remove it */
376 else if (iscleared(gkey(n), 1)) { /* key is not marked (yet)? */ 376 else if (iscleared(gkey(n))) { /* key is not marked (yet)? */
377 hasclears = 1; /* table still have white keys */ 377 hasclears = 1; /* table must be cleared */
378 if (valiswhite(gval(n))) /* value not marked yet? */ 378 if (valiswhite(gval(n))) /* value not marked yet? */
379 prop = 1; 379 prop = 1; /* must propagate again */
380 } 380 }
381 else if (valiswhite(gval(n))) { /* value not marked yet? */ 381 else if (valiswhite(gval(n))) { /* value not marked yet? */
382 marked = 1; /* mark it now */ 382 marked = 1;
383 reallymarkobject(g, gcvalue(gval(n))); 383 reallymarkobject(g, gcvalue(gval(n))); /* mark it now */
384 } 384 }
385 } 385 }
386 if (prop) 386 if (prop)
@@ -566,21 +566,39 @@ static void convergeephemerons (global_State *g) {
566 566
567 567
568/* 568/*
569** clear collected entries from all weaktables in list 'l' 569** clear entries with unmarked keys from all weaktables in list 'l' up
570** to element 'f'
571*/
572static void clearkeys (GCObject *l, GCObject *f) {
573 for (; l != f; l = gco2t(l)->gclist) {
574 Table *h = gco2t(l);
575 Node *n, *limit = gnode(h, sizenode(h));
576 for (n = gnode(h, 0); n < limit; n++) {
577 if (!ttisnil(gval(n)) && (iscleared(gkey(n)))) {
578 setnilvalue(gval(n)); /* remove value ... */
579 removeentry(n); /* and remove entry from table */
580 }
581 }
582 }
583}
584
585
586/*
587** clear entries with unmarked values from all weaktables in list 'l' up
588** to element 'f'
570*/ 589*/
571static void cleartable (GCObject *l) { 590static void clearvalues (GCObject *l, GCObject *f) {
572 for (; l != NULL; l = gco2t(l)->gclist) { 591 for (; l != f; l = gco2t(l)->gclist) {
573 Table *h = gco2t(l); 592 Table *h = gco2t(l);
574 Node *n, *limit = gnode(h, sizenode(h)); 593 Node *n, *limit = gnode(h, sizenode(h));
575 int i; 594 int i;
576 for (i = 0; i < h->sizearray; i++) { 595 for (i = 0; i < h->sizearray; i++) {
577 TValue *o = &h->array[i]; 596 TValue *o = &h->array[i];
578 if (iscleared(o, 0)) /* value was collected? */ 597 if (iscleared(o)) /* value was collected? */
579 setnilvalue(o); /* remove value */ 598 setnilvalue(o); /* remove value */
580 } 599 }
581 for (n = gnode(h, 0); n < limit; n++) { 600 for (n = gnode(h, 0); n < limit; n++) {
582 if (!ttisnil(gval(n)) && /* non-empty entry? */ 601 if (!ttisnil(gval(n)) && iscleared(gval(n))) {
583 (iscleared(gkey(n), 1) || iscleared(gval(n), 0))) {
584 setnilvalue(gval(n)); /* remove value ... */ 602 setnilvalue(gval(n)); /* remove value ... */
585 removeentry(n); /* and remove entry from table */ 603 removeentry(n); /* and remove entry from table */
586 } 604 }
@@ -862,6 +880,7 @@ void luaC_freeallobjects (lua_State *L) {
862 880
863static void atomic (lua_State *L) { 881static void atomic (lua_State *L) {
864 global_State *g = G(L); 882 global_State *g = G(L);
883 GCObject *origweak, *origall;
865 lua_assert(!iswhite(obj2gco(g->mainthread))); 884 lua_assert(!iswhite(obj2gco(g->mainthread)));
866 markobject(g, L); /* mark running thread */ 885 markobject(g, L); /* mark running thread */
867 /* registry and global metatables may be changed by API */ 886 /* registry and global metatables may be changed by API */
@@ -876,14 +895,21 @@ static void atomic (lua_State *L) {
876 traverselistofgrays(g, &g->ephemeron); /* remark ephemeron tables */ 895 traverselistofgrays(g, &g->ephemeron); /* remark ephemeron tables */
877 convergeephemerons(g); 896 convergeephemerons(g);
878 /* at this point, all strongly accessible objects are marked. */ 897 /* at this point, all strongly accessible objects are marked. */
879 luaC_separateudata(L, 0); /* separate userdata to be finalized */ 898 /* clear values from weak tables, before checking finalizers */
899 clearvalues(g->weak, NULL);
900 clearvalues(g->allweak, NULL);
901 origweak = g->weak; origall = g->allweak;
902 luaC_separateudata(L, 0); /* separate objects to be finalized */
880 markbeingfnz(g); /* mark userdata that will be finalized */ 903 markbeingfnz(g); /* mark userdata that will be finalized */
881 propagateall(g); /* remark, to propagate `preserveness' */ 904 propagateall(g); /* remark, to propagate `preserveness' */
882 convergeephemerons(g); 905 convergeephemerons(g);
906 /* at this point, all accessible objects are marked. */
883 /* remove collected objects from weak tables */ 907 /* remove collected objects from weak tables */
884 cleartable(g->weak); 908 clearkeys(g->ephemeron, NULL); /* clear keys from all ephemeron tables */
885 cleartable(g->ephemeron); 909 clearkeys(g->allweak, NULL); /* clear keys from all allweak tables */
886 cleartable(g->allweak); 910 /* clear values from weak tables accessible from separated objects */
911 clearvalues(g->weak, origweak);
912 clearvalues(g->allweak, origall);
887 g->sweepstrgc = 0; /* prepare to sweep strings */ 913 g->sweepstrgc = 0; /* prepare to sweep strings */
888 g->gcstate = GCSsweepstring; 914 g->gcstate = GCSsweepstring;
889 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ 915 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */