summaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2003-12-03 18:03:07 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2003-12-03 18:03:07 -0200
commitc6eac44a9420a26a2f8907dcd5266a6aecdb18ea (patch)
treeacbf11560fe8aee5dddf37ff52b9fcaa6e697ca6 /lgc.c
parent8878554b854009066eeccfe7b17e6e019c69758a (diff)
downloadlua-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.c79
1 files changed, 43 insertions, 36 deletions
diff --git a/lgc.c b/lgc.c
index 8f56b479..183b91ef 100644
--- a/lgc.c
+++ b/lgc.c
@@ -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
109static void reallymarkobject (global_State *g, GCObject *o) { 110static 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
149static void marktmu (global_State *g) { 149static 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
429static GCObject **sweeplist (lua_State *L, GCObject **p, int mask, 428static 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
451static void sweepstrings (lua_State *L, int mask) { 453static 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
524void luaC_sweepall (lua_State *L) { 528void 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) {
560static void sweepstep (lua_State *L) { 566static 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
589void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { 595void 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