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 | |
parent | 0e60572606684458b18febfcef0bc68235b461f4 (diff) | |
download | lua-4df8800a01c7e44800ce59339c66b9257cd75c2a.tar.gz lua-4df8800a01c7e44800ce59339c66b9257cd75c2a.tar.bz2 lua-4df8800a01c7e44800ce59339c66b9257cd75c2a.zip |
cleaner way to free all objects
-rw-r--r-- | lfunc.c | 6 | ||||
-rw-r--r-- | lgc.c | 54 | ||||
-rw-r--r-- | lgc.h | 14 | ||||
-rw-r--r-- | lstate.c | 9 |
4 files changed, 40 insertions, 43 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lfunc.c,v 2.5 2004/11/24 19:20:21 roberto Exp $ | 2 | ** $Id: lfunc.c,v 2.7 2005/01/19 15:54:26 roberto Exp roberto $ |
3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -57,7 +57,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { | |||
57 | while ((p = ngcotouv(*pp)) != NULL && p->v >= level) { | 57 | while ((p = ngcotouv(*pp)) != NULL && p->v >= level) { |
58 | lua_assert(p->v != &p->u.value); | 58 | lua_assert(p->v != &p->u.value); |
59 | if (p->v == level) { /* found a corresponding upvalue? */ | 59 | if (p->v == level) { /* found a corresponding upvalue? */ |
60 | if (isdead(G(L), obj2gco(p))) /* is it dead? */ | 60 | if (isdead(g, obj2gco(p))) /* is it dead? */ |
61 | changewhite(obj2gco(p)); /* ressurect it */ | 61 | changewhite(obj2gco(p)); /* ressurect it */ |
62 | return p; | 62 | return p; |
63 | } | 63 | } |
@@ -106,7 +106,7 @@ void luaF_close (lua_State *L, StkId level) { | |||
106 | setobj(L, &uv->u.value, uv->v); | 106 | setobj(L, &uv->u.value, uv->v); |
107 | if (isgray(o)) { | 107 | if (isgray(o)) { |
108 | gray2black(o); /* closed upvalues are never gray */ | 108 | gray2black(o); /* closed upvalues are never gray */ |
109 | luaC_barrier(L, uv, uv->v); | 109 | luaC_barrier(L, uv, &uv->u.value); |
110 | } | 110 | } |
111 | uv->v = &uv->u.value; /* now current value lives here */ | 111 | uv->v = &uv->u.value; /* now current value lives here */ |
112 | luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ | 112 | luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ |
@@ -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 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 2.9 2004/09/15 20:38:15 roberto Exp $ | 2 | ** $Id: lgc.h,v 2.10 2005/01/19 15:54:26 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 | */ |
@@ -47,8 +47,10 @@ | |||
47 | ** bit 3 - for tables: has weak keys | 47 | ** bit 3 - for tables: has weak keys |
48 | ** bit 4 - for tables: has weak values | 48 | ** bit 4 - for tables: has weak values |
49 | ** bit 5 - object is fixed (should not be collected) | 49 | ** bit 5 - object is fixed (should not be collected) |
50 | ** bit 6 - object is "super" fixed (only the main thread) | ||
50 | */ | 51 | */ |
51 | 52 | ||
53 | |||
52 | #define WHITE0BIT 0 | 54 | #define WHITE0BIT 0 |
53 | #define WHITE1BIT 1 | 55 | #define WHITE1BIT 1 |
54 | #define BLACKBIT 2 | 56 | #define BLACKBIT 2 |
@@ -56,21 +58,23 @@ | |||
56 | #define KEYWEAKBIT 3 | 58 | #define KEYWEAKBIT 3 |
57 | #define VALUEWEAKBIT 4 | 59 | #define VALUEWEAKBIT 4 |
58 | #define FIXEDBIT 5 | 60 | #define FIXEDBIT 5 |
61 | #define SFIXEDBIT 6 | ||
62 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) | ||
59 | 63 | ||
60 | 64 | ||
61 | #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) | 65 | #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) |
62 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) | 66 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) |
63 | #define isgray(x) (!isblack(x) && !iswhite(x)) | 67 | #define isgray(x) (!isblack(x) && !iswhite(x)) |
64 | 68 | ||
65 | #define otherwhite(g) (g->currentwhite ^ bit2mask(WHITE0BIT, WHITE1BIT)) | 69 | #define otherwhite(g) (g->currentwhite ^ WHITEBITS) |
66 | #define isdead(g,v) ((v)->gch.marked & otherwhite(g)) | 70 | #define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) |
67 | 71 | ||
68 | #define changewhite(x) ((x)->gch.marked ^= bit2mask(WHITE0BIT, WHITE1BIT)) | 72 | #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) |
69 | #define gray2black(x) setbit((x)->gch.marked, BLACKBIT) | 73 | #define gray2black(x) setbit((x)->gch.marked, BLACKBIT) |
70 | 74 | ||
71 | #define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) | 75 | #define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) |
72 | 76 | ||
73 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite) | 77 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) |
74 | 78 | ||
75 | 79 | ||
76 | #define luaC_checkGC(L) { if (G(L)->totalbytes >= G(L)->GCthreshold) \ | 80 | #define luaC_checkGC(L) { if (G(L)->totalbytes >= G(L)->GCthreshold) \ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.22 2005/01/14 14:19:42 roberto Exp $ | 2 | ** $Id: lstate.c,v 2.23 2005/01/18 17:18:09 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -114,7 +114,7 @@ static void close_state (lua_State *L) { | |||
114 | global_State *g = G(L); | 114 | global_State *g = G(L); |
115 | luaF_close(L, L->stack); /* close all upvalues for this thread */ | 115 | luaF_close(L, L->stack); /* close all upvalues for this thread */ |
116 | luaC_freeall(L); /* collect all objects */ | 116 | luaC_freeall(L); /* collect all objects */ |
117 | lua_assert(g->rootgc == NULL); | 117 | lua_assert(g->rootgc == obj2gco(L)); |
118 | lua_assert(g->strt.nuse == 0); | 118 | lua_assert(g->strt.nuse == 0); |
119 | luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); | 119 | luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); |
120 | luaZ_freebuffer(L, &g->buff); | 120 | luaZ_freebuffer(L, &g->buff); |
@@ -156,8 +156,9 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
156 | g = &((LG *)L)->g; | 156 | g = &((LG *)L)->g; |
157 | L->next = NULL; | 157 | L->next = NULL; |
158 | L->tt = LUA_TTHREAD; | 158 | L->tt = LUA_TTHREAD; |
159 | L->marked = g->currentwhite = bitmask(WHITE0BIT); | 159 | g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); |
160 | setbit(L->marked, FIXEDBIT); | 160 | L->marked = luaC_white(g); |
161 | set2bits(L->marked, FIXEDBIT, SFIXEDBIT); | ||
161 | preinit_state(L, g); | 162 | preinit_state(L, g); |
162 | g->realloc = f; | 163 | g->realloc = f; |
163 | g->ud = ud; | 164 | g->ud = ud; |