diff options
| -rw-r--r-- | lgc.c | 56 |
1 files changed, 28 insertions, 28 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 2.89 2010/05/05 18:58:36 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.90 2010/05/06 18:18:07 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 | */ |
| @@ -130,7 +130,7 @@ static int iscleared (const TValue *o, int iskey) { | |||
| 130 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { | 130 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { |
| 131 | global_State *g = G(L); | 131 | global_State *g = G(L); |
| 132 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); | 132 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
| 133 | lua_assert(g->gckind == KGC_GEN || g->gcstate != GCSpause); | 133 | lua_assert(isgenerational(g) || g->gcstate != GCSpause); |
| 134 | lua_assert(gch(o)->tt != LUA_TTABLE); | 134 | lua_assert(gch(o)->tt != LUA_TTABLE); |
| 135 | if (keepinvariant(g)) /* must keep invariant? */ | 135 | if (keepinvariant(g)) /* must keep invariant? */ |
| 136 | reallymarkobject(g, v); /* restore invariant */ | 136 | reallymarkobject(g, v); /* restore invariant */ |
| @@ -149,15 +149,9 @@ void luaC_barrierback (lua_State *L, Table *t) { | |||
| 149 | global_State *g = G(L); | 149 | global_State *g = G(L); |
| 150 | GCObject *o = obj2gco(t); | 150 | GCObject *o = obj2gco(t); |
| 151 | lua_assert(isblack(o) && !isdead(g, o)); | 151 | lua_assert(isblack(o) && !isdead(g, o)); |
| 152 | if (keepinvariant(g)) { | 152 | black2gray(o); /* make table gray (again) */ |
| 153 | black2gray(o); /* make table gray (again) */ | 153 | t->gclist = g->grayagain; |
| 154 | t->gclist = g->grayagain; | 154 | g->grayagain = o; |
| 155 | g->grayagain = o; | ||
| 156 | } | ||
| 157 | else { /* sweep phase */ | ||
| 158 | lua_assert(issweepphase(g)); | ||
| 159 | makewhite(g, o); /* mark main obj. as white to avoid other barriers */ | ||
| 160 | } | ||
| 161 | } | 155 | } |
| 162 | 156 | ||
| 163 | 157 | ||
| @@ -612,31 +606,31 @@ static void sweepthread (lua_State *L, lua_State *L1) { | |||
| 612 | */ | 606 | */ |
| 613 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | 607 | static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { |
| 614 | global_State *g = G(L); | 608 | global_State *g = G(L); |
| 615 | int deadmask = otherwhite(g); | 609 | int ow = otherwhite(g); |
| 616 | int toclear, toset; /* bits to clear and to set in all live objects */ | 610 | int toclear, toset; /* bits to clear and to set in all live objects */ |
| 617 | if (g->gckind == KGC_GEN) { /* generational mode? */ | 611 | int tostop; /* stop sweep when this is true */ |
| 612 | if (isgenerational(g)) { /* generational mode? */ | ||
| 618 | toclear = ~0; /* clear nothing */ | 613 | toclear = ~0; /* clear nothing */ |
| 619 | toset = OLDBIT; /* set the old bit of all surviving objects */ | 614 | toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */ |
| 615 | tostop = bitmask(OLDBIT); /* do not sweep old generation */ | ||
| 620 | } | 616 | } |
| 621 | else { /* normal mode */ | 617 | else { /* normal mode */ |
| 622 | toclear = maskcolors; /* clear all color bits */ | 618 | toclear = maskcolors; /* clear all color bits + old bit */ |
| 623 | toset = luaC_white(g); /* make object white */ | 619 | toset = luaC_white(g); /* make object white */ |
| 620 | tostop = 0; /* do not stop */ | ||
| 624 | } | 621 | } |
| 625 | while (*p != NULL && count-- > 0) { | 622 | while (*p != NULL && count-- > 0) { |
| 626 | GCObject *curr = *p; | 623 | GCObject *curr = *p; |
| 627 | int marked = gch(curr)->marked; | 624 | int marked = gch(curr)->marked; |
| 628 | if (!((marked ^ WHITEBITS) & deadmask)) { /* is 'curr' dead? */ | 625 | if (isdeadm(ow, marked)) { /* is 'curr' dead? */ |
| 629 | lua_assert(isdead(g, curr) || deadmask == 0); | ||
| 630 | *p = gch(curr)->next; /* remove 'curr' from list */ | 626 | *p = gch(curr)->next; /* remove 'curr' from list */ |
| 631 | freeobj(L, curr); /* erase 'curr' */ | 627 | freeobj(L, curr); /* erase 'curr' */ |
| 632 | } | 628 | } |
| 633 | else { | 629 | else { |
| 634 | lua_assert(!isdead(g, curr) || testbit(marked, FIXEDBIT)); | ||
| 635 | if (gch(curr)->tt == LUA_TTHREAD) | 630 | if (gch(curr)->tt == LUA_TTHREAD) |
| 636 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ | 631 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ |
| 637 | if (testbit(marked, OLDBIT)) { /* old generation? */ | 632 | if (testbits(marked, tostop)) { |
| 638 | static GCObject *nullp = NULL; | 633 | static GCObject *nullp = NULL; |
| 639 | lua_assert(g->gckind == KGC_GEN); /* can happen only in gen. mode */ | ||
| 640 | return &nullp; /* stop sweeping this list */ | 634 | return &nullp; /* stop sweeping this list */ |
| 641 | } | 635 | } |
| 642 | /* update marks */ | 636 | /* update marks */ |
| @@ -671,7 +665,7 @@ static Udata *udata2finalize (global_State *g) { | |||
| 671 | GCObject *o = g->tobefnz; /* get first element */ | 665 | GCObject *o = g->tobefnz; /* get first element */ |
| 672 | Udata *u = rawgco2u(o); | 666 | Udata *u = rawgco2u(o); |
| 673 | lua_assert(isfinalized(&u->uv)); | 667 | lua_assert(isfinalized(&u->uv)); |
| 674 | lua_assert(!testbit(u->uv.marked, OLDBIT)); | 668 | lua_assert(!isold(o)); |
| 675 | g->tobefnz = u->uv.next; /* remove it from 'tobefnz' list */ | 669 | g->tobefnz = u->uv.next; /* remove it from 'tobefnz' list */ |
| 676 | u->uv.next = g->allgc; /* return it to 'allgc' list */ | 670 | u->uv.next = g->allgc; /* return it to 'allgc' list */ |
| 677 | g->allgc = o; | 671 | g->allgc = o; |
| @@ -725,7 +719,7 @@ void luaC_separateudata (lua_State *L, int all) { | |||
| 725 | GCObject **p = &g->udgc; | 719 | GCObject **p = &g->udgc; |
| 726 | GCObject *curr; | 720 | GCObject *curr; |
| 727 | GCObject **lastnext = &g->tobefnz; | 721 | GCObject **lastnext = &g->tobefnz; |
| 728 | /* find last 'next' field in 'tobefnz' list (to insert elements in its end) */ | 722 | /* find last 'next' field in 'tobefnz' list (to add elements in its end) */ |
| 729 | while (*lastnext != NULL) | 723 | while (*lastnext != NULL) |
| 730 | lastnext = &gch(*lastnext)->next; | 724 | lastnext = &gch(*lastnext)->next; |
| 731 | while ((curr = *p) != NULL) { /* traverse all finalizable objects */ | 725 | while ((curr = *p) != NULL) { /* traverse all finalizable objects */ |
| @@ -735,6 +729,7 @@ void luaC_separateudata (lua_State *L, int all) { | |||
| 735 | p = &gch(curr)->next; /* don't bother with it */ | 729 | p = &gch(curr)->next; /* don't bother with it */ |
| 736 | else { | 730 | else { |
| 737 | l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ | 731 | l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ |
| 732 | resetbit(gch(curr)->marked, OLDBIT); /* may be old when 'all' */ | ||
| 738 | *p = gch(curr)->next; /* remove 'curr' from 'udgc' list */ | 733 | *p = gch(curr)->next; /* remove 'curr' from 'udgc' list */ |
| 739 | gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ | 734 | gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ |
| 740 | *lastnext = curr; | 735 | *lastnext = curr; |
| @@ -761,6 +756,7 @@ void luaC_checkfinalizer (lua_State *L, Udata *u) { | |||
| 761 | u->uv.next = g->udgc; /* link it in list 'udgc' */ | 756 | u->uv.next = g->udgc; /* link it in list 'udgc' */ |
| 762 | g->udgc = obj2gco(u); | 757 | g->udgc = obj2gco(u); |
| 763 | l_setbit(u->uv.marked, SEPARATED); /* mark it as such */ | 758 | l_setbit(u->uv.marked, SEPARATED); /* mark it as such */ |
| 759 | resetbit(u->uv.marked, OLDBIT); | ||
| 764 | } | 760 | } |
| 765 | } | 761 | } |
| 766 | 762 | ||
| @@ -814,6 +810,7 @@ void luaC_freeallobjects (lua_State *L) { | |||
| 814 | callallpendingfinalizers(L, 0); | 810 | callallpendingfinalizers(L, 0); |
| 815 | /* following "white" makes all objects look dead */ | 811 | /* following "white" makes all objects look dead */ |
| 816 | g->currentwhite = WHITEBITS; | 812 | g->currentwhite = WHITEBITS; |
| 813 | g->gckind = KGC_NORMAL; | ||
| 817 | sweepwholelist(L, &g->udgc); | 814 | sweepwholelist(L, &g->udgc); |
| 818 | lua_assert(g->udgc == NULL); | 815 | lua_assert(g->udgc == NULL); |
| 819 | sweepwholelist(L, &g->allgc); | 816 | sweepwholelist(L, &g->allgc); |
| @@ -851,6 +848,7 @@ static void atomic (lua_State *L) { | |||
| 851 | g->sweepstrgc = 0; /* prepare to sweep strings */ | 848 | g->sweepstrgc = 0; /* prepare to sweep strings */ |
| 852 | g->gcstate = GCSsweepstring; | 849 | g->gcstate = GCSsweepstring; |
| 853 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ | 850 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ |
| 851 | /*lua_checkmemory(L);*/ | ||
| 854 | } | 852 | } |
| 855 | 853 | ||
| 856 | 854 | ||
| @@ -859,7 +857,11 @@ static l_mem singlestep (lua_State *L) { | |||
| 859 | /*lua_checkmemory(L);*/ | 857 | /*lua_checkmemory(L);*/ |
| 860 | switch (g->gcstate) { | 858 | switch (g->gcstate) { |
| 861 | case GCSpause: { | 859 | case GCSpause: { |
| 862 | markroot(L); /* start a new collection */ | 860 | if (!isgenerational(g)) |
| 861 | markroot(L); /* start a new collection */ | ||
| 862 | else /* root still marked */ | ||
| 863 | lua_assert(!iswhite(obj2gco(g->mainthread)) | ||
| 864 | && !iswhite(gcvalue(&g->l_registry))); | ||
| 863 | g->gcstate = GCSpropagate; | 865 | g->gcstate = GCSpropagate; |
| 864 | return GCROOTCOST; | 866 | return GCROOTCOST; |
| 865 | } | 867 | } |
| @@ -925,14 +927,12 @@ void luaC_runtilstate (lua_State *L, int statesmask) { | |||
| 925 | 927 | ||
| 926 | static void generationalcollection (lua_State *L) { | 928 | static void generationalcollection (lua_State *L) { |
| 927 | global_State *g = G(L); | 929 | global_State *g = G(L); |
| 928 | lua_assert(g->gcstate == GCSpropagate); | ||
| 929 | if (g->lastmajormem == 0) { /* signal for another major collection? */ | 930 | if (g->lastmajormem == 0) { /* signal for another major collection? */ |
| 930 | luaC_fullgc(L, 0); /* perform a full regular collection */ | 931 | luaC_fullgc(L, 0); /* perform a full regular collection */ |
| 931 | g->lastmajormem = g->totalbytes; /* update control */ | 932 | g->lastmajormem = g->totalbytes; /* update control */ |
| 932 | } | 933 | } |
| 933 | else { | 934 | else { |
| 934 | luaC_runtilstate(L, bitmask(GCSpause)); | 935 | luaC_runtilstate(L, bitmask(GCSpause)); /* run collection */ |
| 935 | g->gcstate = GCSpropagate; /* do not run 'markroot' */ | ||
| 936 | if (g->totalbytes > g->lastmajormem/100 * g->gcpause) | 936 | if (g->totalbytes > g->lastmajormem/100 * g->gcpause) |
| 937 | g->lastmajormem = 0; /* signal for a major collection */ | 937 | g->lastmajormem = 0; /* signal for a major collection */ |
| 938 | } | 938 | } |
| @@ -955,7 +955,7 @@ static void step (lua_State *L) { | |||
| 955 | 955 | ||
| 956 | void luaC_step (lua_State *L) { | 956 | void luaC_step (lua_State *L) { |
| 957 | int i; | 957 | int i; |
| 958 | if (G(L)->gckind == KGC_GEN) generationalcollection(L); | 958 | if (isgenerational(G(L))) generationalcollection(L); |
| 959 | else step(L); | 959 | else step(L); |
| 960 | for (i = 0; i < GCFINALIZENUM && G(L)->tobefnz; i++) | 960 | for (i = 0; i < GCFINALIZENUM && G(L)->tobefnz; i++) |
| 961 | GCTM(L, 1); /* Call a few pending finalizers */ | 961 | GCTM(L, 1); /* Call a few pending finalizers */ |
| @@ -984,11 +984,11 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
| 984 | /* run entire collector */ | 984 | /* run entire collector */ |
| 985 | luaC_runtilstate(L, ~bitmask(GCSpause)); | 985 | luaC_runtilstate(L, ~bitmask(GCSpause)); |
| 986 | luaC_runtilstate(L, bitmask(GCSpause)); | 986 | luaC_runtilstate(L, bitmask(GCSpause)); |
| 987 | g->gckind = origkind; | ||
| 988 | if (origkind == KGC_GEN) { /* generational mode? */ | 987 | if (origkind == KGC_GEN) { /* generational mode? */ |
| 989 | /* generational mode must always start in propagate phase */ | 988 | /* generational mode must always start in propagate phase */ |
| 990 | luaC_runtilstate(L, bitmask(GCSpropagate)); | 989 | luaC_runtilstate(L, bitmask(GCSpropagate)); |
| 991 | } | 990 | } |
| 991 | g->gckind = origkind; | ||
| 992 | g->GCdebt = stddebt(g); | 992 | g->GCdebt = stddebt(g); |
| 993 | if (!isemergency) /* do not run finalizers during emergency GC */ | 993 | if (!isemergency) /* do not run finalizers during emergency GC */ |
| 994 | callallpendingfinalizers(L, 1); | 994 | callallpendingfinalizers(L, 1); |
