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) { |
