aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c75
1 files changed, 44 insertions, 31 deletions
diff --git a/lgc.c b/lgc.c
index ff52fa2c..8cb8620f 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.185 2003/12/04 17:22:42 roberto Exp roberto $ 2** $Id: lgc.c,v 1.186 2003/12/04 18:52:23 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,12 +25,8 @@
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))
29
30#define isblack(x) testbit((x)->gch.marked, BLACKBIT)
31#define gray2black(x) setbit((x)->gch.marked, BLACKBIT) 28#define gray2black(x) setbit((x)->gch.marked, BLACKBIT)
32 29
33#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
34#define maskmarks \ 30#define maskmarks \
35 cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT))) 31 cast(lu_byte, ~(bitmask(BLACKBIT)|bit2mask(WHITE0BIT, WHITE1BIT)))
36#define makewhite(g,x) \ 32#define makewhite(g,x) \
@@ -47,7 +43,6 @@
47#define markfinalized(u) setbit((u)->uv.marked, FINALIZEDBIT) 43#define markfinalized(u) setbit((u)->uv.marked, FINALIZEDBIT)
48 44
49 45
50
51#define KEYWEAK bitmask(KEYWEAKBIT) 46#define KEYWEAK bitmask(KEYWEAKBIT)
52#define VALUEWEAK bitmask(VALUEWEAKBIT) 47#define VALUEWEAK bitmask(VALUEWEAKBIT)
53 48
@@ -110,7 +105,7 @@ static size_t objsize (GCObject *o) {
110 105
111static void reallymarkobject (global_State *g, GCObject *o) { 106static void reallymarkobject (global_State *g, GCObject *o) {
112 lua_assert(iswhite(o)); 107 lua_assert(iswhite(o));
113 lua_assert(!(o->gch.marked & otherwhite(g))); 108 lua_assert(!isdead(g, o));
114 white2gray(o); 109 white2gray(o);
115 switch (o->gch.tt) { 110 switch (o->gch.tt) {
116 case LUA_TSTRING: { 111 case LUA_TSTRING: {
@@ -118,6 +113,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
118 } 113 }
119 case LUA_TUSERDATA: { 114 case LUA_TUSERDATA: {
120 Table *mt = gcotou(o)->uv.metatable; 115 Table *mt = gcotou(o)->uv.metatable;
116 gray2black(o); /* udata are never gray */
121 if (mt) markobject(g, mt); 117 if (mt) markobject(g, mt);
122 return; 118 return;
123 } 119 }
@@ -442,7 +438,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
442 int dead = otherwhite(g); 438 int dead = otherwhite(g);
443 while ((curr = *p) != NULL) { 439 while ((curr = *p) != NULL) {
444 int mark = curr->gch.marked; 440 int mark = curr->gch.marked;
445 lua_assert(all || !(mark & g->currentwhite));
446 lim -= objsize(curr); 441 lim -= objsize(curr);
447 if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { 442 if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) {
448 makewhite(g, curr); 443 makewhite(g, curr);
@@ -469,9 +464,9 @@ static l_mem sweepstrings (lua_State *L, int all, l_mem lim) {
469 while ((curr = *p) != NULL) { 464 while ((curr = *p) != NULL) {
470 int mark = curr->gch.marked; 465 int mark = curr->gch.marked;
471 lu_mem size = sizestring(gcotots(curr)->tsv.len); 466 lu_mem size = sizestring(gcotots(curr)->tsv.len);
472 lua_assert(all || !(mark & g->currentwhite));
473 if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { 467 if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) {
474 makewhite(g, curr); 468 makewhite(g, curr);
469 lua_assert(iswhite(curr) && !isdead(g, curr));
475 p = &curr->gch.next; 470 p = &curr->gch.next;
476 } 471 }
477 else { 472 else {
@@ -499,8 +494,6 @@ static void checkSizes (lua_State *L) {
499 size_t newsize = luaZ_sizebuffer(&g->buff) / 2; 494 size_t newsize = luaZ_sizebuffer(&g->buff) / 2;
500 luaZ_resizebuffer(L, &g->buff, newsize); 495 luaZ_resizebuffer(L, &g->buff, newsize);
501 } 496 }
502 lua_assert(g->nblocks > g->GCthreshold);
503 g->GCthreshold = 2*G(L)->nblocks - g->GCthreshold; /* new threshold */
504} 497}
505 498
506 499
@@ -562,11 +555,13 @@ static void markroot (lua_State *L) {
562 555
563static void atomic (lua_State *L) { 556static void atomic (lua_State *L) {
564 global_State *g = G(L); 557 global_State *g = G(L);
558 /* there may be some gray elements due to the write barrier */
559 propagatemarks(g, MAXLMEM); /* traverse them */
565 lua_assert(g->gray == NULL); 560 lua_assert(g->gray == NULL);
566 g->gray = g->grayagain; 561 g->gray = g->grayagain;
567 g->grayagain = NULL; 562 g->grayagain = NULL;
568 propagatemarks(g, MAXLMEM); 563 propagatemarks(g, MAXLMEM);
569 g->GCthreshold = luaC_separateudata(L); /* separate userdata to be preserved */ 564 luaC_separateudata(L); /* separate userdata to be preserved */
570 marktmu(g); /* mark `preserved' userdata */ 565 marktmu(g); /* mark `preserved' userdata */
571 propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */ 566 propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */
572 cleartable(g->weak); /* remove collected objects from weak tables */ 567 cleartable(g->weak); /* remove collected objects from weak tables */
@@ -597,30 +592,48 @@ static void sweepstep (lua_State *L) {
597 global_State *g = G(L); 592 global_State *g = G(L);
598 l_mem lim = GCSTEPSIZE; 593 l_mem lim = GCSTEPSIZE;
599 g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim); 594 g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim);
600 if (lim == GCSTEPSIZE) /* nothing more to sweep? */ 595 if (lim == GCSTEPSIZE) { /* nothing more to sweep? */
601 g->gcstate = GCSfinalize; /* end sweep phase */ 596 g->gcstate = GCSfinalize; /* end sweep phase */
597 checkSizes(L);
598 }
602} 599}
603 600
604 601
605void luaC_collectgarbage (lua_State *L) { 602void luaC_step (lua_State *L) {
606 global_State *g = G(L); 603 global_State *g = G(L);
607 /* GCSroot */ 604 switch (g->gcstate) {
608 markroot(L); 605 case GCSroot:
609 /* GCSpropagate */ 606 markroot(L);
610 while (g->gcstate == GCSpropagate) 607 break;
611 propagatemarks(g, GCSTEPSIZE); 608 case GCSpropagate:
612 /* atomic */ 609 propagatemarks(g, GCSTEPSIZE);
613 atomic(L); 610 break;
614 /* GCSsweepstring */ 611 case GCSatomic:
615 while (g->gcstate == GCSsweepstring) 612 atomic(L);
616 sweepstringstep(L); 613 break;
617 /* GCSsweep */ 614 case GCSsweepstring:
618 while (g->gcstate == GCSsweep) 615 sweepstringstep(L);
619 sweepstep(L); 616 break;
620 /* GCSfinalize */ 617 case GCSsweep:
621 checkSizes(L); 618 sweepstep(L);
622 while (g->gcstate == GCSfinalize) 619 break;
623 GCTM(L); 620 case GCSfinalize:
621 GCTM(L);
622 break;
623 default: lua_assert(0);
624 }
625 g->GCthreshold = g->nblocks + GCSTEPSIZE;
626}
627
628
629void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
630 global_State *g = G(L);
631 lua_assert(isblack(o) && iswhite(v));
632 lua_assert(!isdead(g, v) && !isdead(g, o));
633 if (g->gcstate > GCSatomic) /* sweeping phases? */
634 black2gray(o); /* just mark as gray to avoid other barriers */
635 else /* breaking invariant! */
636 reallymarkobject(g, v); /* restore it */
624} 637}
625 638
626 639