diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-03-09 14:34:35 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-03-09 14:34:35 -0300 |
| commit | b876ec61c03e05ea0c4c02d8ad8abb84cf55e87c (patch) | |
| tree | 62224cadfc7273beecb092f0e4a761e4c4f634e5 /lgc.c | |
| parent | 898e8a67942186d62aa2cd3dc4ef96fe894788ef (diff) | |
| download | lua-b876ec61c03e05ea0c4c02d8ad8abb84cf55e87c.tar.gz lua-b876ec61c03e05ea0c4c02d8ad8abb84cf55e87c.tar.bz2 lua-b876ec61c03e05ea0c4c02d8ad8abb84cf55e87c.zip | |
new (temporary?) API for garbage collector
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! */ |
