aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c184
1 files changed, 27 insertions, 157 deletions
diff --git a/lgc.c b/lgc.c
index 4fb65ef3..61162d42 100644
--- a/lgc.c
+++ b/lgc.c
@@ -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
88static void reallymarkobject (global_State *g, GCObject *o); 81static 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
187void luaC_fix (lua_State *L, GCObject *o) { 179void 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*/
201GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { 193GCObject *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) {
289static void markbeingfnz (global_State *g) { 281static 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) {
463static lu_mem traverseCclosure (global_State *g, CClosure *cl) { 455static 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*/
909static 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*/
927static 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
934static 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
963static 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
986static 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*/
1010static void setpause (global_State *g, l_mem estimate) { 894static 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) {
1029static int entersweep (lua_State *L) { 913static 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*/
1213void luaC_step (lua_State *L) { 1093void 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