aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2003-11-19 17:41:57 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2003-11-19 17:41:57 -0200
commit57b6ed68151c965b48f662828c50264c50e81d73 (patch)
tree2a3e133e49d9cc52b738fea5383b90c8574caff5 /lgc.c
parent9b9cdfee8b38feb4b94a3750f7539087d020850c (diff)
downloadlua-57b6ed68151c965b48f662828c50264c50e81d73.tar.gz
lua-57b6ed68151c965b48f662828c50264c50e81d73.tar.bz2
lua-57b6ed68151c965b48f662828c50264c50e81d73.zip
initial implementation of white/gray/black coloring
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c89
1 files changed, 53 insertions, 36 deletions
diff --git a/lgc.c b/lgc.c
index ddf2aa13..b60b9d3a 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.178 2003/11/17 19:50:05 roberto Exp roberto $ 2** $Id: lgc.c,v 1.179 2003/11/18 14:55:11 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*/
@@ -23,9 +23,15 @@
23 23
24 24
25 25
26#define unblack(x) resetbit((x)->gch.marked, BLACKBIT)
27#define isblack(x) testbit((x)->gch.marked, BLACKBIT) 26#define isblack(x) testbit((x)->gch.marked, BLACKBIT)
28#define blacken(x) setbit((x)->gch.marked, BLACKBIT) 27#define gray2black(x) ((x)->gch.marked++)
28#define white2black(x) setbit((x)->gch.marked, BLACKBIT)
29
30#define iswhite(x) (!test2bits((x)->gch.marked, GRAYBIT, BLACKBIT))
31#define makewhite(x) reset2bits((x)->gch.marked, GRAYBIT, BLACKBIT)
32
33#define isgray(x) testbit((x)->gch.marked, GRAYBIT)
34#define white2gray(x) setbit((x)->gch.marked, GRAYBIT)
29 35
30#define stringmark(s) setbit((s)->tsv.marked, BLACKBIT) 36#define stringmark(s) setbit((s)->tsv.marked, BLACKBIT)
31 37
@@ -39,55 +45,61 @@
39 45
40 46
41 47
42#define markobject(g,o) { checkconsistency(o); \ 48#define markvalue(g,o) { checkconsistency(o); \
43 if (iscollectable(o) && !isblack(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } 49 if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
44 50
45#define condmarkobject(g,o,c) { checkconsistency(o); \ 51#define condmarkobject(g,o,c) { checkconsistency(o); \
46 if (iscollectable(o) && !isblack(gcvalue(o)) && (c)) \ 52 if (iscollectable(o) && iswhite(gcvalue(o)) && (c)) \
47 reallymarkobject(g,gcvalue(o)); } 53 reallymarkobject(g,gcvalue(o)); }
48 54
49#define markvalue(g,t) { if (!isblack(valtogco(t))) \ 55#define markobject(g,t) { if (iswhite(valtogco(t))) \
50 reallymarkobject(g, valtogco(t)); } 56 reallymarkobject(g, valtogco(t)); }
51 57
52 58
53 59
54static void reallymarkobject (global_State *g, GCObject *o) { 60static void reallymarkobject (global_State *g, GCObject *o) {
55 lua_assert(!isblack(o)); 61 lua_assert(iswhite(o));
56 blacken(o);
57 switch (o->gch.tt) { 62 switch (o->gch.tt) {
63 case LUA_TSTRING: {
64 white2black(o); /* strings do not go to gray list */
65 return;
66 }
58 case LUA_TUSERDATA: { 67 case LUA_TUSERDATA: {
59 markvalue(g, gcotou(o)->uv.metatable); 68 white2black(o); /* userdata do not go to gray list */
60 break; 69 markobject(g, gcotou(o)->uv.metatable);
70 return;
61 } 71 }
62 case LUA_TFUNCTION: { 72 case LUA_TFUNCTION: {
63 gcotocl(o)->c.gclist = g->gray; 73 gcotocl(o)->c.gclist = g->gray;
64 g->gray = o;
65 break; 74 break;
66 } 75 }
67 case LUA_TTABLE: { 76 case LUA_TTABLE: {
68 gcotoh(o)->gclist = g->gray; 77 gcotoh(o)->gclist = g->gray;
69 g->gray = o;
70 break; 78 break;
71 } 79 }
72 case LUA_TTHREAD: { 80 case LUA_TTHREAD: {
73 gcototh(o)->gclist = g->gray; 81 gcototh(o)->gclist = g->gray;
74 g->gray = o;
75 break; 82 break;
76 } 83 }
77 case LUA_TPROTO: { 84 case LUA_TPROTO: {
78 gcotop(o)->gclist = g->gray; 85 gcotop(o)->gclist = g->gray;
79 g->gray = o;
80 break; 86 break;
81 } 87 }
82 default: lua_assert(o->gch.tt == LUA_TSTRING); 88 case LUA_TUPVAL: {
89 gcotouv(o)->gclist = g->gray;
90 break;
91 }
92 default: lua_assert(0);
83 } 93 }
94 g->gray = o; /* finish list linking */
95 white2gray(o);
84} 96}
85 97
86 98
87static void marktmu (global_State *g) { 99static void marktmu (global_State *g) {
88 GCObject *u; 100 GCObject *u;
89 for (u = g->tmudata; u; u = u->gch.next) { 101 for (u = g->tmudata; u; u = u->gch.next) {
90 unblack(u); /* may be marked, if left from previous GC */ 102 makewhite(u); /* may be marked, if left from previous GC */
91 reallymarkobject(g, u); 103 reallymarkobject(g, u);
92 } 104 }
93} 105}
@@ -130,7 +142,7 @@ static void traversetable (global_State *g, Table *h) {
130 int weakkey = 0; 142 int weakkey = 0;
131 int weakvalue = 0; 143 int weakvalue = 0;
132 const TObject *mode; 144 const TObject *mode;
133 markvalue(g, h->metatable); 145 markobject(g, h->metatable);
134 lua_assert(h->lsizenode || h->node == g->dummynode); 146 lua_assert(h->lsizenode || h->node == g->dummynode);
135 mode = gfasttm(g, h->metatable, TM_MODE); 147 mode = gfasttm(g, h->metatable, TM_MODE);
136 if (mode && ttisstring(mode)) { /* is there a weak mode? */ 148 if (mode && ttisstring(mode)) { /* is there a weak mode? */
@@ -148,7 +160,7 @@ static void traversetable (global_State *g, Table *h) {
148 if (!weakvalue) { 160 if (!weakvalue) {
149 i = h->sizearray; 161 i = h->sizearray;
150 while (i--) 162 while (i--)
151 markobject(g, &h->array[i]); 163 markvalue(g, &h->array[i]);
152 } 164 }
153 i = sizenode(h); 165 i = sizenode(h);
154 while (i--) { 166 while (i--) {
@@ -179,7 +191,7 @@ static void traverseproto (global_State *g, Proto *f) {
179 } 191 }
180 for (i=0; i<f->sizep; i++) { /* mark nested protos */ 192 for (i=0; i<f->sizep; i++) { /* mark nested protos */
181 if (f->p[i]) 193 if (f->p[i])
182 markvalue(g, f->p[i]); 194 markobject(g, f->p[i]);
183 } 195 }
184 for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */ 196 for (i=0; i<f->sizelocvars; i++) { /* mark local-variable names */
185 if (f->locvars[i].varname) 197 if (f->locvars[i].varname)
@@ -193,19 +205,15 @@ static void traverseclosure (global_State *g, Closure *cl) {
193 if (cl->c.isC) { 205 if (cl->c.isC) {
194 int i; 206 int i;
195 for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */ 207 for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */
196 markobject(g, &cl->c.upvalue[i]); 208 markvalue(g, &cl->c.upvalue[i]);
197 } 209 }
198 else { 210 else {
199 int i; 211 int i;
200 lua_assert(cl->l.nupvalues == cl->l.p->nups); 212 lua_assert(cl->l.nupvalues == cl->l.p->nups);
201 markvalue(g, hvalue(&cl->l.g)); 213 markobject(g, hvalue(&cl->l.g));
202 markvalue(g, cl->l.p); 214 markobject(g, cl->l.p);
203 for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ 215 for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
204 UpVal *u = cl->l.upvals[i]; 216 markobject(g, cl->l.upvals[i]);
205 if (!isblack(valtogco(u))) {
206 blacken(valtogco(u));
207 markobject(g, &u->value);
208 }
209 } 217 }
210 } 218 }
211} 219}
@@ -226,14 +234,14 @@ static void checkstacksizes (lua_State *L, StkId max) {
226static void traversestack (global_State *g, lua_State *L1) { 234static void traversestack (global_State *g, lua_State *L1) {
227 StkId o, lim; 235 StkId o, lim;
228 CallInfo *ci; 236 CallInfo *ci;
229 markobject(g, gt(L1)); 237 markvalue(g, gt(L1));
230 lim = L1->top; 238 lim = L1->top;
231 for (ci = L1->base_ci; ci <= L1->ci; ci++) { 239 for (ci = L1->base_ci; ci <= L1->ci; ci++) {
232 lua_assert(ci->top <= L1->stack_last); 240 lua_assert(ci->top <= L1->stack_last);
233 if (lim < ci->top) lim = ci->top; 241 if (lim < ci->top) lim = ci->top;
234 } 242 }
235 for (o = L1->stack; o < L1->top; o++) 243 for (o = L1->stack; o < L1->top; o++)
236 markobject(g, o); 244 markvalue(g, o);
237 for (; o <= lim; o++) 245 for (; o <= lim; o++)
238 setnilvalue(o); 246 setnilvalue(o);
239 checkstacksizes(L1, lim); 247 checkstacksizes(L1, lim);
@@ -242,6 +250,8 @@ static void traversestack (global_State *g, lua_State *L1) {
242 250
243static void propagatemarks (global_State *g) { 251static void propagatemarks (global_State *g) {
244 while (g->gray) { /* traverse marked objects */ 252 while (g->gray) { /* traverse marked objects */
253 lua_assert(isgray(g->gray));
254 gray2black(g->gray);
245 switch (g->gray->gch.tt) { 255 switch (g->gray->gch.tt) {
246 case LUA_TTABLE: { 256 case LUA_TTABLE: {
247 Table *h = gcotoh(g->gray); 257 Table *h = gcotoh(g->gray);
@@ -267,6 +277,12 @@ static void propagatemarks (global_State *g) {
267 traverseproto(g, p); 277 traverseproto(g, p);
268 break; 278 break;
269 } 279 }
280 case LUA_TUPVAL: {
281 UpVal *uv = gcotouv(g->gray);
282 g->gray = uv->gclist;
283 markvalue(g, &uv->value);
284 break;
285 }
270 default: lua_assert(0); 286 default: lua_assert(0);
271 } 287 }
272 } 288 }
@@ -354,8 +370,9 @@ static int sweeplist (lua_State *L, GCObject **p, int mask) {
354 GCObject *curr; 370 GCObject *curr;
355 int count = 0; /* number of collected items */ 371 int count = 0; /* number of collected items */
356 while ((curr = *p) != NULL) { 372 while ((curr = *p) != NULL) {
373 lua_assert(!isgray(curr));
357 if (curr->gch.marked & mask) { 374 if (curr->gch.marked & mask) {
358 unblack(curr); 375 makewhite(curr);
359 p = &curr->gch.next; 376 p = &curr->gch.next;
360 } 377 }
361 else { 378 else {
@@ -413,7 +430,7 @@ void luaC_callGCTM (lua_State *L) {
413 udata->uv.next = G(L)->rootudata; /* return it to `root' list */ 430 udata->uv.next = G(L)->rootudata; /* return it to `root' list */
414 G(L)->rootudata = o; 431 G(L)->rootudata = o;
415 setuvalue(L->top - 1, udata); /* keep a reference to it */ 432 setuvalue(L->top - 1, udata); /* keep a reference to it */
416 unblack(o); 433 makewhite(o);
417 do1gcTM(L, udata); 434 do1gcTM(L, udata);
418 } 435 }
419 L->top--; 436 L->top--;
@@ -422,7 +439,7 @@ void luaC_callGCTM (lua_State *L) {
422 439
423 440
424void luaC_sweep (lua_State *L, int all) { 441void luaC_sweep (lua_State *L, int all) {
425 int mask = (all) ? 0 : (bitmask(BLACKBIT) | bitmask(FIXEDBIT)); 442 int mask = (all) ? 0 : bit2mask(BLACKBIT, FIXEDBIT);
426 sweeplist(L, &G(L)->rootudata, mask); 443 sweeplist(L, &G(L)->rootudata, mask);
427 sweepstrings(L, mask); 444 sweepstrings(L, mask);
428 sweeplist(L, &G(L)->rootgc, mask); 445 sweeplist(L, &G(L)->rootgc, mask);
@@ -431,11 +448,11 @@ void luaC_sweep (lua_State *L, int all) {
431 448
432/* mark root set */ 449/* mark root set */
433static void markroot (global_State *g, lua_State *L) { 450static void markroot (global_State *g, lua_State *L) {
434 markobject(g, defaultmeta(L)); 451 markvalue(g, defaultmeta(L));
435 markobject(g, registry(L)); 452 markvalue(g, registry(L));
436 traversestack(g, g->mainthread); 453 traversestack(g, g->mainthread);
437 if (L != g->mainthread) /* another thread is running? */ 454 if (L != g->mainthread) /* another thread is running? */
438 markvalue(g, L); /* cannot collect it */ 455 markobject(g, L); /* cannot collect it */
439} 456}
440 457
441 458