diff options
-rw-r--r-- | lgc.c | 44 |
1 files changed, 19 insertions, 25 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.120 2012/05/08 13:53:33 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.121 2012/05/11 19:22:33 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 | */ |
@@ -65,12 +65,6 @@ | |||
65 | #define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) | 65 | #define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) |
66 | #define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) | 66 | #define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) |
67 | 67 | ||
68 | /* | ||
69 | ** dirty trick: we know that 'reallymarkobject' does not use 'g' when | ||
70 | ** object is a string | ||
71 | */ | ||
72 | #define stringmark(s) markobject(NULL, s) | ||
73 | |||
74 | 68 | ||
75 | #define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) | 69 | #define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) |
76 | 70 | ||
@@ -127,10 +121,10 @@ static void removeentry (Node *n) { | |||
127 | ** other objects: if really collected, cannot keep them; for objects | 121 | ** other objects: if really collected, cannot keep them; for objects |
128 | ** being finalized, keep them in keys, but not in values | 122 | ** being finalized, keep them in keys, but not in values |
129 | */ | 123 | */ |
130 | static int iscleared (const TValue *o) { | 124 | static int iscleared (global_State *g, const TValue *o) { |
131 | if (!iscollectable(o)) return 0; | 125 | if (!iscollectable(o)) return 0; |
132 | else if (ttisstring(o)) { | 126 | else if (ttisstring(o)) { |
133 | stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ | 127 | markobject(g, rawtsvalue(o)); /* strings are `values', so are never weak */ |
134 | return 0; | 128 | return 0; |
135 | } | 129 | } |
136 | else return iswhite(gcvalue(o)); | 130 | else return iswhite(gcvalue(o)); |
@@ -369,7 +363,7 @@ static void traverseweakvalue (global_State *g, Table *h) { | |||
369 | else { | 363 | else { |
370 | lua_assert(!ttisnil(gkey(n))); | 364 | lua_assert(!ttisnil(gkey(n))); |
371 | markvalue(g, gkey(n)); /* mark key */ | 365 | markvalue(g, gkey(n)); /* mark key */ |
372 | if (!hasclears && iscleared(gval(n))) /* is there a white value? */ | 366 | if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ |
373 | hasclears = 1; /* table will have to be cleared */ | 367 | hasclears = 1; /* table will have to be cleared */ |
374 | } | 368 | } |
375 | } | 369 | } |
@@ -398,7 +392,7 @@ static int traverseephemeron (global_State *g, Table *h) { | |||
398 | checkdeadkey(n); | 392 | checkdeadkey(n); |
399 | if (ttisnil(gval(n))) /* entry is empty? */ | 393 | if (ttisnil(gval(n))) /* entry is empty? */ |
400 | removeentry(n); /* remove it */ | 394 | removeentry(n); /* remove it */ |
401 | else if (iscleared(gkey(n))) { /* key is not marked (yet)? */ | 395 | else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */ |
402 | hasclears = 1; /* table must be cleared */ | 396 | hasclears = 1; /* table must be cleared */ |
403 | if (valiswhite(gval(n))) /* value not marked yet? */ | 397 | if (valiswhite(gval(n))) /* value not marked yet? */ |
404 | prop = 1; /* must propagate again */ | 398 | prop = 1; /* must propagate again */ |
@@ -467,15 +461,15 @@ static int traverseproto (global_State *g, Proto *f) { | |||
467 | int i; | 461 | int i; |
468 | if (f->cache && iswhite(obj2gco(f->cache))) | 462 | if (f->cache && iswhite(obj2gco(f->cache))) |
469 | f->cache = NULL; /* allow cache to be collected */ | 463 | f->cache = NULL; /* allow cache to be collected */ |
470 | stringmark(f->source); | 464 | markobject(g, f->source); |
471 | for (i = 0; i < f->sizek; i++) /* mark literals */ | 465 | for (i = 0; i < f->sizek; i++) /* mark literals */ |
472 | markvalue(g, &f->k[i]); | 466 | markvalue(g, &f->k[i]); |
473 | for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ | 467 | for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ |
474 | stringmark(f->upvalues[i].name); | 468 | markobject(g, f->upvalues[i].name); |
475 | for (i = 0; i < f->sizep; i++) /* mark nested protos */ | 469 | for (i = 0; i < f->sizep; i++) /* mark nested protos */ |
476 | markobject(g, f->p[i]); | 470 | markobject(g, f->p[i]); |
477 | for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ | 471 | for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ |
478 | stringmark(f->locvars[i].varname); | 472 | markobject(g, f->locvars[i].varname); |
479 | return TRAVCOST + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars; | 473 | return TRAVCOST + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars; |
480 | } | 474 | } |
481 | 475 | ||
@@ -613,12 +607,12 @@ static void convergeephemerons (global_State *g) { | |||
613 | ** clear entries with unmarked keys from all weaktables in list 'l' up | 607 | ** clear entries with unmarked keys from all weaktables in list 'l' up |
614 | ** to element 'f' | 608 | ** to element 'f' |
615 | */ | 609 | */ |
616 | static void clearkeys (GCObject *l, GCObject *f) { | 610 | static void clearkeys (global_State *g, GCObject *l, GCObject *f) { |
617 | for (; l != f; l = gco2t(l)->gclist) { | 611 | for (; l != f; l = gco2t(l)->gclist) { |
618 | Table *h = gco2t(l); | 612 | Table *h = gco2t(l); |
619 | Node *n, *limit = gnodelast(h); | 613 | Node *n, *limit = gnodelast(h); |
620 | for (n = gnode(h, 0); n < limit; n++) { | 614 | for (n = gnode(h, 0); n < limit; n++) { |
621 | if (!ttisnil(gval(n)) && (iscleared(gkey(n)))) { | 615 | if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { |
622 | setnilvalue(gval(n)); /* remove value ... */ | 616 | setnilvalue(gval(n)); /* remove value ... */ |
623 | removeentry(n); /* and remove entry from table */ | 617 | removeentry(n); /* and remove entry from table */ |
624 | } | 618 | } |
@@ -631,18 +625,18 @@ static void clearkeys (GCObject *l, GCObject *f) { | |||
631 | ** clear entries with unmarked values from all weaktables in list 'l' up | 625 | ** clear entries with unmarked values from all weaktables in list 'l' up |
632 | ** to element 'f' | 626 | ** to element 'f' |
633 | */ | 627 | */ |
634 | static void clearvalues (GCObject *l, GCObject *f) { | 628 | static void clearvalues (global_State *g, GCObject *l, GCObject *f) { |
635 | for (; l != f; l = gco2t(l)->gclist) { | 629 | for (; l != f; l = gco2t(l)->gclist) { |
636 | Table *h = gco2t(l); | 630 | Table *h = gco2t(l); |
637 | Node *n, *limit = gnodelast(h); | 631 | Node *n, *limit = gnodelast(h); |
638 | int i; | 632 | int i; |
639 | for (i = 0; i < h->sizearray; i++) { | 633 | for (i = 0; i < h->sizearray; i++) { |
640 | TValue *o = &h->array[i]; | 634 | TValue *o = &h->array[i]; |
641 | if (iscleared(o)) /* value was collected? */ | 635 | if (iscleared(g, o)) /* value was collected? */ |
642 | setnilvalue(o); /* remove value */ | 636 | setnilvalue(o); /* remove value */ |
643 | } | 637 | } |
644 | for (n = gnode(h, 0); n < limit; n++) { | 638 | for (n = gnode(h, 0); n < limit; n++) { |
645 | if (!ttisnil(gval(n)) && iscleared(gval(n))) { | 639 | if (!ttisnil(gval(n)) && iscleared(g, gval(n))) { |
646 | setnilvalue(gval(n)); /* remove value ... */ | 640 | setnilvalue(gval(n)); /* remove value ... */ |
647 | removeentry(n); /* and remove entry from table */ | 641 | removeentry(n); /* and remove entry from table */ |
648 | } | 642 | } |
@@ -945,8 +939,8 @@ static void atomic (lua_State *L) { | |||
945 | convergeephemerons(g); | 939 | convergeephemerons(g); |
946 | /* at this point, all strongly accessible objects are marked. */ | 940 | /* at this point, all strongly accessible objects are marked. */ |
947 | /* clear values from weak tables, before checking finalizers */ | 941 | /* clear values from weak tables, before checking finalizers */ |
948 | clearvalues(g->weak, NULL); | 942 | clearvalues(g, g->weak, NULL); |
949 | clearvalues(g->allweak, NULL); | 943 | clearvalues(g, g->allweak, NULL); |
950 | origweak = g->weak; origall = g->allweak; | 944 | origweak = g->weak; origall = g->allweak; |
951 | separatetobefnz(L, 0); /* separate objects to be finalized */ | 945 | separatetobefnz(L, 0); /* separate objects to be finalized */ |
952 | markbeingfnz(g); /* mark userdata that will be finalized */ | 946 | markbeingfnz(g); /* mark userdata that will be finalized */ |
@@ -954,11 +948,11 @@ static void atomic (lua_State *L) { | |||
954 | convergeephemerons(g); | 948 | convergeephemerons(g); |
955 | /* at this point, all resurrected objects are marked. */ | 949 | /* at this point, all resurrected objects are marked. */ |
956 | /* remove dead objects from weak tables */ | 950 | /* remove dead objects from weak tables */ |
957 | clearkeys(g->ephemeron, NULL); /* clear keys from all ephemeron tables */ | 951 | clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */ |
958 | clearkeys(g->allweak, NULL); /* clear keys from all allweak tables */ | 952 | clearkeys(g, g->allweak, NULL); /* clear keys from all allweak tables */ |
959 | /* clear values from resurrected weak tables */ | 953 | /* clear values from resurrected weak tables */ |
960 | clearvalues(g->weak, origweak); | 954 | clearvalues(g, g->weak, origweak); |
961 | clearvalues(g->allweak, origall); | 955 | clearvalues(g, g->allweak, origall); |
962 | g->sweepstrgc = 0; /* prepare to sweep strings */ | 956 | g->sweepstrgc = 0; /* prepare to sweep strings */ |
963 | g->gcstate = GCSsweepstring; | 957 | g->gcstate = GCSsweepstring; |
964 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ | 958 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ |