summaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2004-02-16 16:09:52 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2004-02-16 16:09:52 -0300
commit2aaf7394ad17180565423ce360d5faffb60f4e4f (patch)
tree32caa2d7b0079b4bc9b0ac392d216c5094a6433d /lgc.c
parentb3ce4505296253e6da1fa780c23e7ed012efc88e (diff)
downloadlua-2aaf7394ad17180565423ce360d5faffb60f4e4f.tar.gz
lua-2aaf7394ad17180565423ce360d5faffb60f4e4f.tar.bz2
lua-2aaf7394ad17180565423ce360d5faffb60f4e4f.zip
more and better tools (assertions & inspectors) to check incremental GC
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/lgc.c b/lgc.c
index fe6461c0..ae5cd686 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $ 2** $Id: lgc.c,v 2.2 2003/12/12 18:29:34 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*/
@@ -60,6 +60,7 @@
60 60
61 61
62 62
63
63/* 64/*
64** computes the size of a collectible object 65** computes the size of a collectible object
65*/ 66*/
@@ -152,7 +153,7 @@ static void marktmu (global_State *g) {
152 153
153 154
154/* move `dead' udata that need finalization to list `tmudata' */ 155/* move `dead' udata that need finalization to list `tmudata' */
155size_t luaC_separateudata (lua_State *L) { 156size_t luaC_separateudata (lua_State *L, int all) {
156 size_t deadmem = 0; 157 size_t deadmem = 0;
157 GCObject **p = &G(L)->firstudata; 158 GCObject **p = &G(L)->firstudata;
158 GCObject *curr; 159 GCObject *curr;
@@ -160,7 +161,7 @@ size_t luaC_separateudata (lua_State *L) {
160 GCObject **lastcollected = &collected; 161 GCObject **lastcollected = &collected;
161 while ((curr = *p) != NULL) { 162 while ((curr = *p) != NULL) {
162 lua_assert(curr->gch.tt == LUA_TUSERDATA); 163 lua_assert(curr->gch.tt == LUA_TUSERDATA);
163 if (!iswhite(curr) || isfinalized(gco2u(curr))) 164 if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
164 p = &curr->gch.next; /* don't bother with them */ 165 p = &curr->gch.next; /* don't bother with them */
165 else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { 166 else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
166 markfinalized(gco2u(curr)); /* don't need finalization */ 167 markfinalized(gco2u(curr)); /* don't need finalization */
@@ -182,7 +183,7 @@ size_t luaC_separateudata (lua_State *L) {
182} 183}
183 184
184 185
185static void traversetable (global_State *g, Table *h) { 186static int traversetable (global_State *g, Table *h) {
186 int i; 187 int i;
187 int weakkey = 0; 188 int weakkey = 0;
188 int weakvalue = 0; 189 int weakvalue = 0;
@@ -202,7 +203,7 @@ static void traversetable (global_State *g, Table *h) {
202 g->weak = obj2gco(h); /* ... so put in the appropriate list */ 203 g->weak = obj2gco(h); /* ... so put in the appropriate list */
203 } 204 }
204 } 205 }
205 if (weakkey && weakvalue) return; 206 if (weakkey && weakvalue) return 1;
206 if (!weakvalue) { 207 if (!weakvalue) {
207 i = h->sizearray; 208 i = h->sizearray;
208 while (i--) 209 while (i--)
@@ -217,6 +218,7 @@ static void traversetable (global_State *g, Table *h) {
217 condmarkobject(g, gval(n), !weakvalue); 218 condmarkobject(g, gval(n), !weakvalue);
218 } 219 }
219 } 220 }
221 return weakkey || weakvalue;
220} 222}
221 223
222 224
@@ -227,10 +229,8 @@ static void traversetable (global_State *g, Table *h) {
227static void traverseproto (global_State *g, Proto *f) { 229static void traverseproto (global_State *g, Proto *f) {
228 int i; 230 int i;
229 if (f->source) stringmark(f->source); 231 if (f->source) stringmark(f->source);
230 for (i=0; i<f->sizek; i++) { /* mark literal strings */ 232 for (i=0; i<f->sizek; i++) /* mark literals */
231 if (ttisstring(f->k+i)) 233 markvalue(g, &f->k[i]);
232 stringmark(rawtsvalue(f->k+i));
233 }
234 for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */ 234 for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */
235 if (f->upvalues[i]) 235 if (f->upvalues[i])
236 stringmark(f->upvalues[i]); 236 stringmark(f->upvalues[i]);
@@ -258,9 +258,8 @@ static void traverseclosure (global_State *g, Closure *cl) {
258 lua_assert(cl->l.nupvalues == cl->l.p->nups); 258 lua_assert(cl->l.nupvalues == cl->l.p->nups);
259 markobject(g, hvalue(&cl->l.g)); 259 markobject(g, hvalue(&cl->l.g));
260 markobject(g, cl->l.p); 260 markobject(g, cl->l.p);
261 for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ 261 for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */
262 markobject(g, cl->l.upvals[i]); 262 markobject(g, cl->l.upvals[i]);
263 }
264 } 263 }
265} 264}
266 265
@@ -307,7 +306,8 @@ static l_mem propagatemarks (global_State *g, l_mem lim) {
307 case LUA_TTABLE: { 306 case LUA_TTABLE: {
308 Table *h = gco2h(o); 307 Table *h = gco2h(o);
309 g->gray = h->gclist; 308 g->gray = h->gclist;
310 traversetable(g, h); 309 if (traversetable(g, h)) /* table is weak? */
310 black2gray(o); /* keep it gray */
311 break; 311 break;
312 } 312 }
313 case LUA_TFUNCTION: { 313 case LUA_TFUNCTION: {
@@ -339,7 +339,8 @@ static l_mem propagatemarks (global_State *g, l_mem lim) {
339 g->grayagain = o; 339 g->grayagain = o;
340 black2gray(o); 340 black2gray(o);
341 } 341 }
342 markvalue(g, &uv->value); 342 else
343 markvalue(g, &uv->value);
343 break; 344 break;
344 } 345 }
345 default: lua_assert(0); 346 default: lua_assert(0);
@@ -428,6 +429,13 @@ static void freeobj (lua_State *L, GCObject *o) {
428} 429}
429 430
430 431
432static void sweepupvalues (global_State *g, lua_State *L1) {
433 GCObject *curr;
434 for (curr = L1->openupval; curr != NULL; curr = curr->gch.next)
435 makewhite(g, curr);
436}
437
438
431static GCObject **sweeplist (lua_State *L, GCObject **p, int all, 439static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
432 l_mem *plim) { 440 l_mem *plim) {
433 GCObject *curr; 441 GCObject *curr;
@@ -439,10 +447,14 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
439 lim -= objsize(curr); 447 lim -= objsize(curr);
440 if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { 448 if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) {
441 makewhite(g, curr); 449 makewhite(g, curr);
450 if (curr->gch.tt == LUA_TTHREAD)
451 sweepupvalues(g, gco2th(curr));
442 p = &curr->gch.next; 452 p = &curr->gch.next;
443 } 453 }
444 else { 454 else {
445 *p = curr->gch.next; 455 *p = curr->gch.next;
456 if (curr == g->rootgc) /* is the first element of the list? */
457 g->rootgc = curr->gch.next; /* adjust first */
446 freeobj(L, curr); 458 freeobj(L, curr);
447 } 459 }
448 if (lim <= 0) break; 460 if (lim <= 0) break;
@@ -537,7 +549,8 @@ void luaC_sweepall (lua_State *L) {
537/* mark root set */ 549/* mark root set */
538static void markroot (lua_State *L) { 550static void markroot (lua_State *L) {
539 global_State *g = G(L); 551 global_State *g = G(L);
540 lua_assert(g->gray == NULL && g->grayagain == NULL); 552 lua_assert(g->gray == NULL);
553 g->grayagain = NULL;
541 g->weak = NULL; 554 g->weak = NULL;
542 makewhite(g, obj2gco(g->mainthread)); 555 makewhite(g, obj2gco(g->mainthread));
543 markobject(g, g->mainthread); 556 markobject(g, g->mainthread);
@@ -550,28 +563,30 @@ static void markroot (lua_State *L) {
550static void atomic (lua_State *L) { 563static void atomic (lua_State *L) {
551 global_State *g = G(L); 564 global_State *g = G(L);
552 lua_assert(g->gray == NULL); 565 lua_assert(g->gray == NULL);
566 /* remark weak tables */
567 g->gray = g->weak;
568 g->weak = NULL;
569 propagatemarks(g, MAXLMEM);
570 /* remark gray again */
553 g->gray = g->grayagain; 571 g->gray = g->grayagain;
554 g->grayagain = NULL; 572 g->grayagain = NULL;
555 propagatemarks(g, MAXLMEM); 573 propagatemarks(g, MAXLMEM);
556 luaC_separateudata(L); /* separate userdata to be preserved */ 574 luaC_separateudata(L, 0); /* separate userdata to be preserved */
557 marktmu(g); /* mark `preserved' userdata */ 575 marktmu(g); /* mark `preserved' userdata */
558 propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */ 576 propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */
559 cleartable(g->weak); /* remove collected objects from weak tables */ 577 cleartable(g->weak); /* remove collected objects from weak tables */
560 /* flip current white */ 578 /* flip current white */
561 g->currentwhite = otherwhite(g); 579 g->currentwhite = otherwhite(g);
562 /* first element of root list will be used as temporary head for sweep 580 g->sweepgc = &g->rootgc;
563 phase, so it won't be swept */
564 makewhite(g, g->rootgc);
565 g->sweepgc = &g->rootgc->gch.next;
566 g->sweepstrgc = 0; 581 g->sweepstrgc = 0;
567 g->gcstate = GCSsweepstring; 582 g->gcstate = GCSsweepstring;
568 g->grayagain = NULL;
569} 583}
570 584
571 585
572void luaC_step (lua_State *L) { 586void luaC_step (lua_State *L) {
573 global_State *g = G(L); 587 global_State *g = G(L);
574 l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2; 588 l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2;
589luaC_checkall(L);
575 switch (g->gcstate) { 590 switch (g->gcstate) {
576 case GCSpropagate: { 591 case GCSpropagate: {
577 if (g->gray) 592 if (g->gray)
@@ -593,8 +608,9 @@ void luaC_step (lua_State *L) {
593 case GCSsweep: { 608 case GCSsweep: {
594 g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim); 609 g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim);
595 if (*g->sweepgc == NULL) { /* nothing more to sweep? */ 610 if (*g->sweepgc == NULL) { /* nothing more to sweep? */
596 g->gcstate = GCSfinalize; /* end sweep phase */
597 checkSizes(L); 611 checkSizes(L);
612 sweepupvalues(g, g->mainthread);
613 g->gcstate = GCSfinalize; /* end sweep phase */
598 } 614 }
599 break; 615 break;
600 } 616 }
@@ -610,13 +626,14 @@ void luaC_step (lua_State *L) {
610 default: lua_assert(0); 626 default: lua_assert(0);
611 } 627 }
612 g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2; 628 g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2;
629luaC_checkall(L);
613} 630}
614 631
615 632
616void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { 633void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
617 global_State *g = G(L); 634 global_State *g = G(L);
618 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); 635 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
619 if (g->gcstate >= GCSsweepstring) /* sweeping phases? */ 636 if (g->gcstate != GCSpropagate) /* sweeping phases? */
620 black2gray(o); /* just mark as gray to avoid other barriers */ 637 black2gray(o); /* just mark as gray to avoid other barriers */
621 else /* breaking invariant! */ 638 else /* breaking invariant! */
622 reallymarkobject(g, v); /* restore it */ 639 reallymarkobject(g, v); /* restore it */