diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-08-03 13:22:57 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-08-03 13:22:57 -0300 |
commit | b9b554e0f68726b19274209ea6ce910b7e9f5fbf (patch) | |
tree | 5e0b126da4447bcb7bdfc80821d209dc86584a9e /lgc.c | |
parent | 0dc5deca1c0182a4a3db2fcfd7bc721f27fb352b (diff) | |
download | lua-b9b554e0f68726b19274209ea6ce910b7e9f5fbf.tar.gz lua-b9b554e0f68726b19274209ea6ce910b7e9f5fbf.tar.bz2 lua-b9b554e0f68726b19274209ea6ce910b7e9f5fbf.zip |
Clearer handling of gray lists when entering generational mode
When entering generational mode, all objects are old. So, the only
objects that need to be in a gray list are threads, which can be
assigned without barriers. Changes in anything else (e.g., weak
tables) will trigger barriers that, if needed, will add the object
to a gray list.
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 36 |
1 files changed, 30 insertions, 6 deletions
@@ -368,12 +368,17 @@ static int remarkupvals (global_State *g) { | |||
368 | } | 368 | } |
369 | 369 | ||
370 | 370 | ||
371 | static void cleargraylists (global_State *g) { | ||
372 | g->gray = g->grayagain = NULL; | ||
373 | g->weak = g->allweak = g->ephemeron = NULL; | ||
374 | } | ||
375 | |||
376 | |||
371 | /* | 377 | /* |
372 | ** mark root set and reset all gray lists, to start a new collection | 378 | ** mark root set and reset all gray lists, to start a new collection |
373 | */ | 379 | */ |
374 | static void restartcollection (global_State *g) { | 380 | static void restartcollection (global_State *g) { |
375 | g->gray = g->grayagain = NULL; | 381 | cleargraylists(g); |
376 | g->weak = g->allweak = g->ephemeron = NULL; | ||
377 | markobject(g, g->mainthread); | 382 | markobject(g, g->mainthread); |
378 | markvalue(g, &g->l_registry); | 383 | markvalue(g, &g->l_registry); |
379 | markmt(g); | 384 | markmt(g); |
@@ -1019,19 +1024,30 @@ static void setpause (global_State *g); | |||
1019 | 1024 | ||
1020 | 1025 | ||
1021 | /* | 1026 | /* |
1022 | ** Sweep a list of objects, deleting dead ones and turning | 1027 | ** Sweep a list of objects to enter generational mode. Deletes dead |
1023 | ** the non dead to old (without changing their colors). | 1028 | ** 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 | ||
1030 | ** gray list. | ||
1031 | ** | ||
1024 | */ | 1032 | */ |
1025 | static void sweep2old (lua_State *L, GCObject **p) { | 1033 | static void sweep2old (lua_State *L, GCObject **p) { |
1026 | GCObject *curr; | 1034 | GCObject *curr; |
1035 | global_State *g = G(L); | ||
1027 | while ((curr = *p) != NULL) { | 1036 | while ((curr = *p) != NULL) { |
1028 | if (iswhite(curr)) { /* is 'curr' dead? */ | 1037 | if (iswhite(curr)) { /* is 'curr' dead? */ |
1029 | lua_assert(isdead(G(L), curr)); | 1038 | lua_assert(isdead(g, curr)); |
1030 | *p = curr->next; /* remove 'curr' from list */ | 1039 | *p = curr->next; /* remove 'curr' from list */ |
1031 | freeobj(L, curr); /* erase 'curr' */ | 1040 | freeobj(L, curr); /* erase 'curr' */ |
1032 | } | 1041 | } |
1033 | else { /* all surviving objects become old */ | 1042 | else { /* all surviving objects become old */ |
1034 | setage(curr, G_OLD); | 1043 | setage(curr, G_OLD); |
1044 | if (curr->tt == LUA_VTHREAD) { /* threads must be watched */ | ||
1045 | lua_State *th = gco2th(curr); | ||
1046 | linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ | ||
1047 | black2gray(th); /* OK if already gray */ | ||
1048 | } | ||
1049 | else /* everything else is black */ | ||
1050 | gray2black(curr); /* OK if already black */ | ||
1035 | p = &curr->next; /* go to next element */ | 1051 | p = &curr->next; /* go to next element */ |
1036 | } | 1052 | } |
1037 | } | 1053 | } |
@@ -1221,7 +1237,14 @@ static void youngcollection (lua_State *L, global_State *g) { | |||
1221 | } | 1237 | } |
1222 | 1238 | ||
1223 | 1239 | ||
1240 | /* | ||
1241 | ** Clears all gray lists, sweeps objects, and prepare sublists to enter | ||
1242 | ** generational mode. The sweeps remove dead objects and turn all | ||
1243 | ** surviving objects to old. Threads go back to 'grayagain'; everything | ||
1244 | ** else is turned black (not in any gray list). | ||
1245 | */ | ||
1224 | static void atomic2gen (lua_State *L, global_State *g) { | 1246 | static void atomic2gen (lua_State *L, global_State *g) { |
1247 | cleargraylists(g); | ||
1225 | /* sweep all elements making them old */ | 1248 | /* sweep all elements making them old */ |
1226 | g->gcstate = GCSswpallgc; | 1249 | g->gcstate = GCSswpallgc; |
1227 | sweep2old(L, &g->allgc); | 1250 | sweep2old(L, &g->allgc); |
@@ -1244,7 +1267,8 @@ static void atomic2gen (lua_State *L, global_State *g) { | |||
1244 | 1267 | ||
1245 | /* | 1268 | /* |
1246 | ** Enter generational mode. Must go until the end of an atomic cycle | 1269 | ** Enter generational mode. Must go until the end of an atomic cycle |
1247 | ** to ensure that all threads and weak tables are in the gray lists. | 1270 | ** to ensure that all objects are correctly marked and weak tables |
1271 | ** are cleared. | ||
1248 | ** Then, turn all objects into old and finishes the collection. | 1272 | ** Then, turn all objects into old and finishes the collection. |
1249 | */ | 1273 | */ |
1250 | static lu_mem entergen (lua_State *L, global_State *g) { | 1274 | static lu_mem entergen (lua_State *L, global_State *g) { |