diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-08-07 14:53:38 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-08-07 14:53:38 -0300 |
commit | 65141832d29824ebfbf26e8af9e6e4b8549518d4 (patch) | |
tree | 3956c55c5e90d1946a2356fce5b884f4f238dd84 | |
parent | f13dc59416afa8fc93bb3d784d1a73e49e1b5b09 (diff) | |
download | lua-65141832d29824ebfbf26e8af9e6e4b8549518d4.tar.gz lua-65141832d29824ebfbf26e8af9e6e4b8549518d4.tar.bz2 lua-65141832d29824ebfbf26e8af9e6e4b8549518d4.zip |
Open upvalues should be gray when entering gen. mode
Open upvalues are never black; so, when entering generational mode,
they must be colored gray, not black.
-rw-r--r-- | lgc.c | 21 | ||||
-rw-r--r-- | lstate.h | 14 |
2 files changed, 21 insertions, 14 deletions
@@ -267,21 +267,22 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { | |||
267 | ** Mark an object. Userdata, strings, and closed upvalues are visited | 267 | ** Mark an object. Userdata, strings, and closed upvalues are visited |
268 | ** and turned black here. Other objects are marked gray and added | 268 | ** and turned black here. Other objects are marked gray and added |
269 | ** to appropriate list to be visited (and turned black) later. (Open | 269 | ** to appropriate list to be visited (and turned black) later. (Open |
270 | ** upvalues are already linked in 'headuv' list. They are kept gray | 270 | ** upvalues are already indirectly linked through the 'twups' list. They |
271 | ** to avoid barriers, as their values will be revisited by the thread.) | 271 | ** are kept gray to avoid barriers, as their values will be revisited by |
272 | ** the thread or by 'remarkupvals'.) | ||
272 | */ | 273 | */ |
273 | static void reallymarkobject (global_State *g, GCObject *o) { | 274 | static void reallymarkobject (global_State *g, GCObject *o) { |
274 | white2gray(o); | 275 | white2gray(o); |
275 | switch (o->tt) { | 276 | switch (o->tt) { |
276 | case LUA_VSHRSTR: | 277 | case LUA_VSHRSTR: |
277 | case LUA_VLNGSTR: { | 278 | case LUA_VLNGSTR: { |
278 | gray2black(o); | 279 | gray2black(o); /* nothing to visit */ |
279 | break; | 280 | break; |
280 | } | 281 | } |
281 | case LUA_VUPVAL: { | 282 | case LUA_VUPVAL: { |
282 | UpVal *uv = gco2upv(o); | 283 | UpVal *uv = gco2upv(o); |
283 | if (!upisopen(uv)) /* open upvalues are kept gray */ | 284 | if (!upisopen(uv)) /* open upvalues are kept gray */ |
284 | gray2black(o); | 285 | gray2black(o); /* closed upvalues are visited here */ |
285 | markvalue(g, uv->v); /* mark its content */ | 286 | markvalue(g, uv->v); /* mark its content */ |
286 | break; | 287 | break; |
287 | } | 288 | } |
@@ -296,7 +297,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
296 | } /* FALLTHROUGH */ | 297 | } /* FALLTHROUGH */ |
297 | case LUA_VLCL: case LUA_VCCL: case LUA_VTABLE: | 298 | case LUA_VLCL: case LUA_VCCL: case LUA_VTABLE: |
298 | case LUA_VTHREAD: case LUA_VPROTO: { | 299 | case LUA_VTHREAD: case LUA_VPROTO: { |
299 | linkobjgclist(o, g->gray); | 300 | linkobjgclist(o, g->gray); /* to be visited later */ |
300 | break; | 301 | break; |
301 | } | 302 | } |
302 | default: lua_assert(0); break; | 303 | default: lua_assert(0); break; |
@@ -355,8 +356,10 @@ static int remarkupvals (global_State *g) { | |||
355 | for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { | 356 | for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { |
356 | lua_assert(getage(uv) <= getage(thread)); | 357 | lua_assert(getage(uv) <= getage(thread)); |
357 | work++; | 358 | work++; |
358 | if (!iswhite(uv)) /* upvalue already visited? */ | 359 | if (!iswhite(uv)) { /* upvalue already visited? */ |
360 | lua_assert(upisopen(uv) && isgray(uv)); | ||
359 | markvalue(g, uv->v); /* mark its value */ | 361 | markvalue(g, uv->v); /* mark its value */ |
362 | } | ||
360 | } | 363 | } |
361 | } | 364 | } |
362 | } | 365 | } |
@@ -1028,8 +1031,8 @@ static void setpause (global_State *g); | |||
1028 | /* | 1031 | /* |
1029 | ** Sweep a list of objects to enter generational mode. Deletes dead | 1032 | ** Sweep a list of objects to enter generational mode. Deletes dead |
1030 | ** 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 |
1031 | ** 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 |
1032 | ** gray list. | 1035 | ** gray list. Open upvalues are also kept gray. |
1033 | */ | 1036 | */ |
1034 | static void sweep2old (lua_State *L, GCObject **p) { | 1037 | static void sweep2old (lua_State *L, GCObject **p) { |
1035 | GCObject *curr; | 1038 | GCObject *curr; |
@@ -1047,6 +1050,8 @@ static void sweep2old (lua_State *L, GCObject **p) { | |||
1047 | linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ | 1050 | linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ |
1048 | black2gray(th); /* OK if already gray */ | 1051 | black2gray(th); /* OK if already gray */ |
1049 | } | 1052 | } |
1053 | else if (curr->tt == LUA_VUPVAL && upisopen(gco2upv(curr))) | ||
1054 | black2gray(curr); /* open upvalues are always gray */ | ||
1050 | else /* everything else is black */ | 1055 | else /* everything else is black */ |
1051 | gray2black(curr); /* OK if already black */ | 1056 | gray2black(curr); /* OK if already black */ |
1052 | p = &curr->next; /* go to next element */ | 1057 | p = &curr->next; /* go to next element */ |
@@ -63,7 +63,7 @@ | |||
63 | ** can become gray have such a field. The field is not the same | 63 | ** can become gray have such a field. The field is not the same |
64 | ** in all objects, but it always has this name.) Any gray object | 64 | ** in all objects, but it always has this name.) Any gray object |
65 | ** must belong to one of these lists, and all objects in these lists | 65 | ** must belong to one of these lists, and all objects in these lists |
66 | ** must be gray (with one exception explained below): | 66 | ** must be gray (with two exceptions explained below): |
67 | ** | 67 | ** |
68 | ** 'gray': regular gray objects, still waiting to be visited. | 68 | ** 'gray': regular gray objects, still waiting to be visited. |
69 | ** 'grayagain': objects that must be revisited at the atomic phase. | 69 | ** 'grayagain': objects that must be revisited at the atomic phase. |
@@ -75,11 +75,13 @@ | |||
75 | ** 'ephemeron': ephemeron tables with white->white entries; | 75 | ** 'ephemeron': ephemeron tables with white->white entries; |
76 | ** 'allweak': tables with weak keys and/or weak values to be cleared. | 76 | ** 'allweak': tables with weak keys and/or weak values to be cleared. |
77 | ** | 77 | ** |
78 | ** The exception to that "gray rule" is the TOUCHED2 objects in | 78 | ** The exceptions to that "gray rule" are: |
79 | ** generational mode. Those objects stay in a gray list (because they | 79 | ** - TOUCHED2 objects in generational mode stay in a gray list (because |
80 | ** must be visited again at the end of the cycle), but they are marked | 80 | ** they must be visited again at the end of the cycle), but they are |
81 | ** black (because assignments to them must activate barriers, to move | 81 | ** marked black because assignments to them must activate barriers (to |
82 | ** them back to TOUCHED1). | 82 | ** move them back to TOUCHED1). |
83 | ** - Open upvales are kept gray to avoid barriers, but they stay out | ||
84 | ** of gray lists. (They don't even have a 'gclist' field.) | ||
83 | */ | 85 | */ |
84 | 86 | ||
85 | 87 | ||