diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-19 17:06:56 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-19 17:06:56 -0300 |
commit | 1afd5a152dc8b3a304236dc4e07bca38ea5eb53a (patch) | |
tree | 7c4f880b09a023a3fe527d7d2cbcec9f11c09302 /lgc.c | |
parent | 422318f6777d8d3bac13ade797d9c8eaa38686b6 (diff) | |
download | lua-1afd5a152dc8b3a304236dc4e07bca38ea5eb53a.tar.gz lua-1afd5a152dc8b3a304236dc4e07bca38ea5eb53a.tar.bz2 lua-1afd5a152dc8b3a304236dc4e07bca38ea5eb53a.zip |
more generic way to handle 'gclist'
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 112 |
1 files changed, 50 insertions, 62 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.245 2018/01/28 15:13:26 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.248 2018/02/19 16:02:25 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 | */ |
@@ -110,13 +110,32 @@ static lu_mem atomic (lua_State *L); | |||
110 | #define gnodelast(h) gnode(h, cast_sizet(sizenode(h))) | 110 | #define gnodelast(h) gnode(h, cast_sizet(sizenode(h))) |
111 | 111 | ||
112 | 112 | ||
113 | static GCObject **getgclist (GCObject *o) { | ||
114 | switch (o->tt) { | ||
115 | case LUA_TTABLE: return &gco2t(o)->gclist; | ||
116 | case LUA_TLCL: return &gco2lcl(o)->gclist; | ||
117 | case LUA_TCCL: return &gco2ccl(o)->gclist; | ||
118 | case LUA_TTHREAD: return &gco2th(o)->gclist; | ||
119 | case LUA_TPROTO: return &gco2p(o)->gclist; | ||
120 | default: lua_assert(0); return 0; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | |||
113 | /* | 125 | /* |
114 | ** link collectable object 'o' into list pointed by 'p' | 126 | ** Link a collectable object 'o' with a known type into list pointed by 'p'. |
115 | */ | 127 | */ |
116 | #define linkgclist(o,p) ((o)->gclist = (p), (p) = obj2gco(o)) | 128 | #define linkgclist(o,p) ((o)->gclist = (p), (p) = obj2gco(o)) |
117 | 129 | ||
118 | 130 | ||
119 | /* | 131 | /* |
132 | ** Link a generic collectable object 'o' into list pointed by 'p'. | ||
133 | */ | ||
134 | #define linkobjgclist(o,p) (*getgclist(o) = (p), (p) = obj2gco(o)) | ||
135 | |||
136 | |||
137 | |||
138 | /* | ||
120 | ** Clear keys for empty entries in tables. If entry is empty | 139 | ** Clear keys for empty entries in tables. If entry is empty |
121 | ** and its key is not marked, mark its entry as dead. This allows the | 140 | ** and its key is not marked, mark its entry as dead. This allows the |
122 | ** collection of the key, but keeps its entry in the table (its removal | 141 | ** collection of the key, but keeps its entry in the table (its removal |
@@ -175,14 +194,14 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { | |||
175 | ** barrier that moves collector backward, that is, mark the black object | 194 | ** barrier that moves collector backward, that is, mark the black object |
176 | ** pointing to a white object as gray again. | 195 | ** pointing to a white object as gray again. |
177 | */ | 196 | */ |
178 | void luaC_barrierback_ (lua_State *L, Table *t) { | 197 | void luaC_barrierback_ (lua_State *L, GCObject *o) { |
179 | global_State *g = G(L); | 198 | global_State *g = G(L); |
180 | lua_assert(isblack(t) && !isdead(g, t)); | 199 | lua_assert(isblack(o) && !isdead(g, o)); |
181 | lua_assert(g->gckind != KGC_GEN || (isold(t) && getage(t) != G_TOUCHED1)); | 200 | lua_assert(g->gckind != KGC_GEN || (isold(o) && getage(o) != G_TOUCHED1)); |
182 | if (getage(t) != G_TOUCHED2) /* not already in gray list? */ | 201 | if (getage(o) != G_TOUCHED2) /* not already in gray list? */ |
183 | linkgclist(t, g->grayagain); /* link it in 'grayagain' */ | 202 | linkobjgclist(o, g->grayagain); /* link it in 'grayagain' */ |
184 | black2gray(t); /* make table gray (again) */ | 203 | black2gray(o); /* make table gray (again) */ |
185 | setage(t, G_TOUCHED1); /* touched in current cycle */ | 204 | setage(o, G_TOUCHED1); /* touched in current cycle */ |
186 | } | 205 | } |
187 | 206 | ||
188 | 207 | ||
@@ -276,24 +295,9 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
276 | markvalue(g, uv->v); /* mark its content */ | 295 | markvalue(g, uv->v); /* mark its content */ |
277 | break; | 296 | break; |
278 | } | 297 | } |
279 | case LUA_TLCL: { | 298 | case LUA_TLCL: case LUA_TCCL: case LUA_TTABLE: |
280 | linkgclist(gco2lcl(o), g->gray); | 299 | case LUA_TTHREAD: case LUA_TPROTO: { |
281 | break; | 300 | linkobjgclist(o, g->gray); |
282 | } | ||
283 | case LUA_TCCL: { | ||
284 | linkgclist(gco2ccl(o), g->gray); | ||
285 | break; | ||
286 | } | ||
287 | case LUA_TTABLE: { | ||
288 | linkgclist(gco2t(o), g->gray); | ||
289 | break; | ||
290 | } | ||
291 | case LUA_TTHREAD: { | ||
292 | linkgclist(gco2th(o), g->gray); | ||
293 | break; | ||
294 | } | ||
295 | case LUA_TPROTO: { | ||
296 | linkgclist(gco2p(o), g->gray); | ||
297 | break; | 301 | break; |
298 | } | 302 | } |
299 | default: lua_assert(0); break; | 303 | default: lua_assert(0); break; |
@@ -605,34 +609,18 @@ static int traversethread (global_State *g, lua_State *th) { | |||
605 | static lu_mem propagatemark (global_State *g) { | 609 | static lu_mem propagatemark (global_State *g) { |
606 | GCObject *o = g->gray; | 610 | GCObject *o = g->gray; |
607 | gray2black(o); | 611 | gray2black(o); |
612 | g->gray = *getgclist(o); /* remove from 'gray' list */ | ||
608 | switch (o->tt) { | 613 | switch (o->tt) { |
609 | case LUA_TTABLE: { | 614 | case LUA_TTABLE: return traversetable(g, gco2t(o)); |
610 | Table *h = gco2t(o); | 615 | case LUA_TLCL: return traverseLclosure(g, gco2lcl(o)); |
611 | g->gray = h->gclist; /* remove from 'gray' list */ | 616 | case LUA_TCCL: return traverseCclosure(g, gco2ccl(o)); |
612 | return traversetable(g, h); | 617 | case LUA_TPROTO: return traverseproto(g, gco2p(o)); |
613 | } | ||
614 | case LUA_TLCL: { | ||
615 | LClosure *cl = gco2lcl(o); | ||
616 | g->gray = cl->gclist; /* remove from 'gray' list */ | ||
617 | return traverseLclosure(g, cl); | ||
618 | } | ||
619 | case LUA_TCCL: { | ||
620 | CClosure *cl = gco2ccl(o); | ||
621 | g->gray = cl->gclist; /* remove from 'gray' list */ | ||
622 | return traverseCclosure(g, cl); | ||
623 | } | ||
624 | case LUA_TTHREAD: { | 618 | case LUA_TTHREAD: { |
625 | lua_State *th = gco2th(o); | 619 | lua_State *th = gco2th(o); |
626 | g->gray = th->gclist; /* remove from 'gray' list */ | ||
627 | linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ | 620 | linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ |
628 | black2gray(o); | 621 | black2gray(o); |
629 | return traversethread(g, th); | 622 | return traversethread(g, th); |
630 | } | 623 | } |
631 | case LUA_TPROTO: { | ||
632 | Proto *p = gco2p(o); | ||
633 | g->gray = p->gclist; /* remove from 'gray' list */ | ||
634 | return traverseproto(g, p); | ||
635 | } | ||
636 | default: lua_assert(0); return 0; | 624 | default: lua_assert(0); return 0; |
637 | } | 625 | } |
638 | } | 626 | } |
@@ -1069,8 +1057,8 @@ static void whitelist (global_State *g, GCObject *p) { | |||
1069 | ** Correct a list of gray objects. Because this correction is | 1057 | ** Correct a list of gray objects. Because this correction is |
1070 | ** done after sweeping, young objects can be white and still | 1058 | ** done after sweeping, young objects can be white and still |
1071 | ** be in the list. They are only removed. | 1059 | ** be in the list. They are only removed. |
1072 | ** For tables, advance 'touched1' to 'touched2'; 'touched2' objects | 1060 | ** For tables and userdata, advance 'touched1' to 'touched2'; 'touched2' |
1073 | ** become regular old and are removed from the list. | 1061 | ** objects become regular old and are removed from the list. |
1074 | ** For threads, just remove white ones from the list. | 1062 | ** For threads, just remove white ones from the list. |
1075 | */ | 1063 | */ |
1076 | static GCObject **correctgraylist (GCObject **p) { | 1064 | static GCObject **correctgraylist (GCObject **p) { |
@@ -1078,21 +1066,21 @@ static GCObject **correctgraylist (GCObject **p) { | |||
1078 | while ((curr = *p) != NULL) { | 1066 | while ((curr = *p) != NULL) { |
1079 | switch (curr->tt) { | 1067 | switch (curr->tt) { |
1080 | case LUA_TTABLE: { | 1068 | case LUA_TTABLE: { |
1081 | Table *h = gco2t(curr); | 1069 | GCObject **next = getgclist(curr); |
1082 | if (getage(h) == G_TOUCHED1) { /* touched in this cycle? */ | 1070 | if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ |
1083 | lua_assert(isgray(h)); | 1071 | lua_assert(isgray(curr)); |
1084 | gray2black(h); /* make it black, for next barrier */ | 1072 | gray2black(curr); /* make it black, for next barrier */ |
1085 | changeage(h, G_TOUCHED1, G_TOUCHED2); | 1073 | changeage(curr, G_TOUCHED1, G_TOUCHED2); |
1086 | p = &h->gclist; /* go to next element */ | 1074 | p = next; /* go to next element */ |
1087 | } | 1075 | } |
1088 | else { | 1076 | else { |
1089 | if (!iswhite(h)) { | 1077 | if (!iswhite(curr)) { |
1090 | lua_assert(isold(h)); | 1078 | lua_assert(isold(curr)); |
1091 | if (getage(h) == G_TOUCHED2) | 1079 | if (getage(curr) == G_TOUCHED2) |
1092 | changeage(h, G_TOUCHED2, G_OLD); | 1080 | changeage(curr, G_TOUCHED2, G_OLD); |
1093 | gray2black(h); /* make it black */ | 1081 | gray2black(curr); /* make it black */ |
1094 | } | 1082 | } |
1095 | *p = h->gclist; /* remove 'curr' from gray list */ | 1083 | *p = *next; /* remove 'curr' from gray list */ |
1096 | } | 1084 | } |
1097 | break; | 1085 | break; |
1098 | } | 1086 | } |