aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-08-07 14:53:38 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-08-07 14:53:38 -0300
commit65141832d29824ebfbf26e8af9e6e4b8549518d4 (patch)
tree3956c55c5e90d1946a2356fce5b884f4f238dd84
parentf13dc59416afa8fc93bb3d784d1a73e49e1b5b09 (diff)
downloadlua-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.c21
-rw-r--r--lstate.h14
2 files changed, 21 insertions, 14 deletions
diff --git a/lgc.c b/lgc.c
index cb820f9c..7d62fafb 100644
--- a/lgc.c
+++ b/lgc.c
@@ -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*/
273static void reallymarkobject (global_State *g, GCObject *o) { 274static 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*/
1034static void sweep2old (lua_State *L, GCObject **p) { 1037static 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 */
diff --git a/lstate.h b/lstate.h
index 697d73b2..1b6bcdf8 100644
--- a/lstate.h
+++ b/lstate.h
@@ -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