diff options
| -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 | ||
