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 */ |
