diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-12-03 18:03:07 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-12-03 18:03:07 -0200 |
commit | c6eac44a9420a26a2f8907dcd5266a6aecdb18ea (patch) | |
tree | acbf11560fe8aee5dddf37ff52b9fcaa6e697ca6 /lgc.c | |
parent | 8878554b854009066eeccfe7b17e6e019c69758a (diff) | |
download | lua-c6eac44a9420a26a2f8907dcd5266a6aecdb18ea.tar.gz lua-c6eac44a9420a26a2f8907dcd5266a6aecdb18ea.tar.bz2 lua-c6eac44a9420a26a2f8907dcd5266a6aecdb18ea.zip |
two different white flags (to distinguish dead elements from new ones)
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 79 |
1 files changed, 43 insertions, 36 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.182 2003/12/01 18:22:56 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.183 2003/12/03 12:30:41 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 | */ |
@@ -25,26 +25,27 @@ | |||
25 | #define GCSTEPSIZE (20*sizeof(TObject)) | 25 | #define GCSTEPSIZE (20*sizeof(TObject)) |
26 | 26 | ||
27 | 27 | ||
28 | #define otherwhite(g) (g->currentwhite ^ bit2mask(WHITE0BIT, WHITE1BIT)) | ||
28 | 29 | ||
29 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) | 30 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) |
30 | #define gray2black(x) ((x)->gch.marked++) | 31 | #define gray2black(x) setbit((x)->gch.marked, BLACKBIT) |
31 | #define white2black(x) setbit((x)->gch.marked, BLACKBIT) | ||
32 | 32 | ||
33 | #define iswhite(x) (!test2bits((x)->gch.marked, GRAYBIT, BLACKBIT)) | 33 | #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) |
34 | #define makewhite(x) reset2bits((x)->gch.marked, GRAYBIT, BLACKBIT) | 34 | #define maskmarks \ |
35 | cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT))) | ||
36 | #define makewhite(g,x) \ | ||
37 | ((x)->gch.marked = ((x)->gch.marked & maskmarks) | g->currentwhite) | ||
35 | 38 | ||
36 | #define isgray(x) testbit((x)->gch.marked, GRAYBIT) | 39 | #define isgray(x) (!isblack(x) && !iswhite(x)) |
37 | #define white2gray(x) setbit((x)->gch.marked, GRAYBIT) | 40 | #define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) |
38 | 41 | ||
39 | #define stringmark(s) setbit((s)->tsv.marked, BLACKBIT) | 42 | #define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) |
40 | 43 | ||
41 | 44 | ||
42 | #define isfinalized(u) testbit((u)->uv.marked, FINALIZEDBIT) | 45 | #define isfinalized(u) testbit((u)->uv.marked, FINALIZEDBIT) |
43 | #define markfinalized(u) setbit((u)->uv.marked, FINALIZEDBIT) | 46 | #define markfinalized(u) setbit((u)->uv.marked, FINALIZEDBIT) |
44 | 47 | ||
45 | 48 | ||
46 | #define maskbf bit2mask(BLACKBIT, FIXEDBIT) | ||
47 | |||
48 | 49 | ||
49 | #define KEYWEAK bitmask(KEYWEAKBIT) | 50 | #define KEYWEAK bitmask(KEYWEAKBIT) |
50 | #define VALUEWEAK bitmask(VALUEWEAKBIT) | 51 | #define VALUEWEAK bitmask(VALUEWEAKBIT) |
@@ -108,14 +109,14 @@ static size_t objsize (GCObject *o) { | |||
108 | 109 | ||
109 | static void reallymarkobject (global_State *g, GCObject *o) { | 110 | static void reallymarkobject (global_State *g, GCObject *o) { |
110 | lua_assert(iswhite(o)); | 111 | lua_assert(iswhite(o)); |
112 | lua_assert(!(o->gch.marked & otherwhite(g))); | ||
113 | white2gray(o); | ||
111 | switch (o->gch.tt) { | 114 | switch (o->gch.tt) { |
112 | case LUA_TSTRING: { | 115 | case LUA_TSTRING: { |
113 | white2black(o); /* strings do not go to gray list */ | ||
114 | return; | 116 | return; |
115 | } | 117 | } |
116 | case LUA_TUSERDATA: { | 118 | case LUA_TUSERDATA: { |
117 | Table *mt = gcotou(o)->uv.metatable; | 119 | Table *mt = gcotou(o)->uv.metatable; |
118 | white2black(o); /* userdata do not go to gray list */ | ||
119 | if (mt) markobject(g, mt); | 120 | if (mt) markobject(g, mt); |
120 | return; | 121 | return; |
121 | } | 122 | } |
@@ -142,14 +143,13 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
142 | default: lua_assert(0); | 143 | default: lua_assert(0); |
143 | } | 144 | } |
144 | g->gray = o; /* finish list linking */ | 145 | g->gray = o; /* finish list linking */ |
145 | white2gray(o); | ||
146 | } | 146 | } |
147 | 147 | ||
148 | 148 | ||
149 | static void marktmu (global_State *g) { | 149 | static void marktmu (global_State *g) { |
150 | GCObject *u; | 150 | GCObject *u; |
151 | for (u = g->tmudata; u; u = u->gch.next) { | 151 | for (u = g->tmudata; u; u = u->gch.next) { |
152 | makewhite(u); /* may be marked, if left from previous GC */ | 152 | makewhite(g, u); /* may be marked, if left from previous GC */ |
153 | reallymarkobject(g, u); | 153 | reallymarkobject(g, u); |
154 | } | 154 | } |
155 | } | 155 | } |
@@ -164,9 +164,8 @@ size_t luaC_separateudata (lua_State *L) { | |||
164 | GCObject **lastcollected = &collected; | 164 | GCObject **lastcollected = &collected; |
165 | while ((curr = *p) != NULL) { | 165 | while ((curr = *p) != NULL) { |
166 | lua_assert(curr->gch.tt == LUA_TUSERDATA); | 166 | lua_assert(curr->gch.tt == LUA_TUSERDATA); |
167 | if (isblack(curr) || isfinalized(gcotou(curr))) | 167 | if (!iswhite(curr) || isfinalized(gcotou(curr))) |
168 | p = &curr->gch.next; /* don't bother with them */ | 168 | p = &curr->gch.next; /* don't bother with them */ |
169 | |||
170 | else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) { | 169 | else if (fasttm(L, gcotou(curr)->uv.metatable, TM_GC) == NULL) { |
171 | markfinalized(gcotou(curr)); /* don't need finalization */ | 170 | markfinalized(gcotou(curr)); /* don't need finalization */ |
172 | p = &curr->gch.next; | 171 | p = &curr->gch.next; |
@@ -362,7 +361,7 @@ static int iscleared (const TObject *o, int iskey) { | |||
362 | stringmark(tsvalue(o)); /* strings are `values', so are never weak */ | 361 | stringmark(tsvalue(o)); /* strings are `values', so are never weak */ |
363 | return 0; | 362 | return 0; |
364 | } | 363 | } |
365 | return !isblack(gcvalue(o)) || | 364 | return iswhite(gcvalue(o)) || |
366 | (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); | 365 | (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); |
367 | } | 366 | } |
368 | 367 | ||
@@ -426,16 +425,19 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
426 | } | 425 | } |
427 | 426 | ||
428 | 427 | ||
429 | static GCObject **sweeplist (lua_State *L, GCObject **p, int mask, | 428 | static GCObject **sweeplist (lua_State *L, GCObject **p, int all, |
430 | l_mem *plim) { | 429 | l_mem *plim) { |
431 | GCObject *curr; | 430 | GCObject *curr; |
431 | global_State *g = G(L); | ||
432 | l_mem lim = *plim; | 432 | l_mem lim = *plim; |
433 | int white = otherwhite(g); | ||
433 | while ((curr = *p) != NULL) { | 434 | while ((curr = *p) != NULL) { |
434 | lua_assert(!isgray(curr)); | 435 | int mark = curr->gch.marked; |
435 | if (curr->gch.marked & mask) { | 436 | lua_assert(all || !(mark & g->currentwhite)); |
436 | lim -= objsize(curr); | 437 | if (!all && (!(mark & white) || testbit(mark, FIXEDBIT))) { |
437 | makewhite(curr); | 438 | makewhite(g, curr); |
438 | p = &curr->gch.next; | 439 | p = &curr->gch.next; |
440 | lim -= objsize(curr); | ||
439 | } | 441 | } |
440 | else { | 442 | else { |
441 | *p = curr->gch.next; | 443 | *p = curr->gch.next; |
@@ -448,16 +450,18 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int mask, | |||
448 | } | 450 | } |
449 | 451 | ||
450 | 452 | ||
451 | static void sweepstrings (lua_State *L, int mask) { | 453 | static void sweepstrings (lua_State *L, int all) { |
452 | int i; | 454 | int i; |
453 | global_State *g = G(L); | 455 | global_State *g = G(L); |
456 | int white = otherwhite(g); | ||
454 | for (i = 0; i < g->strt.size; i++) { /* for each list */ | 457 | for (i = 0; i < g->strt.size; i++) { /* for each list */ |
455 | GCObject *curr; | 458 | GCObject *curr; |
456 | GCObject **p = &G(L)->strt.hash[i]; | 459 | GCObject **p = &G(L)->strt.hash[i]; |
457 | while ((curr = *p) != NULL) { | 460 | while ((curr = *p) != NULL) { |
458 | lua_assert(!isgray(curr) && curr->gch.tt == LUA_TSTRING); | 461 | int mark = curr->gch.marked; |
459 | if (curr->gch.marked & mask) { | 462 | lua_assert(all || !(mark & g->currentwhite)); |
460 | makewhite(curr); | 463 | if (!all && (!(mark & white) || testbit(mark, FIXEDBIT))) { |
464 | makewhite(g, curr); | ||
461 | p = &curr->gch.next; | 465 | p = &curr->gch.next; |
462 | } | 466 | } |
463 | else { | 467 | else { |
@@ -497,7 +501,7 @@ static void GCTM (lua_State *L) { | |||
497 | g->tmudata = udata->uv.next; /* remove udata from `tmudata' */ | 501 | g->tmudata = udata->uv.next; /* remove udata from `tmudata' */ |
498 | udata->uv.next = g->firstudata->uv.next; /* return it to `root' list */ | 502 | udata->uv.next = g->firstudata->uv.next; /* return it to `root' list */ |
499 | g->firstudata->uv.next = o; | 503 | g->firstudata->uv.next = o; |
500 | makewhite(o); | 504 | makewhite(g, o); |
501 | tm = fasttm(L, udata->uv.metatable, TM_GC); | 505 | tm = fasttm(L, udata->uv.metatable, TM_GC); |
502 | if (tm != NULL) { | 506 | if (tm != NULL) { |
503 | lu_byte oldah = L->allowhook; | 507 | lu_byte oldah = L->allowhook; |
@@ -523,8 +527,8 @@ void luaC_callGCTM (lua_State *L) { | |||
523 | 527 | ||
524 | void luaC_sweepall (lua_State *L) { | 528 | void luaC_sweepall (lua_State *L) { |
525 | l_mem dummy = MAXLMEM; | 529 | l_mem dummy = MAXLMEM; |
526 | sweepstrings(L, 0); | 530 | sweepstrings(L, 1); |
527 | sweeplist(L, &G(L)->rootgc, 0, &dummy); | 531 | sweeplist(L, &G(L)->rootgc, 1, &dummy); |
528 | } | 532 | } |
529 | 533 | ||
530 | 534 | ||
@@ -533,7 +537,7 @@ static void markroot (lua_State *L) { | |||
533 | global_State *g = G(L); | 537 | global_State *g = G(L); |
534 | lua_assert(g->gray == NULL); | 538 | lua_assert(g->gray == NULL); |
535 | g->weak = NULL; | 539 | g->weak = NULL; |
536 | makewhite(valtogco(g->mainthread)); | 540 | makewhite(g, valtogco(g->mainthread)); |
537 | markobject(g, g->mainthread); | 541 | markobject(g, g->mainthread); |
538 | markvalue(g, registry(L)); | 542 | markvalue(g, registry(L)); |
539 | markobject(g, g->firstudata); | 543 | markobject(g, g->firstudata); |
@@ -548,11 +552,13 @@ static void atomic (lua_State *L) { | |||
548 | marktmu(g); /* mark `preserved' userdata */ | 552 | marktmu(g); /* mark `preserved' userdata */ |
549 | propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */ | 553 | propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */ |
550 | cleartable(g->weak); /* remove collected objects from weak tables */ | 554 | cleartable(g->weak); /* remove collected objects from weak tables */ |
555 | /* echange current white */ | ||
556 | g->currentwhite = otherwhite(g); | ||
551 | /* first element of root list will be used as temporary head for sweep | 557 | /* first element of root list will be used as temporary head for sweep |
552 | phase, so it won't be seeped */ | 558 | phase, so it won't be seeped */ |
553 | makewhite(g->rootgc); | 559 | makewhite(g, g->rootgc); |
554 | g->sweepgc = &g->rootgc->gch.next; | 560 | g->sweepgc = &g->rootgc->gch.next; |
555 | sweepstrings(L, maskbf); | 561 | sweepstrings(L, 0); |
556 | g->gcstate = GCSsweep; | 562 | g->gcstate = GCSsweep; |
557 | } | 563 | } |
558 | 564 | ||
@@ -560,7 +566,7 @@ static void atomic (lua_State *L) { | |||
560 | static void sweepstep (lua_State *L) { | 566 | static void sweepstep (lua_State *L) { |
561 | global_State *g = G(L); | 567 | global_State *g = G(L); |
562 | l_mem lim = GCSTEPSIZE; | 568 | l_mem lim = GCSTEPSIZE; |
563 | g->sweepgc = sweeplist(L, g->sweepgc, maskbf, &lim); | 569 | g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim); |
564 | if (lim == GCSTEPSIZE) { /* nothing more to sweep? */ | 570 | if (lim == GCSTEPSIZE) { /* nothing more to sweep? */ |
565 | g->gcstate = GCSfinalize; /* end sweep phase */ | 571 | g->gcstate = GCSfinalize; /* end sweep phase */ |
566 | } | 572 | } |
@@ -587,9 +593,10 @@ void luaC_collectgarbage (lua_State *L) { | |||
587 | 593 | ||
588 | 594 | ||
589 | void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { | 595 | void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { |
590 | o->gch.next = G(L)->rootgc; | 596 | global_State *g = G(L); |
591 | G(L)->rootgc = o; | 597 | o->gch.next = g->rootgc; |
592 | o->gch.marked = 0; | 598 | g->rootgc = o; |
599 | o->gch.marked = luaC_white(g); | ||
593 | o->gch.tt = tt; | 600 | o->gch.tt = tt; |
594 | } | 601 | } |
595 | 602 | ||