aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c58
1 files changed, 36 insertions, 22 deletions
diff --git a/lgc.c b/lgc.c
index ae5cd686..0f34b099 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.2 2003/12/12 18:29:34 roberto Exp roberto $ 2** $Id: lgc.c,v 2.3 2004/02/16 19:09:52 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,6 +23,8 @@
23 23
24 24
25#define GCSTEPSIZE (40*sizeof(TValue)) 25#define GCSTEPSIZE (40*sizeof(TValue))
26#define GCFREECOST (sizeof(TValue)/2)
27#define GCSWEEPCOST sizeof(TValue)
26 28
27 29
28#define gray2black(x) setbit((x)->gch.marked, BLACKBIT) 30#define gray2black(x) setbit((x)->gch.marked, BLACKBIT)
@@ -51,10 +53,6 @@
51#define markvalue(g,o) { checkconsistency(o); \ 53#define markvalue(g,o) { checkconsistency(o); \
52 if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } 54 if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }
53 55
54#define condmarkobject(g,o,c) { checkconsistency(o); \
55 if (iscollectable(o) && iswhite(gcvalue(o)) && (c)) \
56 reallymarkobject(g,gcvalue(o)); }
57
58#define markobject(g,t) { if (iswhite(obj2gco(t))) \ 56#define markobject(g,t) { if (iswhite(obj2gco(t))) \
59 reallymarkobject(g, obj2gco(t)); } 57 reallymarkobject(g, obj2gco(t)); }
60 58
@@ -214,8 +212,8 @@ static int traversetable (global_State *g, Table *h) {
214 Node *n = gnode(h, i); 212 Node *n = gnode(h, i);
215 if (!ttisnil(gval(n))) { 213 if (!ttisnil(gval(n))) {
216 lua_assert(!ttisnil(gkey(n))); 214 lua_assert(!ttisnil(gkey(n)));
217 condmarkobject(g, gkey(n), !weakkey); 215 if (!weakkey) markvalue(g, gkey(n));
218 condmarkobject(g, gval(n), !weakvalue); 216 if (!weakvalue) markvalue(g, gval(n));
219 } 217 }
220 } 218 }
221 return weakkey || weakvalue; 219 return weakkey || weakvalue;
@@ -444,18 +442,19 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
444 int dead = otherwhite(g); 442 int dead = otherwhite(g);
445 while ((curr = *p) != NULL) { 443 while ((curr = *p) != NULL) {
446 int mark = curr->gch.marked; 444 int mark = curr->gch.marked;
447 lim -= objsize(curr);
448 if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { 445 if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) {
449 makewhite(g, curr); 446 makewhite(g, curr);
450 if (curr->gch.tt == LUA_TTHREAD) 447 if (curr->gch.tt == LUA_TTHREAD)
451 sweepupvalues(g, gco2th(curr)); 448 sweepupvalues(g, gco2th(curr));
452 p = &curr->gch.next; 449 p = &curr->gch.next;
450 lim -= GCSWEEPCOST;
453 } 451 }
454 else { 452 else {
455 *p = curr->gch.next; 453 *p = curr->gch.next;
456 if (curr == g->rootgc) /* is the first element of the list? */ 454 if (curr == g->rootgc) /* is the first element of the list? */
457 g->rootgc = curr->gch.next; /* adjust first */ 455 g->rootgc = curr->gch.next; /* adjust first */
458 freeobj(L, curr); 456 freeobj(L, curr);
457 lim -= GCFREECOST;
459 } 458 }
460 if (lim <= 0) break; 459 if (lim <= 0) break;
461 } 460 }
@@ -583,19 +582,16 @@ static void atomic (lua_State *L) {
583} 582}
584 583
585 584
586void luaC_step (lua_State *L) { 585static l_mem singlestep (lua_State *L, l_mem lim) {
587 global_State *g = G(L); 586 global_State *g = G(L);
588 l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2;
589luaC_checkall(L);
590 switch (g->gcstate) { 587 switch (g->gcstate) {
591 case GCSpropagate: { 588 case GCSpropagate: {
592 if (g->gray) 589 if (g->gray)
593 lim = propagatemarks(g, lim); 590 return propagatemarks(g, lim);
594 else { /* no more `gray' objects */ 591 else { /* no more `gray' objects */
595 atomic(L); /* finish mark phase */ 592 atomic(L); /* finish mark phase */
596 lim = 0; 593 return 0;
597 } 594 }
598 break;
599 } 595 }
600 case GCSsweepstring: { 596 case GCSsweepstring: {
601 lim = sweepstrings(L, 0, lim); 597 lim = sweepstrings(L, 0, lim);
@@ -603,7 +599,7 @@ luaC_checkall(L);
603 g->sweepstrgc = 0; 599 g->sweepstrgc = 0;
604 g->gcstate = GCSsweep; /* end sweep-string phase */ 600 g->gcstate = GCSsweep; /* end sweep-string phase */
605 } 601 }
606 break; 602 return lim;
607 } 603 }
608 case GCSsweep: { 604 case GCSsweep: {
609 g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim); 605 g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim);
@@ -612,27 +608,45 @@ luaC_checkall(L);
612 sweepupvalues(g, g->mainthread); 608 sweepupvalues(g, g->mainthread);
613 g->gcstate = GCSfinalize; /* end sweep phase */ 609 g->gcstate = GCSfinalize; /* end sweep phase */
614 } 610 }
615 break; 611 return lim;
616 } 612 }
617 case GCSfinalize: { 613 case GCSfinalize: {
618 if (g->tmudata) { 614 if (g->tmudata)
619 GCTM(L); 615 GCTM(L);
620 lim = 0;
621 }
622 else /* no more `udata' to finalize */ 616 else /* no more `udata' to finalize */
623 markroot(L); /* may restart collection */ 617 markroot(L); /* may restart collection */
624 break; 618 return 0;
625 } 619 }
626 default: lua_assert(0); 620 default: lua_assert(0); return 0; /* to avoid warnings */
627 } 621 }
622}
623
624
625void luaC_step (lua_State *L) {
626 global_State *g = G(L);
627 l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2;
628/*printf("+ %d %lu %lu %ld\n", g->gcstate, g->nblocks, g->GCthreshold, lim);*/
629 while (lim > 0) lim = singlestep(L, lim);
628 g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2; 630 g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2;
629luaC_checkall(L); 631/*printf("- %d %lu %lu %ld\n", g->gcstate, g->nblocks, g->GCthreshold, lim);*/
632 lua_assert((long)g->nblocks + (long)GCSTEPSIZE >= lim/2);
633}
634
635
636void luaC_fullgc (lua_State *L) {
637 global_State *g = G(L);
638 while (g->gcstate != GCSfinalize) singlestep(L, MAXLMEM);
639 markroot(L);
640 while (g->gcstate != GCSfinalize) singlestep(L, MAXLMEM);
641 luaC_callGCTM(L); /* call finalizers */
642 g->GCthreshold = g->nblocks + GCSTEPSIZE;
630} 643}
631 644
632 645
633void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { 646void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
634 global_State *g = G(L); 647 global_State *g = G(L);
635 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); 648 lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
649 lua_assert(g->gcstate != GCSfinalize);
636 if (g->gcstate != GCSpropagate) /* sweeping phases? */ 650 if (g->gcstate != GCSpropagate) /* sweeping phases? */
637 black2gray(o); /* just mark as gray to avoid other barriers */ 651 black2gray(o); /* just mark as gray to avoid other barriers */
638 else /* breaking invariant! */ 652 else /* breaking invariant! */