diff options
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 58 |
1 files changed, 36 insertions, 22 deletions
@@ -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 | ||
586 | void luaC_step (lua_State *L) { | 585 | static 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; | ||
589 | luaC_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 | |||
625 | void 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; |
629 | luaC_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 | |||
636 | void 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 | ||
633 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { | 646 | void 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! */ |