diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-02-10 11:25:02 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2005-02-10 11:25:02 -0200 |
commit | 4df8800a01c7e44800ce59339c66b9257cd75c2a (patch) | |
tree | 226ae5cfc06164f6f01e33d778336c1ffd561d72 /lgc.c | |
parent | 0e60572606684458b18febfcef0bc68235b461f4 (diff) | |
download | lua-4df8800a01c7e44800ce59339c66b9257cd75c2a.tar.gz lua-4df8800a01c7e44800ce59339c66b9257cd75c2a.tar.bz2 lua-4df8800a01c7e44800ce59339c66b9257cd75c2a.zip |
cleaner way to free all objects
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 54 |
1 files changed, 23 insertions, 31 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.21 2005/01/14 14:19:42 roberto Exp $ | 2 | ** $Id: lgc.c,v 2.22 2005/01/18 17:18:09 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 | */ |
@@ -29,13 +29,11 @@ | |||
29 | #define GCFINALIZECOST 100 | 29 | #define GCFINALIZECOST 100 |
30 | 30 | ||
31 | 31 | ||
32 | #define FIXEDMASK bitmask(FIXEDBIT) | ||
33 | |||
34 | #define maskmarks \ | 32 | #define maskmarks \ |
35 | cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT))) | 33 | cast(lu_byte, ~(bitmask(BLACKBIT)|WHITEBITS)) |
36 | 34 | ||
37 | #define makewhite(g,x) \ | 35 | #define makewhite(g,x) \ |
38 | ((x)->gch.marked = ((x)->gch.marked & maskmarks) | g->currentwhite) | 36 | ((x)->gch.marked = ((x)->gch.marked & maskmarks) | luaC_white(g)) |
39 | 37 | ||
40 | #define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) | 38 | #define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) |
41 | #define gray2black(x) setbit((x)->gch.marked, BLACKBIT) | 39 | #define gray2black(x) setbit((x)->gch.marked, BLACKBIT) |
@@ -60,6 +58,8 @@ | |||
60 | reallymarkobject(g, obj2gco(t)); } | 58 | reallymarkobject(g, obj2gco(t)); } |
61 | 59 | ||
62 | 60 | ||
61 | #define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpace) | ||
62 | |||
63 | 63 | ||
64 | static void removeentry (Node *n) { | 64 | static void removeentry (Node *n) { |
65 | lua_assert(ttisnil(gval(n))); | 65 | lua_assert(ttisnil(gval(n))); |
@@ -400,24 +400,23 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
400 | 400 | ||
401 | 401 | ||
402 | 402 | ||
403 | #define sweepwholelist(L,p) sweeplist(L,p,LUA_MAXINT32) | 403 | #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) |
404 | 404 | ||
405 | 405 | ||
406 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_int32 count) { | 406 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { |
407 | GCObject *curr; | 407 | GCObject *curr; |
408 | global_State *g = G(L); | 408 | global_State *g = G(L); |
409 | int whitebit = otherwhite(g); | 409 | int deadmask = otherwhite(g); |
410 | int deadmask = whitebit | FIXEDMASK; | ||
411 | while ((curr = *p) != NULL && count-- > 0) { | 410 | while ((curr = *p) != NULL && count-- > 0) { |
412 | if ((curr->gch.marked ^ whitebit) & deadmask) { | 411 | if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ |
412 | sweepwholelist(L, &gco2th(curr)->openupval); | ||
413 | if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ | ||
413 | lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); | 414 | lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); |
414 | makewhite(g, curr); | 415 | makewhite(g, curr); /* make it white (for next cycle) */ |
415 | if (curr->gch.tt == LUA_TTHREAD) | ||
416 | sweepwholelist(L, &gco2th(curr)->openupval); | ||
417 | p = &curr->gch.next; | 416 | p = &curr->gch.next; |
418 | } | 417 | } |
419 | else { | 418 | else { /* must erase `curr' */ |
420 | lua_assert(isdead(g, curr)); | 419 | lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); |
421 | *p = curr->gch.next; | 420 | *p = curr->gch.next; |
422 | if (curr == g->rootgc) /* is the first element of the list? */ | 421 | if (curr == g->rootgc) /* is the first element of the list? */ |
423 | g->rootgc = curr->gch.next; /* adjust first */ | 422 | g->rootgc = curr->gch.next; /* adjust first */ |
@@ -428,21 +427,10 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_int32 count) { | |||
428 | } | 427 | } |
429 | 428 | ||
430 | 429 | ||
431 | |||
432 | static void freelist (lua_State *L, GCObject **p) { | ||
433 | while (*p) { | ||
434 | GCObject *curr = *p; | ||
435 | *p = (*p)->gch.next; | ||
436 | if (curr != obj2gco(L)) | ||
437 | freeobj(L, curr); | ||
438 | } | ||
439 | } | ||
440 | |||
441 | |||
442 | static void checkSizes (lua_State *L) { | 430 | static void checkSizes (lua_State *L) { |
443 | global_State *g = G(L); | 431 | global_State *g = G(L); |
444 | /* check size of string hash */ | 432 | /* check size of string hash */ |
445 | if (g->strt.nuse < cast(lu_int32, G(L)->strt.size/4) && | 433 | if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && |
446 | g->strt.size > MINSTRTABSIZE*2) | 434 | g->strt.size > MINSTRTABSIZE*2) |
447 | luaS_resize(L, g->strt.size/2); /* table is too big */ | 435 | luaS_resize(L, g->strt.size/2); /* table is too big */ |
448 | /* check size of buffer */ | 436 | /* check size of buffer */ |
@@ -487,9 +475,10 @@ void luaC_callGCTM (lua_State *L) { | |||
487 | void luaC_freeall (lua_State *L) { | 475 | void luaC_freeall (lua_State *L) { |
488 | global_State *g = G(L); | 476 | global_State *g = G(L); |
489 | int i; | 477 | int i; |
490 | freelist(L, &g->rootgc); | 478 | g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ |
479 | sweepwholelist(L, &g->rootgc); | ||
491 | for (i = 0; i < g->strt.size; i++) /* free all string lists */ | 480 | for (i = 0; i < g->strt.size; i++) /* free all string lists */ |
492 | freelist(L, &G(L)->strt.hash[i]); | 481 | sweepwholelist(L, &g->strt.hash[i]); |
493 | } | 482 | } |
494 | 483 | ||
495 | 484 | ||
@@ -604,6 +593,8 @@ static l_mem singlestep (lua_State *L) { | |||
604 | void luaC_step (lua_State *L) { | 593 | void luaC_step (lua_State *L) { |
605 | global_State *g = G(L); | 594 | global_State *g = G(L); |
606 | l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; | 595 | l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; |
596 | if (lim == 0) | ||
597 | lim = (MAX_LUMEM-1)/2; /* no limit */ | ||
607 | g->gcdept += g->totalbytes - g->GCthreshold; | 598 | g->gcdept += g->totalbytes - g->GCthreshold; |
608 | do { | 599 | do { |
609 | lim -= singlestep(L); | 600 | lim -= singlestep(L); |
@@ -620,7 +611,7 @@ void luaC_step (lua_State *L) { | |||
620 | } | 611 | } |
621 | else { | 612 | else { |
622 | lua_assert(g->totalbytes >= g->estimate); | 613 | lua_assert(g->totalbytes >= g->estimate); |
623 | g->GCthreshold = (g->estimate/100) * g->gcpace; | 614 | setthreshold(g); |
624 | } | 615 | } |
625 | } | 616 | } |
626 | 617 | ||
@@ -637,6 +628,7 @@ void luaC_fullgc (lua_State *L) { | |||
637 | g->weak = NULL; | 628 | g->weak = NULL; |
638 | g->gcstate = GCSsweepstring; | 629 | g->gcstate = GCSsweepstring; |
639 | } | 630 | } |
631 | lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); | ||
640 | /* finish any pending sweep phase */ | 632 | /* finish any pending sweep phase */ |
641 | while (g->gcstate != GCSfinalize) { | 633 | while (g->gcstate != GCSfinalize) { |
642 | lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); | 634 | lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); |
@@ -646,7 +638,7 @@ void luaC_fullgc (lua_State *L) { | |||
646 | while (g->gcstate != GCSpause) { | 638 | while (g->gcstate != GCSpause) { |
647 | singlestep(L); | 639 | singlestep(L); |
648 | } | 640 | } |
649 | g->GCthreshold = 2*g->estimate; | 641 | setthreshold(g); |
650 | } | 642 | } |
651 | 643 | ||
652 | 644 | ||