diff options
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 184 |
1 files changed, 27 insertions, 157 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.169 2014/02/11 12:18:12 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.170 2014/02/11 12:28:47 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 | */ |
@@ -72,18 +72,11 @@ | |||
72 | lua_longassert(!iscollectable(obj) || righttt(obj)) | 72 | lua_longassert(!iscollectable(obj) || righttt(obj)) |
73 | 73 | ||
74 | 74 | ||
75 | #define marklocalvalue(g,o) { checkconsistency(o); \ | 75 | #define markvalue(g,o) { checkconsistency(o); \ |
76 | if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } | 76 | if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } |
77 | 77 | ||
78 | #define markvalue(g,o) { \ | ||
79 | lua_longassert(!(iscollectable(o) && islocal(gcvalue(o)))); \ | ||
80 | marklocalvalue(g,o); } | ||
81 | |||
82 | #define marklocalobject(g,t) \ | ||
83 | { if ((t) && iswhite(obj2gco(t))) reallymarkobject(g, obj2gco(t)); } | ||
84 | |||
85 | #define markobject(g,t) \ | 78 | #define markobject(g,t) \ |
86 | { lua_assert((t) == NULL || !islocal(obj2gco(t))); marklocalobject(g,t); } | 79 | { if ((t) && iswhite(obj2gco(t))) reallymarkobject(g, obj2gco(t)); } |
87 | 80 | ||
88 | static void reallymarkobject (global_State *g, GCObject *o); | 81 | static void reallymarkobject (global_State *g, GCObject *o); |
89 | 82 | ||
@@ -178,7 +171,6 @@ LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { | |||
178 | global_State *g = G(L); | 171 | global_State *g = G(L); |
179 | GCObject *o = gcvalue(uv->v); | 172 | GCObject *o = gcvalue(uv->v); |
180 | lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ | 173 | lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ |
181 | nolocal(o); | ||
182 | if (keepinvariant(g)) | 174 | if (keepinvariant(g)) |
183 | markobject(g, o); | 175 | markobject(g, o); |
184 | } | 176 | } |
@@ -186,9 +178,9 @@ LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { | |||
186 | 178 | ||
187 | void luaC_fix (lua_State *L, GCObject *o) { | 179 | void luaC_fix (lua_State *L, GCObject *o) { |
188 | global_State *g = G(L); | 180 | global_State *g = G(L); |
189 | lua_assert(g->localgc == o); | 181 | lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ |
190 | white2gray(o); | 182 | white2gray(o); /* they will be gray forever */ |
191 | g->localgc = o->gch.next; /* remove object from 'localgc' list */ | 183 | g->allgc = o->gch.next; /* remove object from 'allgc' list */ |
192 | o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */ | 184 | o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */ |
193 | g->fixedgc = o; | 185 | g->fixedgc = o; |
194 | } | 186 | } |
@@ -196,15 +188,15 @@ void luaC_fix (lua_State *L, GCObject *o) { | |||
196 | 188 | ||
197 | /* | 189 | /* |
198 | ** create a new collectable object (with given type and size) and link | 190 | ** create a new collectable object (with given type and size) and link |
199 | ** it to 'localgc' list. | 191 | ** it to 'allgc' list. |
200 | */ | 192 | */ |
201 | GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { | 193 | GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { |
202 | global_State *g = G(L); | 194 | global_State *g = G(L); |
203 | GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); | 195 | GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); |
204 | gch(o)->marked = luaC_white(g); | 196 | gch(o)->marked = luaC_white(g); |
205 | gch(o)->tt = tt; | 197 | gch(o)->tt = tt; |
206 | gch(o)->next = g->localgc; | 198 | gch(o)->next = g->allgc; |
207 | g->localgc = o; | 199 | g->allgc = o; |
208 | return o; | 200 | return o; |
209 | } | 201 | } |
210 | 202 | ||
@@ -289,7 +281,7 @@ static void markmt (global_State *g) { | |||
289 | static void markbeingfnz (global_State *g) { | 281 | static void markbeingfnz (global_State *g) { |
290 | GCObject *o; | 282 | GCObject *o; |
291 | for (o = g->tobefnz; o != NULL; o = gch(o)->next) | 283 | for (o = g->tobefnz; o != NULL; o = gch(o)->next) |
292 | marklocalobject(g, o); | 284 | markobject(g, o); |
293 | } | 285 | } |
294 | 286 | ||
295 | 287 | ||
@@ -306,7 +298,7 @@ static void remarkupvals (global_State *g) { | |||
306 | UpVal *uv = gco2th(thread)->openupval; | 298 | UpVal *uv = gco2th(thread)->openupval; |
307 | for (; uv != NULL; uv = uv->u.op.next) { | 299 | for (; uv != NULL; uv = uv->u.op.next) { |
308 | if (uv->u.op.touched) { | 300 | if (uv->u.op.touched) { |
309 | marklocalvalue(g, uv->v); /* remark upvalue's value */ | 301 | markvalue(g, uv->v); /* remark upvalue's value */ |
310 | uv->u.op.touched = 0; | 302 | uv->u.op.touched = 0; |
311 | } | 303 | } |
312 | } | 304 | } |
@@ -463,7 +455,7 @@ static int traverseproto (global_State *g, Proto *f) { | |||
463 | static lu_mem traverseCclosure (global_State *g, CClosure *cl) { | 455 | static lu_mem traverseCclosure (global_State *g, CClosure *cl) { |
464 | int i; | 456 | int i; |
465 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ | 457 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ |
466 | marklocalvalue(g, &cl->upvalue[i]); | 458 | markvalue(g, &cl->upvalue[i]); |
467 | return sizeCclosure(cl->nupvalues); | 459 | return sizeCclosure(cl->nupvalues); |
468 | } | 460 | } |
469 | 461 | ||
@@ -489,7 +481,7 @@ static lu_mem traversestack (global_State *g, lua_State *th) { | |||
489 | if (o == NULL) | 481 | if (o == NULL) |
490 | return 1; /* stack not completely built yet */ | 482 | return 1; /* stack not completely built yet */ |
491 | for (; o < th->top; o++) /* mark live elements in the stack */ | 483 | for (; o < th->top; o++) /* mark live elements in the stack */ |
492 | marklocalvalue(g, o); | 484 | markvalue(g, o); |
493 | if (g->gcstate == GCSatomic) { /* final traversal? */ | 485 | if (g->gcstate == GCSatomic) { /* final traversal? */ |
494 | StkId lim = th->stack + th->stacksize; /* real end of stack */ | 486 | StkId lim = th->stack + th->stacksize; /* real end of stack */ |
495 | for (; o < lim; o++) /* clear not-marked stack slice */ | 487 | for (; o < lim; o++) /* clear not-marked stack slice */ |
@@ -769,16 +761,8 @@ static GCObject *udata2finalize (global_State *g) { | |||
769 | GCObject *o = g->tobefnz; /* get first element */ | 761 | GCObject *o = g->tobefnz; /* get first element */ |
770 | lua_assert(tofinalize(o)); | 762 | lua_assert(tofinalize(o)); |
771 | g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ | 763 | g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ |
772 | if (islocal(o)) { | 764 | gch(o)->next = g->allgc; /* return it to 'allgc' list */ |
773 | gch(o)->next = g->localgc; /* return it to 'localgc' list */ | 765 | g->allgc = o; |
774 | g->localgc = o; | ||
775 | resetbit(gch(o)->marked, LOCALMARK); | ||
776 | } | ||
777 | else { /* return it to 'allgc' list */ | ||
778 | gch(o)->next = g->allgc; | ||
779 | g->allgc = o; | ||
780 | l_setbit(gch(o)->marked, LOCALMARK); | ||
781 | } | ||
782 | resetbit(gch(o)->marked, FINALIZEDBIT); /* object is "normal" again */ | 766 | resetbit(gch(o)->marked, FINALIZEDBIT); /* object is "normal" again */ |
783 | if (issweepphase(g)) | 767 | if (issweepphase(g)) |
784 | makewhite(g, o); /* "sweep" object */ | 768 | makewhite(g, o); /* "sweep" object */ |
@@ -882,8 +866,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
882 | g->sweepgc = sweeptolive(L, g->sweepgc, NULL); | 866 | g->sweepgc = sweeptolive(L, g->sweepgc, NULL); |
883 | } | 867 | } |
884 | /* search for pointer pointing to 'o' */ | 868 | /* search for pointer pointing to 'o' */ |
885 | p = (testbit(o->gch.marked, LOCALMARK)) ? &g->allgc : &g->localgc; | 869 | for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ } |
886 | for (; *p != o; p = &gch(*p)->next) { /* empty */ } | ||
887 | *p = o->gch.next; /* remove 'o' from its list */ | 870 | *p = o->gch.next; /* remove 'o' from its list */ |
888 | o->gch.next = g->finobj; /* link it in "fin" list */ | 871 | o->gch.next = g->finobj; /* link it in "fin" list */ |
889 | g->finobj = o; | 872 | g->finobj = o; |
@@ -896,105 +879,6 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
896 | /* }====================================================== */ | 879 | /* }====================================================== */ |
897 | 880 | ||
898 | 881 | ||
899 | /* | ||
900 | ** {====================================================== | ||
901 | ** Local Collection | ||
902 | ** ======================================================= | ||
903 | */ | ||
904 | |||
905 | |||
906 | /* | ||
907 | ** Traverse a thread, local marking all its collectable objects | ||
908 | */ | ||
909 | static void localmarkthread (lua_State *l) { | ||
910 | StkId o = l->stack; | ||
911 | StkId lim = l->stack + l->stacksize; /* real end of stack */ | ||
912 | if (o == NULL) | ||
913 | return; /* stack not completely built yet */ | ||
914 | for (; o < l->top; o++) { /* mark live elements in the stack */ | ||
915 | if (iscollectable(o)) | ||
916 | l_setbit(gcvalue(o)->gch.marked, LOCALMARK); | ||
917 | } | ||
918 | for (; o < lim; o++) /* clear not-marked stack slice */ | ||
919 | setnilvalue(o); | ||
920 | } | ||
921 | |||
922 | |||
923 | /* | ||
924 | ** Mark all that is locally accessible (accessible directly from | ||
925 | ** a thread) | ||
926 | */ | ||
927 | static void localmark (global_State *g) { | ||
928 | GCObject *thread = obj2gco(g->mainthread); | ||
929 | for (; thread != NULL; thread = gch(thread)->next) /* traverse all threads */ | ||
930 | localmarkthread(gco2th(thread)); | ||
931 | } | ||
932 | |||
933 | |||
934 | static void localsweep (lua_State *L, global_State *g) { | ||
935 | GCObject **p = &g->localgc; | ||
936 | while (*p != NULL) { | ||
937 | GCObject *curr = *p; | ||
938 | if (!islocal(curr)) { /* is 'curr' no more local? */ | ||
939 | *p = curr->gch.next; /* remove 'curr' from list */ | ||
940 | curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */ | ||
941 | g->allgc = curr; | ||
942 | /* mark it as out of local list */ | ||
943 | l_setbit(curr->gch.marked, LOCALMARK); | ||
944 | } | ||
945 | else { /* still local */ | ||
946 | if (testbit(curr->gch.marked, LOCALMARK)) { /* locally alive? */ | ||
947 | resetbit(curr->gch.marked, LOCALMARK); | ||
948 | p = &curr->gch.next; /* go to next element */ | ||
949 | } | ||
950 | else { /* object is dead */ | ||
951 | if (curr->gch.tt == LUA_TLCL) { /* is it a Lua closure? */ | ||
952 | if (gco2lcl(curr)->p->cache == gco2cl(curr)) | ||
953 | gco2lcl(curr)->p->cache = NULL; /* clear cache */ | ||
954 | } | ||
955 | *p = curr->gch.next; /* remove 'curr' from list */ | ||
956 | freeobj(L, curr); /* erase 'curr' */ | ||
957 | } | ||
958 | } | ||
959 | } | ||
960 | } | ||
961 | |||
962 | |||
963 | static void separatelocal (global_State *g) { | ||
964 | GCObject **p = &g->finobj; | ||
965 | GCObject **lastnext = findlast(&g->tobefnz); | ||
966 | while (*p != NULL) { | ||
967 | GCObject *curr = *p; | ||
968 | if (!islocal(curr)) /* is 'curr' no more local? */ | ||
969 | p = &curr->gch.next; /* go to next element */ | ||
970 | else { /* still local */ | ||
971 | if (testbit(curr->gch.marked, LOCALMARK)) { /* locally alive? */ | ||
972 | resetbit(curr->gch.marked, LOCALMARK); | ||
973 | p = &curr->gch.next; /* go to next element */ | ||
974 | } | ||
975 | else { /* object is "dead" */ | ||
976 | *p = curr->gch.next; /* remove 'curr' from list */ | ||
977 | curr->gch.next = *lastnext; /* link at the end of 'tobefnz' list */ | ||
978 | *lastnext = curr; | ||
979 | lastnext = &curr->gch.next; | ||
980 | } | ||
981 | } | ||
982 | } | ||
983 | } | ||
984 | |||
985 | |||
986 | static void luaC_localcollection (lua_State *L) { | ||
987 | global_State *g = G(L); | ||
988 | lua_assert(g->gcstate == GCSpause); | ||
989 | localmark(g); | ||
990 | localsweep(L, g); | ||
991 | separatelocal(g); | ||
992 | callallpendingfinalizers(L, 1); | ||
993 | } | ||
994 | |||
995 | /* }====================================================== */ | ||
996 | |||
997 | |||
998 | 882 | ||
999 | /* | 883 | /* |
1000 | ** {====================================================== | 884 | ** {====================================================== |
@@ -1008,13 +892,13 @@ static void luaC_localcollection (lua_State *L) { | |||
1008 | ** cycle will start when memory use hits threshold | 892 | ** cycle will start when memory use hits threshold |
1009 | */ | 893 | */ |
1010 | static void setpause (global_State *g, l_mem estimate) { | 894 | static void setpause (global_State *g, l_mem estimate) { |
1011 | l_mem threshold; | 895 | l_mem threshold, debt; |
1012 | estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ | 896 | estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ |
1013 | threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ | 897 | threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ |
1014 | ? estimate * g->gcpause /* no overflow */ | 898 | ? estimate * g->gcpause /* no overflow */ |
1015 | : MAX_LMEM; /* overflow; truncate to maximum */ | 899 | : MAX_LMEM; /* overflow; truncate to maximum */ |
1016 | g->GCthreshold = threshold; | 900 | debt = gettotalbytes(g) - threshold; |
1017 | luaE_setdebt(g, -g->gclocalpause); | 901 | luaE_setdebt(g, debt); |
1018 | } | 902 | } |
1019 | 903 | ||
1020 | 904 | ||
@@ -1029,9 +913,9 @@ static void setpause (global_State *g, l_mem estimate) { | |||
1029 | static int entersweep (lua_State *L) { | 913 | static int entersweep (lua_State *L) { |
1030 | global_State *g = G(L); | 914 | global_State *g = G(L); |
1031 | int n = 0; | 915 | int n = 0; |
1032 | g->gcstate = GCSswplocalgc; | 916 | g->gcstate = GCSswpallgc; |
1033 | lua_assert(g->sweepgc == NULL); | 917 | lua_assert(g->sweepgc == NULL); |
1034 | g->sweepgc = sweeptolive(L, &g->localgc, &n); | 918 | g->sweepgc = sweeptolive(L, &g->allgc, &n); |
1035 | return n; | 919 | return n; |
1036 | } | 920 | } |
1037 | 921 | ||
@@ -1044,7 +928,6 @@ void luaC_freeallobjects (lua_State *L) { | |||
1044 | lua_assert(g->tobefnz == NULL); | 928 | lua_assert(g->tobefnz == NULL); |
1045 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ | 929 | g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ |
1046 | g->gckind = KGC_NORMAL; | 930 | g->gckind = KGC_NORMAL; |
1047 | sweepwholelist(L, &g->localgc); | ||
1048 | sweepwholelist(L, &g->finobj); | 931 | sweepwholelist(L, &g->finobj); |
1049 | sweepwholelist(L, &g->allgc); | 932 | sweepwholelist(L, &g->allgc); |
1050 | sweepwholelist(L, &g->mainthread->next); | 933 | sweepwholelist(L, &g->mainthread->next); |
@@ -1136,10 +1019,7 @@ static lu_mem singlestep (lua_State *L) { | |||
1136 | sw = entersweep(L); | 1019 | sw = entersweep(L); |
1137 | return work + sw * GCSWEEPCOST; | 1020 | return work + sw * GCSWEEPCOST; |
1138 | } | 1021 | } |
1139 | case GCSswplocalgc: { /* sweep local objects */ | 1022 | case GCSswpallgc: { /* sweep "regular" objects */ |
1140 | return sweepstep(L, g, GCSswpallgc, &g->allgc); | ||
1141 | } | ||
1142 | case GCSswpallgc: { /* sweep non-local objects */ | ||
1143 | return sweepstep(L, g, GCSswpthreads, &g->mainthread->next); | 1023 | return sweepstep(L, g, GCSswpthreads, &g->mainthread->next); |
1144 | } | 1024 | } |
1145 | case GCSswpthreads: { /* sweep threads */ | 1025 | case GCSswpthreads: { /* sweep threads */ |
@@ -1208,23 +1088,13 @@ void luaC_forcestep (lua_State *L) { | |||
1208 | 1088 | ||
1209 | 1089 | ||
1210 | /* | 1090 | /* |
1211 | ** performs a basic GC step or a local collection when collector is running | 1091 | ** performs a basic GC step when collector is running |
1212 | */ | 1092 | */ |
1213 | void luaC_step (lua_State *L) { | 1093 | void luaC_step (lua_State *L) { |
1214 | global_State *g = G(L); | 1094 | if (!G(L)->gcrunning) |
1215 | if (!g->gcrunning) | 1095 | luaE_setdebt(G(L), -GCSTEPSIZE); /* avoid being called too often */ |
1216 | luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ | 1096 | else |
1217 | else { | 1097 | luaC_forcestep(L); |
1218 | if (g->gcstate != GCSpause) /* in the middle of a cycle? */ | ||
1219 | luaC_forcestep(L); /* continue it */ | ||
1220 | else { | ||
1221 | luaC_localcollection(L); /* try a local collection */ | ||
1222 | if (gettotalbytes(g) <= g->GCthreshold) /* enough? */ | ||
1223 | luaE_setdebt(g, -g->gclocalpause); | ||
1224 | else /* local collection did not collect enough memory */ | ||
1225 | luaC_forcestep(L); /* start a full collection */ | ||
1226 | } | ||
1227 | } | ||
1228 | } | 1098 | } |
1229 | 1099 | ||
1230 | 1100 | ||