aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c47
1 files changed, 29 insertions, 18 deletions
diff --git a/lgc.c b/lgc.c
index 5e8c02d3..717f80e8 100644
--- a/lgc.c
+++ b/lgc.c
@@ -348,8 +348,7 @@ static int remarkupvals (global_State *g) {
348 int work = 0; /* estimate of how much work was done here */ 348 int work = 0; /* estimate of how much work was done here */
349 while ((thread = *p) != NULL) { 349 while ((thread = *p) != NULL) {
350 work++; 350 work++;
351 lua_assert(!isblack(thread)); /* threads are never black */ 351 if (!iswhite(thread) && thread->openupval != NULL)
352 if (isgray(thread) && thread->openupval != NULL)
353 p = &thread->twups; /* keep marked thread with upvalues in the list */ 352 p = &thread->twups; /* keep marked thread with upvalues in the list */
354 else { /* thread is not marked or without upvalues */ 353 else { /* thread is not marked or without upvalues */
355 UpVal *uv; 354 UpVal *uv;
@@ -600,12 +599,23 @@ static int traverseLclosure (global_State *g, LClosure *cl) {
600 599
601/* 600/*
602** Traverse a thread, marking the elements in the stack up to its top 601** Traverse a thread, marking the elements in the stack up to its top
603** and cleaning the rest of the stack in the final traversal. 602** and cleaning the rest of the stack in the final traversal. That
604** That ensures that the entire stack have valid (non-dead) objects. 603** ensures that the entire stack have valid (non-dead) objects.
604** Threads have no barriers. In gen. mode, old threads must be visited
605** at every cycle, because they might point to young objects. In inc.
606** mode, the thread can still be modified before the end of the cycle,
607** and therefore it must be visited again in the atomic phase. To ensure
608** these visits, threads must return to a gray list if they are not new
609** (which can only happen in generational mode) or if the traverse is in
610** the propagate phase (which can only happen in incremental mode).
605*/ 611*/
606static int traversethread (global_State *g, lua_State *th) { 612static int traversethread (global_State *g, lua_State *th) {
607 UpVal *uv; 613 UpVal *uv;
608 StkId o = th->stack; 614 StkId o = th->stack;
615 if (isold(th) || g->gcstate == GCSpropagate) {
616 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
617 black2gray(th);
618 }
609 if (o == NULL) 619 if (o == NULL)
610 return 1; /* stack not completely built yet */ 620 return 1; /* stack not completely built yet */
611 lua_assert(g->gcstate == GCSatomic || 621 lua_assert(g->gcstate == GCSatomic ||
@@ -644,12 +654,7 @@ static lu_mem propagatemark (global_State *g) {
644 case LUA_VLCL: return traverseLclosure(g, gco2lcl(o)); 654 case LUA_VLCL: return traverseLclosure(g, gco2lcl(o));
645 case LUA_VCCL: return traverseCclosure(g, gco2ccl(o)); 655 case LUA_VCCL: return traverseCclosure(g, gco2ccl(o));
646 case LUA_VPROTO: return traverseproto(g, gco2p(o)); 656 case LUA_VPROTO: return traverseproto(g, gco2p(o));
647 case LUA_VTHREAD: { 657 case LUA_VTHREAD: return traversethread(g, gco2th(o));
648 lua_State *th = gco2th(o);
649 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
650 black2gray(o);
651 return traversethread(g, th);
652 }
653 default: lua_assert(0); return 0; 658 default: lua_assert(0); return 0;
654 } 659 }
655} 660}
@@ -1028,7 +1033,6 @@ static void setpause (global_State *g);
1028** objects and turns the non dead to old. All non-dead threads---which 1033** objects and turns the non dead to old. All non-dead threads---which
1029** are now old---must be in a gray list. Everything else is not in a 1034** are now old---must be in a gray list. Everything else is not in a
1030** gray list. 1035** gray list.
1031**
1032*/ 1036*/
1033static void sweep2old (lua_State *L, GCObject **p) { 1037static void sweep2old (lua_State *L, GCObject **p) {
1034 GCObject *curr; 1038 GCObject *curr;
@@ -1139,10 +1143,16 @@ static GCObject **correctgraylist (GCObject **p) {
1139 goto remain; /* keep non-white threads on the list */ 1143 goto remain; /* keep non-white threads on the list */
1140 } 1144 }
1141 else { /* everything else is removed */ 1145 else { /* everything else is removed */
1142 lua_assert(isold(curr)); /* young objects should be white */ 1146 lua_assert(isold(curr)); /* young objects should be white here */
1143 if (getage(curr) == G_TOUCHED2) /* advance from G_TOUCHED2... */ 1147 if (getage(curr) == G_TOUCHED2) { /* advance from TOUCHED2... */
1144 changeage(curr, G_TOUCHED2, G_OLD); /* ... to G_OLD */ 1148 changeage(curr, G_TOUCHED2, G_OLD); /* ... to OLD */
1145 gray2black(curr); /* make object black */ 1149 lua_assert(isblack(curr)); /* TOUCHED2 objects are always black */
1150 }
1151 else {
1152 /* everything else in a gray list should be gray */
1153 lua_assert(isgray(curr));
1154 gray2black(curr); /* make object black (to be removed) */
1155 }
1146 goto remove; 1156 goto remove;
1147 } 1157 }
1148 remove: *p = *next; continue; 1158 remove: *p = *next; continue;
@@ -1207,11 +1217,12 @@ static void youngcollection (lua_State *L, global_State *g) {
1207 GCObject **psurvival; /* to point to first non-dead survival object */ 1217 GCObject **psurvival; /* to point to first non-dead survival object */
1208 GCObject *dummy; /* dummy out parameter to 'sweepgen' */ 1218 GCObject *dummy; /* dummy out parameter to 'sweepgen' */
1209 lua_assert(g->gcstate == GCSpropagate); 1219 lua_assert(g->gcstate == GCSpropagate);
1210 if (g->firstold1) { /* are there OLD1 objects? */ 1220 if (g->firstold1) { /* are there regular OLD1 objects? */
1211 markold(g, g->firstold1, g->reallyold); /* mark them */ 1221 markold(g, g->firstold1, g->reallyold); /* mark them */
1212 g->firstold1 = NULL; /* no more OLD1 objects (for now) */ 1222 g->firstold1 = NULL; /* no more OLD1 objects (for now) */
1213 } 1223 }
1214 markold(g, g->finobj, g->finobjrold); 1224 markold(g, g->finobj, g->finobjrold);
1225 markold(g, g->tobefnz, NULL);
1215 atomic(L); 1226 atomic(L);
1216 1227
1217 /* sweep nursery and get a pointer to its last live element */ 1228 /* sweep nursery and get a pointer to its last live element */
@@ -1268,8 +1279,8 @@ static void atomic2gen (lua_State *L, global_State *g) {
1268/* 1279/*
1269** Enter generational mode. Must go until the end of an atomic cycle 1280** Enter generational mode. Must go until the end of an atomic cycle
1270** to ensure that all objects are correctly marked and weak tables 1281** to ensure that all objects are correctly marked and weak tables
1271** are cleared. 1282** are cleared. Then, turn all objects into old and finishes the
1272** Then, turn all objects into old and finishes the collection. 1283** collection.
1273*/ 1284*/
1274static lu_mem entergen (lua_State *L, global_State *g) { 1285static lu_mem entergen (lua_State *L, global_State *g) {
1275 lu_mem numobjs; 1286 lu_mem numobjs;