diff options
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 47 |
1 files changed, 29 insertions, 18 deletions
@@ -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 | */ |
606 | static int traversethread (global_State *g, lua_State *th) { | 612 | static 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 | */ |
1033 | static void sweep2old (lua_State *L, GCObject **p) { | 1037 | static 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 | */ |
1274 | static lu_mem entergen (lua_State *L, global_State *g) { | 1285 | static lu_mem entergen (lua_State *L, global_State *g) { |
1275 | lu_mem numobjs; | 1286 | lu_mem numobjs; |