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 | |
parent | 422318f6777d8d3bac13ade797d9c8eaa38686b6 (diff) | |
download | lua-1afd5a152dc8b3a304236dc4e07bca38ea5eb53a.tar.gz lua-1afd5a152dc8b3a304236dc4e07bca38ea5eb53a.tar.bz2 lua-1afd5a152dc8b3a304236dc4e07bca38ea5eb53a.zip |
more generic way to handle 'gclist'
-rw-r--r-- | lapi.c | 8 | ||||
-rw-r--r-- | lgc.c | 112 | ||||
-rw-r--r-- | lgc.h | 4 | ||||
-rw-r--r-- | ltable.c | 4 | ||||
-rw-r--r-- | lvm.c | 6 | ||||
-rw-r--r-- | lvm.h | 4 |
6 files changed, 63 insertions, 75 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 2.282 2018/01/29 16:21:35 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.283 2018/02/05 17:10:52 roberto Exp roberto $ |
3 | ** Lua API | 3 | ** Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -828,7 +828,7 @@ LUA_API void lua_rawset (lua_State *L, int idx) { | |||
828 | slot = luaH_set(L, hvalue(o), s2v(L->top - 2)); | 828 | slot = luaH_set(L, hvalue(o), s2v(L->top - 2)); |
829 | setobj2t(L, slot, s2v(L->top - 1)); | 829 | setobj2t(L, slot, s2v(L->top - 1)); |
830 | invalidateTMcache(hvalue(o)); | 830 | invalidateTMcache(hvalue(o)); |
831 | luaC_barrierback(L, hvalue(o), s2v(L->top - 1)); | 831 | luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); |
832 | L->top -= 2; | 832 | L->top -= 2; |
833 | lua_unlock(L); | 833 | lua_unlock(L); |
834 | } | 834 | } |
@@ -841,7 +841,7 @@ LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { | |||
841 | o = index2value(L, idx); | 841 | o = index2value(L, idx); |
842 | api_check(L, ttistable(o), "table expected"); | 842 | api_check(L, ttistable(o), "table expected"); |
843 | luaH_setint(L, hvalue(o), n, s2v(L->top - 1)); | 843 | luaH_setint(L, hvalue(o), n, s2v(L->top - 1)); |
844 | luaC_barrierback(L, hvalue(o), s2v(L->top - 1)); | 844 | luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); |
845 | L->top--; | 845 | L->top--; |
846 | lua_unlock(L); | 846 | lua_unlock(L); |
847 | } | 847 | } |
@@ -857,7 +857,7 @@ LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { | |||
857 | setpvalue(&k, cast_voidp(p)); | 857 | setpvalue(&k, cast_voidp(p)); |
858 | slot = luaH_set(L, hvalue(o), &k); | 858 | slot = luaH_set(L, hvalue(o), &k); |
859 | setobj2t(L, slot, s2v(L->top - 1)); | 859 | setobj2t(L, slot, s2v(L->top - 1)); |
860 | luaC_barrierback(L, hvalue(o), s2v(L->top - 1)); | 860 | luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); |
861 | L->top--; | 861 | L->top--; |
862 | lua_unlock(L); | 862 | lua_unlock(L); |
863 | } | 863 | } |
@@ -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 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 2.100 2018/01/28 15:13:26 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.102 2018/02/19 13:55:34 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 | */ |
@@ -173,7 +173,7 @@ LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); | |||
173 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); | 173 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); |
174 | LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); | 174 | LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); |
175 | LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); | 175 | LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); |
176 | LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o); | 176 | LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); |
177 | LUAI_FUNC void luaC_protobarrier_ (lua_State *L, Proto *p); | 177 | LUAI_FUNC void luaC_protobarrier_ (lua_State *L, Proto *p); |
178 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); | 178 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); |
179 | LUAI_FUNC void luaC_changemode (lua_State *L, int newmode); | 179 | LUAI_FUNC void luaC_changemode (lua_State *L, int newmode); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 2.130 2017/12/29 15:58:23 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.131 2018/01/28 15:13:26 roberto Exp roberto $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -600,7 +600,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
600 | } | 600 | } |
601 | } | 601 | } |
602 | setnodekey(L, mp, key); | 602 | setnodekey(L, mp, key); |
603 | luaC_barrierback(L, t, key); | 603 | luaC_barrierback(L, obj2gco(t), key); |
604 | lua_assert(ttisnil(gval(mp))); | 604 | lua_assert(ttisnil(gval(mp))); |
605 | return gval(mp); | 605 | return gval(mp); |
606 | } | 606 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.340 2018/02/15 15:34:29 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.341 2018/02/17 19:20:00 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -223,7 +223,7 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | |||
223 | /* no metamethod and (now) there is an entry with given key */ | 223 | /* no metamethod and (now) there is an entry with given key */ |
224 | setobj2t(L, cast(TValue *, slot), val); /* set its new value */ | 224 | setobj2t(L, cast(TValue *, slot), val); /* set its new value */ |
225 | invalidateTMcache(h); | 225 | invalidateTMcache(h); |
226 | luaC_barrierback(L, h, val); | 226 | luaC_barrierback(L, obj2gco(h), val); |
227 | return; | 227 | return; |
228 | } | 228 | } |
229 | /* else will try the metamethod */ | 229 | /* else will try the metamethod */ |
@@ -1691,7 +1691,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1691 | TValue *val = s2v(ra + n); | 1691 | TValue *val = s2v(ra + n); |
1692 | setobj2t(L, &h->array[last - 1], val); | 1692 | setobj2t(L, &h->array[last - 1], val); |
1693 | last--; | 1693 | last--; |
1694 | luaC_barrierback(L, h, val); | 1694 | luaC_barrierback(L, obj2gco(h), val); |
1695 | } | 1695 | } |
1696 | vmbreak; | 1696 | vmbreak; |
1697 | } | 1697 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.h,v 2.47 2017/11/08 14:50:23 roberto Exp roberto $ | 2 | ** $Id: lvm.h,v 2.48 2017/11/29 13:02:17 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -96,7 +96,7 @@ | |||
96 | */ | 96 | */ |
97 | #define luaV_finishfastset(L,t,slot,v) \ | 97 | #define luaV_finishfastset(L,t,slot,v) \ |
98 | { setobj2t(L, cast(TValue *,slot), v); \ | 98 | { setobj2t(L, cast(TValue *,slot), v); \ |
99 | luaC_barrierback(L, hvalue(t), v); } | 99 | luaC_barrierback(L, gcvalue(t), v); } |
100 | 100 | ||
101 | 101 | ||
102 | 102 | ||