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