diff options
| -rw-r--r-- | lfunc.c | 15 | ||||
| -rw-r--r-- | lgc.c | 6 | ||||
| -rw-r--r-- | lobject.h | 4 | ||||
| -rw-r--r-- | lstate.h | 3 | ||||
| -rw-r--r-- | ltests.c | 3 |
5 files changed, 13 insertions, 18 deletions
| @@ -59,14 +59,15 @@ void luaF_initupvals (lua_State *L, LClosure *cl) { | |||
| 59 | 59 | ||
| 60 | 60 | ||
| 61 | /* | 61 | /* |
| 62 | ** Create a new upvalue with the given tag at the given level, | 62 | ** Create a new upvalue at the given level, and link it to the list of |
| 63 | ** and link it to the list of open upvalues of 'L' after entry 'prev'. | 63 | ** open upvalues of 'L' after entry 'prev'. |
| 64 | **/ | 64 | **/ |
| 65 | static UpVal *newupval (lua_State *L, int tag, StkId level, UpVal **prev) { | 65 | static UpVal *newupval (lua_State *L, int tbc, StkId level, UpVal **prev) { |
| 66 | GCObject *o = luaC_newobj(L, tag, sizeof(UpVal)); | 66 | GCObject *o = luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal)); |
| 67 | UpVal *uv = gco2upv(o); | 67 | UpVal *uv = gco2upv(o); |
| 68 | UpVal *next = *prev; | 68 | UpVal *next = *prev; |
| 69 | uv->v = s2v(level); /* current value lives in the stack */ | 69 | uv->v = s2v(level); /* current value lives in the stack */ |
| 70 | uv->tbc = tbc; | ||
| 70 | uv->u.open.next = next; /* link it to list of open upvalues */ | 71 | uv->u.open.next = next; /* link it to list of open upvalues */ |
| 71 | uv->u.open.previous = prev; | 72 | uv->u.open.previous = prev; |
| 72 | if (next) | 73 | if (next) |
| @@ -94,7 +95,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { | |||
| 94 | pp = &p->u.open.next; | 95 | pp = &p->u.open.next; |
| 95 | } | 96 | } |
| 96 | /* not found: create a new upvalue after 'pp' */ | 97 | /* not found: create a new upvalue after 'pp' */ |
| 97 | return newupval(L, LUA_TUPVAL, level, pp); | 98 | return newupval(L, 0, level, pp); |
| 98 | } | 99 | } |
| 99 | 100 | ||
| 100 | 101 | ||
| @@ -170,7 +171,7 @@ static int callclosemth (lua_State *L, StkId level, int status) { | |||
| 170 | static void trynewtbcupval (lua_State *L, void *ud) { | 171 | static void trynewtbcupval (lua_State *L, void *ud) { |
| 171 | StkId level = cast(StkId, ud); | 172 | StkId level = cast(StkId, ud); |
| 172 | lua_assert(L->openupval == NULL || uplevel(L->openupval) < level); | 173 | lua_assert(L->openupval == NULL || uplevel(L->openupval) < level); |
| 173 | newupval(L, LUA_TUPVALTBC, level, &L->openupval); | 174 | newupval(L, 1, level, &L->openupval); |
| 174 | } | 175 | } |
| 175 | 176 | ||
| 176 | 177 | ||
| @@ -204,7 +205,7 @@ int luaF_close (lua_State *L, StkId level, int status) { | |||
| 204 | while ((uv = L->openupval) != NULL && uplevel(uv) >= level) { | 205 | while ((uv = L->openupval) != NULL && uplevel(uv) >= level) { |
| 205 | TValue *slot = &uv->u.value; /* new position for value */ | 206 | TValue *slot = &uv->u.value; /* new position for value */ |
| 206 | lua_assert(uplevel(uv) < L->top); | 207 | lua_assert(uplevel(uv) < L->top); |
| 207 | if (uv->tt == LUA_TUPVALTBC && status != NOCLOSINGMETH) { | 208 | if (uv->tbc && status != NOCLOSINGMETH) { |
| 208 | /* must run closing method, which may change the stack */ | 209 | /* must run closing method, which may change the stack */ |
| 209 | ptrdiff_t levelrel = savestack(L, level); | 210 | ptrdiff_t levelrel = savestack(L, level); |
| 210 | status = callclosemth(L, uplevel(uv), status); | 211 | status = callclosemth(L, uplevel(uv), status); |
| @@ -273,8 +273,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
| 273 | gray2black(o); | 273 | gray2black(o); |
| 274 | break; | 274 | break; |
| 275 | } | 275 | } |
| 276 | case LUA_TUPVAL: | 276 | case LUA_TUPVAL: { |
| 277 | case LUA_TUPVALTBC: { | ||
| 278 | UpVal *uv = gco2upv(o); | 277 | UpVal *uv = gco2upv(o); |
| 279 | if (!upisopen(uv)) /* open upvalues are kept gray */ | 278 | if (!upisopen(uv)) /* open upvalues are kept gray */ |
| 280 | gray2black(o); | 279 | gray2black(o); |
| @@ -571,7 +570,7 @@ static int traversethread (global_State *g, lua_State *th) { | |||
| 571 | for (; o < th->top; o++) /* mark live elements in the stack */ | 570 | for (; o < th->top; o++) /* mark live elements in the stack */ |
| 572 | markvalue(g, s2v(o)); | 571 | markvalue(g, s2v(o)); |
| 573 | for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) { | 572 | for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) { |
| 574 | if (uv->tt == LUA_TUPVALTBC) /* to be closed? */ | 573 | if (uv->tbc) /* to be closed? */ |
| 575 | markobject(g, uv); /* cannot be collected */ | 574 | markobject(g, uv); /* cannot be collected */ |
| 576 | } | 575 | } |
| 577 | if (g->gcstate == GCSatomic) { /* final traversal? */ | 576 | if (g->gcstate == GCSatomic) { /* final traversal? */ |
| @@ -706,7 +705,6 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
| 706 | luaF_freeproto(L, gco2p(o)); | 705 | luaF_freeproto(L, gco2p(o)); |
| 707 | break; | 706 | break; |
| 708 | case LUA_TUPVAL: | 707 | case LUA_TUPVAL: |
| 709 | case LUA_TUPVALTBC: | ||
| 710 | freeupval(L, gco2upv(o)); | 708 | freeupval(L, gco2upv(o)); |
| 711 | break; | 709 | break; |
| 712 | case LUA_TLCL: | 710 | case LUA_TLCL: |
| @@ -568,6 +568,7 @@ typedef struct Proto { | |||
| 568 | */ | 568 | */ |
| 569 | typedef struct UpVal { | 569 | typedef struct UpVal { |
| 570 | CommonHeader; | 570 | CommonHeader; |
| 571 | lu_byte tbc; /* true if it represents a to-be-closed variable */ | ||
| 571 | TValue *v; /* points to stack or to its own value */ | 572 | TValue *v; /* points to stack or to its own value */ |
| 572 | union { | 573 | union { |
| 573 | struct { /* (when open) */ | 574 | struct { /* (when open) */ |
| @@ -579,9 +580,6 @@ typedef struct UpVal { | |||
| 579 | } UpVal; | 580 | } UpVal; |
| 580 | 581 | ||
| 581 | 582 | ||
| 582 | /* variant for "To Be Closed" upvalues */ | ||
| 583 | #define LUA_TUPVALTBC (LUA_TUPVAL | (1 << 4)) | ||
| 584 | |||
| 585 | 583 | ||
| 586 | #define ClosureHeader \ | 584 | #define ClosureHeader \ |
| 587 | CommonHeader; lu_byte nupvalues; GCObject *gclist | 585 | CommonHeader; lu_byte nupvalues; GCObject *gclist |
| @@ -335,8 +335,7 @@ union GCUnion { | |||
| 335 | #define gco2t(o) check_exp((o)->tt == LUA_TTABLE, &((cast_u(o))->h)) | 335 | #define gco2t(o) check_exp((o)->tt == LUA_TTABLE, &((cast_u(o))->h)) |
| 336 | #define gco2p(o) check_exp((o)->tt == LUA_TPROTO, &((cast_u(o))->p)) | 336 | #define gco2p(o) check_exp((o)->tt == LUA_TPROTO, &((cast_u(o))->p)) |
| 337 | #define gco2th(o) check_exp((o)->tt == LUA_TTHREAD, &((cast_u(o))->th)) | 337 | #define gco2th(o) check_exp((o)->tt == LUA_TTHREAD, &((cast_u(o))->th)) |
| 338 | #define gco2upv(o) \ | 338 | #define gco2upv(o) check_exp((o)->tt == LUA_TUPVAL, &((cast_u(o))->upv)) |
| 339 | check_exp(novariant((o)->tt) == LUA_TUPVAL, &((cast_u(o))->upv)) | ||
| 340 | 339 | ||
| 341 | 340 | ||
| 342 | /* | 341 | /* |
| @@ -397,8 +397,7 @@ static void checkrefs (global_State *g, GCObject *o) { | |||
| 397 | checkudata(g, gco2u(o)); | 397 | checkudata(g, gco2u(o)); |
| 398 | break; | 398 | break; |
| 399 | } | 399 | } |
| 400 | case LUA_TUPVAL: | 400 | case LUA_TUPVAL: { |
| 401 | case LUA_TUPVALTBC: { | ||
| 402 | checkvalref(g, o, gco2upv(o)->v); | 401 | checkvalref(g, o, gco2upv(o)->v); |
| 403 | break; | 402 | break; |
| 404 | } | 403 | } |
