diff options
-rw-r--r-- | lapi.c | 22 | ||||
-rw-r--r-- | ldo.c | 15 | ||||
-rw-r--r-- | lfunc.c | 65 | ||||
-rw-r--r-- | lfunc.h | 22 | ||||
-rw-r--r-- | lgc.c | 142 | ||||
-rw-r--r-- | lgc.h | 14 | ||||
-rw-r--r-- | lobject.h | 13 | ||||
-rw-r--r-- | lstate.c | 4 | ||||
-rw-r--r-- | lstate.h | 14 | ||||
-rw-r--r-- | ltests.c | 40 | ||||
-rw-r--r-- | ltm.c | 4 | ||||
-rw-r--r-- | lvm.c | 7 |
12 files changed, 157 insertions, 205 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 2.186 2013/08/05 16:58:28 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.187 2013/08/16 18:55:49 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 | */ |
@@ -1192,7 +1192,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { | |||
1192 | 1192 | ||
1193 | 1193 | ||
1194 | static const char *aux_upvalue (StkId fi, int n, TValue **val, | 1194 | static const char *aux_upvalue (StkId fi, int n, TValue **val, |
1195 | GCObject **owner) { | 1195 | GCObject **owner, UpVal **uv) { |
1196 | switch (ttype(fi)) { | 1196 | switch (ttype(fi)) { |
1197 | case LUA_TCCL: { /* C closure */ | 1197 | case LUA_TCCL: { /* C closure */ |
1198 | CClosure *f = clCvalue(fi); | 1198 | CClosure *f = clCvalue(fi); |
@@ -1207,7 +1207,7 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val, | |||
1207 | Proto *p = f->p; | 1207 | Proto *p = f->p; |
1208 | if (!(1 <= n && n <= p->sizeupvalues)) return NULL; | 1208 | if (!(1 <= n && n <= p->sizeupvalues)) return NULL; |
1209 | *val = f->upvals[n-1]->v; | 1209 | *val = f->upvals[n-1]->v; |
1210 | if (owner) *owner = obj2gco(f->upvals[n - 1]); | 1210 | if (uv) *uv = f->upvals[n - 1]; |
1211 | name = p->upvalues[n-1].name; | 1211 | name = p->upvalues[n-1].name; |
1212 | return (name == NULL) ? "" : getstr(name); | 1212 | return (name == NULL) ? "" : getstr(name); |
1213 | } | 1213 | } |
@@ -1220,7 +1220,7 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { | |||
1220 | const char *name; | 1220 | const char *name; |
1221 | TValue *val = NULL; /* to avoid warnings */ | 1221 | TValue *val = NULL; /* to avoid warnings */ |
1222 | lua_lock(L); | 1222 | lua_lock(L); |
1223 | name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL); | 1223 | name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL); |
1224 | if (name) { | 1224 | if (name) { |
1225 | setobj2s(L, L->top, val); | 1225 | setobj2s(L, L->top, val); |
1226 | api_incr_top(L); | 1226 | api_incr_top(L); |
@@ -1233,16 +1233,18 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { | |||
1233 | LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { | 1233 | LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { |
1234 | const char *name; | 1234 | const char *name; |
1235 | TValue *val = NULL; /* to avoid warnings */ | 1235 | TValue *val = NULL; /* to avoid warnings */ |
1236 | GCObject *owner = NULL; /* to avoid warnings */ | 1236 | GCObject *owner = NULL; |
1237 | UpVal *uv = NULL; | ||
1237 | StkId fi; | 1238 | StkId fi; |
1238 | lua_lock(L); | 1239 | lua_lock(L); |
1239 | fi = index2addr(L, funcindex); | 1240 | fi = index2addr(L, funcindex); |
1240 | api_checknelems(L, 1); | 1241 | api_checknelems(L, 1); |
1241 | name = aux_upvalue(fi, n, &val, &owner); | 1242 | name = aux_upvalue(fi, n, &val, &owner, &uv); |
1242 | if (name) { | 1243 | if (name) { |
1243 | L->top--; | 1244 | L->top--; |
1244 | setobj(L, val, L->top); | 1245 | setobj(L, val, L->top); |
1245 | luaC_barrier(L, owner, L->top); | 1246 | if (owner) { luaC_barrier(L, owner, L->top); } |
1247 | else if (uv) { luaC_upvalbarrier(L, uv); } | ||
1246 | } | 1248 | } |
1247 | lua_unlock(L); | 1249 | lua_unlock(L); |
1248 | return name; | 1250 | return name; |
@@ -1284,7 +1286,11 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, | |||
1284 | LClosure *f1; | 1286 | LClosure *f1; |
1285 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); | 1287 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); |
1286 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); | 1288 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); |
1289 | luaC_upvdeccount(L, *up1); | ||
1287 | *up1 = *up2; | 1290 | *up1 = *up2; |
1288 | luaC_objbarrier(L, f1, *up2); | 1291 | (*up1)->refcount++; |
1292 | if (upisopen(*up1)) (*up1)->u.op.touched = 1; | ||
1293 | luaC_upvalbarrier(L, *up1); | ||
1289 | } | 1294 | } |
1290 | 1295 | ||
1296 | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.108.1.2 2013/04/19 21:03:23 roberto Exp $ | 2 | ** $Id: ldo.c,v 2.109 2013/04/19 21:05:04 roberto Exp roberto $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -141,10 +141,10 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |||
141 | 141 | ||
142 | static void correctstack (lua_State *L, TValue *oldstack) { | 142 | static void correctstack (lua_State *L, TValue *oldstack) { |
143 | CallInfo *ci; | 143 | CallInfo *ci; |
144 | GCObject *up; | 144 | UpVal *up; |
145 | L->top = (L->top - oldstack) + L->stack; | 145 | L->top = (L->top - oldstack) + L->stack; |
146 | for (up = L->openupval; up != NULL; up = up->gch.next) | 146 | for (up = L->openupval; up != NULL; up = up->u.op.next) |
147 | gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; | 147 | up->v = (up->v - oldstack) + L->stack; |
148 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | 148 | for (ci = L->ci; ci != NULL; ci = ci->previous) { |
149 | ci->top = (ci->top - oldstack) + L->stack; | 149 | ci->top = (ci->top - oldstack) + L->stack; |
150 | ci->func = (ci->func - oldstack) + L->stack; | 150 | ci->func = (ci->func - oldstack) + L->stack; |
@@ -637,7 +637,6 @@ static void checkmode (lua_State *L, const char *mode, const char *x) { | |||
637 | 637 | ||
638 | 638 | ||
639 | static void f_parser (lua_State *L, void *ud) { | 639 | static void f_parser (lua_State *L, void *ud) { |
640 | int i; | ||
641 | Closure *cl; | 640 | Closure *cl; |
642 | struct SParser *p = cast(struct SParser *, ud); | 641 | struct SParser *p = cast(struct SParser *, ud); |
643 | int c = zgetc(p->z); /* read first character */ | 642 | int c = zgetc(p->z); /* read first character */ |
@@ -650,11 +649,7 @@ static void f_parser (lua_State *L, void *ud) { | |||
650 | cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); | 649 | cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); |
651 | } | 650 | } |
652 | lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues); | 651 | lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues); |
653 | for (i = 0; i < cl->l.nupvalues; i++) { /* initialize upvalues */ | 652 | luaF_initupvals(L, &cl->l); |
654 | UpVal *up = luaF_newupval(L); | ||
655 | cl->l.upvals[i] = up; | ||
656 | luaC_objbarrier(L, cl, up); | ||
657 | } | ||
658 | } | 653 | } |
659 | 654 | ||
660 | 655 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lfunc.c,v 2.34 2013/08/23 13:34:54 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 2.35 2013/08/26 12:41:10 roberto Exp roberto $ |
3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -38,32 +38,33 @@ Closure *luaF_newLclosure (lua_State *L, int n) { | |||
38 | } | 38 | } |
39 | 39 | ||
40 | 40 | ||
41 | UpVal *luaF_newupval (lua_State *L) { | 41 | void luaF_initupvals (lua_State *L, LClosure *cl) { |
42 | UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), | 42 | int i; |
43 | &G(L)->localupv, 0)->uv; | 43 | for (i = 0; i < cl->nupvalues; i++) { |
44 | uv->v = &uv->value; | 44 | UpVal *uv = luaM_new(L, UpVal); |
45 | setnilvalue(uv->v); | 45 | uv->refcount = 1; |
46 | return uv; | 46 | uv->v = &uv->u.value; /* make it closed */ |
47 | setnilvalue(uv->v); | ||
48 | cl->upvals[i] = uv; | ||
49 | } | ||
47 | } | 50 | } |
48 | 51 | ||
49 | 52 | ||
50 | UpVal *luaF_findupval (lua_State *L, StkId level) { | 53 | UpVal *luaF_findupval (lua_State *L, StkId level) { |
51 | global_State *g = G(L); | 54 | UpVal **pp = &L->openupval; |
52 | GCObject **pp = &L->openupval; | ||
53 | UpVal *p; | 55 | UpVal *p; |
54 | UpVal *uv; | 56 | UpVal *uv; |
55 | while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { | 57 | while (*pp != NULL && (p = *pp)->v >= level) { |
56 | GCObject *o = obj2gco(p); | 58 | lua_assert(upisopen(p)); |
57 | lua_assert(p->v != &p->value); | 59 | if (p->v == level) /* found a corresponding upvalue? */ |
58 | if (p->v == level) { /* found a corresponding upvalue? */ | 60 | return p; /* return it */ |
59 | if (isdead(g, o)) /* is it dead? */ | 61 | pp = &p->u.op.next; |
60 | changewhite(o); /* resurrect it */ | ||
61 | return p; | ||
62 | } | ||
63 | pp = &p->next; | ||
64 | } | 62 | } |
65 | /* not found: create a new one */ | 63 | /* not found: create a new one */ |
66 | uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv; | 64 | uv = luaM_new(L, UpVal); |
65 | uv->refcount = 0; | ||
66 | uv->u.op.next = *pp; | ||
67 | *pp = uv; | ||
67 | uv->v = level; /* current value lives in the stack */ | 68 | uv->v = level; /* current value lives in the stack */ |
68 | return uv; | 69 | return uv; |
69 | } | 70 | } |
@@ -71,27 +72,15 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { | |||
71 | 72 | ||
72 | void luaF_close (lua_State *L, StkId level) { | 73 | void luaF_close (lua_State *L, StkId level) { |
73 | UpVal *uv; | 74 | UpVal *uv; |
74 | global_State *g = G(L); | 75 | while (L->openupval != NULL && (uv = L->openupval)->v >= level) { |
75 | while (L->openupval != NULL && (uv = gco2uv(L->openupval))->v >= level) { | 76 | lua_assert(upisopen(uv)); |
76 | GCObject *o = obj2gco(uv); | 77 | L->openupval = uv->u.op.next; /* remove from `open' list */ |
77 | lua_assert(!isblack(o) && uv->v != &uv->value); | 78 | if (uv->refcount == 0) /* no references? */ |
78 | L->openupval = uv->next; /* remove from `open' list */ | ||
79 | if (isdead(g, o)) | ||
80 | luaM_free(L, uv); /* free upvalue */ | 79 | luaM_free(L, uv); /* free upvalue */ |
81 | else { | 80 | else { |
82 | setobj(L, &uv->value, uv->v); /* move value to upvalue slot */ | 81 | setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ |
83 | uv->v = &uv->value; /* now current value lives here */ | 82 | uv->v = &uv->u.value; /* now current value lives here */ |
84 | if (islocal(o)) { | 83 | luaC_upvalbarrier(L, uv); |
85 | gch(o)->next = g->localupv; /* link upvalue into 'localupv' list */ | ||
86 | g->localupv = o; | ||
87 | resetbit(o->gch.marked, LOCALBLACK); | ||
88 | } | ||
89 | else { /* link upvalue into 'allgc' list */ | ||
90 | gch(o)->next = g->allgc; | ||
91 | g->allgc = o; | ||
92 | } | ||
93 | valnolocal(uv->v); /* keep local invariant */ | ||
94 | luaC_checkupvalcolor(g, uv); | ||
95 | } | 84 | } |
96 | } | 85 | } |
97 | } | 86 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lfunc.h,v 2.8 2012/05/08 13:53:33 roberto Exp roberto $ | 2 | ** $Id: lfunc.h,v 2.9 2013/08/07 12:18:11 roberto Exp roberto $ |
3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -18,10 +18,28 @@ | |||
18 | cast(int, sizeof(TValue *)*((n)-1))) | 18 | cast(int, sizeof(TValue *)*((n)-1))) |
19 | 19 | ||
20 | 20 | ||
21 | /* | ||
22 | ** Upvalues for Lua closures | ||
23 | */ | ||
24 | struct UpVal { | ||
25 | TValue *v; /* points to stack or to its own value */ | ||
26 | unsigned int refcount; /* reference counter */ | ||
27 | union { | ||
28 | struct { /* (when open) */ | ||
29 | UpVal *next; /* linked list */ | ||
30 | int touched; /* mark to avoid cycles with dead threads */ | ||
31 | } op; | ||
32 | TValue value; /* the value (when closed) */ | ||
33 | } u; | ||
34 | }; | ||
35 | |||
36 | #define upisopen(up) ((up)->v != &(up)->u.value) | ||
37 | |||
38 | |||
21 | LUAI_FUNC Proto *luaF_newproto (lua_State *L); | 39 | LUAI_FUNC Proto *luaF_newproto (lua_State *L); |
22 | LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems); | 40 | LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems); |
23 | LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems); | 41 | LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems); |
24 | LUAI_FUNC UpVal *luaF_newupval (lua_State *L); | 42 | LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); |
25 | LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); | 43 | LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); |
26 | LUAI_FUNC void luaF_close (lua_State *L, StkId level); | 44 | LUAI_FUNC void luaF_close (lua_State *L, StkId level); |
27 | LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); | 45 | LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.151 2013/08/23 13:34:54 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.152 2013/08/26 12:41:10 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 | */ |
@@ -85,12 +85,9 @@ | |||
85 | lua_longassert(!(iscollectable(o) && islocal(gcvalue(o)))); \ | 85 | lua_longassert(!(iscollectable(o) && islocal(gcvalue(o)))); \ |
86 | marklocalvalue(g,o); } | 86 | marklocalvalue(g,o); } |
87 | 87 | ||
88 | #define marklocalobject(g,t) { \ | ||
89 | if ((t) && iswhite(obj2gco(t))) \ | ||
90 | reallymarkobject(g, obj2gco(t)); } | ||
91 | |||
92 | #define markobject(g,t) \ | 88 | #define markobject(g,t) \ |
93 | { lua_assert((t) == NULL || !islocal(obj2gco(t))); marklocalobject(g,t); } | 89 | { lua_assert((t) == NULL || !islocal(obj2gco(t))); \ |
90 | if ((t) && iswhite(obj2gco(t))) reallymarkobject(g, obj2gco(t)); } | ||
94 | 91 | ||
95 | static void reallymarkobject (global_State *g, GCObject *o); | 92 | static void reallymarkobject (global_State *g, GCObject *o); |
96 | 93 | ||
@@ -176,22 +173,18 @@ void luaC_barrierback_ (lua_State *L, GCObject *o) { | |||
176 | 173 | ||
177 | 174 | ||
178 | /* | 175 | /* |
179 | ** check color (and invariants) for an upvalue that is being closed, | 176 | ** barrier for assignments to closed upvalues. Because upvalues are |
180 | ** i.e., moved into the 'allgc' list | 177 | ** shared among closures, it is impossible to know the color of all |
178 | ** closured pointing to it. So, we assume that the object being assigned | ||
179 | ** must be marked. | ||
181 | */ | 180 | */ |
182 | void luaC_checkupvalcolor (global_State *g, UpVal *uv) { | 181 | LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { |
183 | GCObject *o = obj2gco(uv); | 182 | global_State *g = G(L); |
184 | lua_assert(!isblack(o)); /* open upvalues are never black */ | 183 | GCObject *o = gcvalue(uv->v); |
185 | if (isgray(o)) { | 184 | lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ |
186 | if (keepinvariant(g)) { | 185 | nolocal(o); |
187 | gray2black(o); /* it is being visited now */ | 186 | if (keepinvariant(g)) |
188 | markvalue(g, uv->v); | 187 | markobject(g, o); |
189 | } | ||
190 | else { | ||
191 | lua_assert(issweepphase(g)); | ||
192 | makewhite(g, o); | ||
193 | } | ||
194 | } | ||
195 | } | 188 | } |
196 | 189 | ||
197 | 190 | ||
@@ -257,14 +250,6 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
257 | size = sizeudata(gco2u(o)); | 250 | size = sizeudata(gco2u(o)); |
258 | break; | 251 | break; |
259 | } | 252 | } |
260 | case LUA_TUPVAL: { | ||
261 | UpVal *uv = gco2uv(o); | ||
262 | marklocalvalue(g, uv->v); | ||
263 | if (uv->v != &uv->value) /* open? */ | ||
264 | return; /* open upvalues remain gray */ | ||
265 | size = sizeof(UpVal); | ||
266 | break; | ||
267 | } | ||
268 | case LUA_TLCL: { | 253 | case LUA_TLCL: { |
269 | gco2lcl(o)->gclist = g->gray; | 254 | gco2lcl(o)->gclist = g->gray; |
270 | g->gray = o; | 255 | g->gray = o; |
@@ -328,10 +313,12 @@ static void remarkupvals (global_State *g) { | |||
328 | for (; thread != NULL; thread = gch(thread)->next) { | 313 | for (; thread != NULL; thread = gch(thread)->next) { |
329 | lua_assert(!isblack(thread)); /* threads are never black */ | 314 | lua_assert(!isblack(thread)); /* threads are never black */ |
330 | if (!isgray(thread)) { /* dead thread? */ | 315 | if (!isgray(thread)) { /* dead thread? */ |
331 | GCObject *uv = gco2th(thread)->openupval; | 316 | UpVal *uv = gco2th(thread)->openupval; |
332 | for (; uv != NULL; uv = gch(uv)->next) { | 317 | for (; uv != NULL; uv = uv->u.op.next) { |
333 | if (isgray(uv)) /* marked? */ | 318 | if (uv->u.op.touched) { |
334 | marklocalvalue(g, gco2uv(uv)->v); /* remark upvalue's value */ | 319 | marklocalvalue(g, uv->v); /* remark upvalue's value */ |
320 | uv->u.op.touched = 0; | ||
321 | } | ||
335 | } | 322 | } |
336 | } | 323 | } |
337 | } | 324 | } |
@@ -493,8 +480,15 @@ static lu_mem traverseCclosure (global_State *g, CClosure *cl) { | |||
493 | static lu_mem traverseLclosure (global_State *g, LClosure *cl) { | 480 | static lu_mem traverseLclosure (global_State *g, LClosure *cl) { |
494 | int i; | 481 | int i; |
495 | markobject(g, cl->p); /* mark its prototype */ | 482 | markobject(g, cl->p); /* mark its prototype */ |
496 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ | 483 | for (i = 0; i < cl->nupvalues; i++) { /* mark its upvalues */ |
497 | marklocalobject(g, cl->upvals[i]); | 484 | UpVal *uv = cl->upvals[i]; |
485 | if (uv != NULL) { | ||
486 | if (upisopen(uv)) | ||
487 | uv->u.op.touched = 1; /* can be marked in 'remarkupvals' */ | ||
488 | else | ||
489 | markvalue(g, uv->v); | ||
490 | } | ||
491 | } | ||
498 | return sizeLclosure(cl->nupvalues); | 492 | return sizeLclosure(cl->nupvalues); |
499 | } | 493 | } |
500 | 494 | ||
@@ -511,10 +505,14 @@ static lu_mem traversestack (global_State *g, lua_State *th) { | |||
511 | for (; o < lim; o++) /* clear not-marked stack slice */ | 505 | for (; o < lim; o++) /* clear not-marked stack slice */ |
512 | setnilvalue(o); | 506 | setnilvalue(o); |
513 | } | 507 | } |
514 | else { /* count call infos to compute size */ | 508 | else { |
515 | CallInfo *ci; | 509 | CallInfo *ci; |
510 | luaE_freeCI(th); /* free extra CallInfo slots */ | ||
516 | for (ci = &th->base_ci; ci != th->ci; ci = ci->next) | 511 | for (ci = &th->base_ci; ci != th->ci; ci = ci->next) |
517 | n++; | 512 | n++; /* count call infos to compute size */ |
513 | /* should not change the stack during an emergency gc cycle */ | ||
514 | if (g->gckind != KGC_EMERGENCY) | ||
515 | luaD_shrinkstack(th); | ||
518 | } | 516 | } |
519 | return sizeof(lua_State) + sizeof(TValue) * th->stacksize + | 517 | return sizeof(lua_State) + sizeof(TValue) * th->stacksize + |
520 | sizeof(CallInfo) * n; | 518 | sizeof(CallInfo) * n; |
@@ -667,18 +665,36 @@ static void clearvalues (global_State *g, GCObject *l, GCObject *f) { | |||
667 | } | 665 | } |
668 | 666 | ||
669 | 667 | ||
668 | void luaC_upvdeccount (lua_State *L, UpVal *uv) { | ||
669 | lua_assert(uv->refcount > 0); | ||
670 | uv->refcount--; | ||
671 | if (uv->refcount == 0 && !upisopen(uv)) | ||
672 | luaM_free(L, uv); | ||
673 | } | ||
674 | |||
675 | |||
676 | static void freeLclosure (lua_State *L, LClosure *cl) { | ||
677 | int i; | ||
678 | for (i = 0; i < cl->nupvalues; i++) { | ||
679 | UpVal *uv = cl->upvals[i]; | ||
680 | if (uv) | ||
681 | luaC_upvdeccount(L, uv); | ||
682 | } | ||
683 | luaM_freemem(L, cl, sizeLclosure(cl->nupvalues)); | ||
684 | } | ||
685 | |||
686 | |||
670 | static void freeobj (lua_State *L, GCObject *o) { | 687 | static void freeobj (lua_State *L, GCObject *o) { |
671 | switch (gch(o)->tt) { | 688 | switch (gch(o)->tt) { |
672 | case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; | 689 | case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; |
673 | case LUA_TLCL: { | 690 | case LUA_TLCL: { |
674 | luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); | 691 | freeLclosure(L, gco2lcl(o)); |
675 | break; | 692 | break; |
676 | } | 693 | } |
677 | case LUA_TCCL: { | 694 | case LUA_TCCL: { |
678 | luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); | 695 | luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); |
679 | break; | 696 | break; |
680 | } | 697 | } |
681 | case LUA_TUPVAL: luaM_free(L, gco2uv(o)); break; | ||
682 | case LUA_TTABLE: luaH_free(L, gco2t(o)); break; | 698 | case LUA_TTABLE: luaH_free(L, gco2t(o)); break; |
683 | case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; | 699 | case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; |
684 | case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; | 700 | case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; |
@@ -699,20 +715,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); | |||
699 | 715 | ||
700 | 716 | ||
701 | /* | 717 | /* |
702 | ** sweep the (open) upvalues of a thread and resize its stack and | ||
703 | ** list of call-info structures. | ||
704 | */ | ||
705 | static void sweepthread (lua_State *L, lua_State *L1) { | ||
706 | if (L1->stack == NULL) return; /* stack not completely built yet */ | ||
707 | sweepwholelist(L, &L1->openupval); /* sweep open upvalues */ | ||
708 | luaE_freeCI(L1); /* free extra CallInfo slots */ | ||
709 | /* should not change the stack during an emergency gc cycle */ | ||
710 | if (G(L)->gckind != KGC_EMERGENCY) | ||
711 | luaD_shrinkstack(L1); | ||
712 | } | ||
713 | |||
714 | |||
715 | /* | ||
716 | ** sweep at most 'count' elements from a list of GCObjects erasing dead | 718 | ** sweep at most 'count' elements from a list of GCObjects erasing dead |
717 | ** objects, where a dead (not alive) object is one marked with the "old" | 719 | ** objects, where a dead (not alive) object is one marked with the "old" |
718 | ** (non current) white and not fixed; change all non-dead objects back | 720 | ** (non current) white and not fixed; change all non-dead objects back |
@@ -730,10 +732,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { | |||
730 | *p = gch(curr)->next; /* remove 'curr' from list */ | 732 | *p = gch(curr)->next; /* remove 'curr' from list */ |
731 | freeobj(L, curr); /* erase 'curr' */ | 733 | freeobj(L, curr); /* erase 'curr' */ |
732 | } | 734 | } |
733 | else { | 735 | else { /* update marks */ |
734 | if (gch(curr)->tt == LUA_TTHREAD) | ||
735 | sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ | ||
736 | /* update marks */ | ||
737 | gch(curr)->marked = cast_byte((marked & maskcolors) | white); | 736 | gch(curr)->marked = cast_byte((marked & maskcolors) | white); |
738 | p = &gch(curr)->next; /* go to next element */ | 737 | p = &gch(curr)->next; /* go to next element */ |
739 | } | 738 | } |
@@ -886,16 +885,6 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
886 | */ | 885 | */ |
887 | 886 | ||
888 | 887 | ||
889 | static void localmarkclosure (LClosure *cl, int bit) { | ||
890 | int i; | ||
891 | for (i = 0; i < cl->nupvalues; i++) { | ||
892 | if (cl->upvals[i]) { | ||
893 | l_setbit(cl->upvals[i]->marked, bit); | ||
894 | } | ||
895 | } | ||
896 | } | ||
897 | |||
898 | |||
899 | /* | 888 | /* |
900 | ** Traverse a thread, local marking all its collectable objects | 889 | ** Traverse a thread, local marking all its collectable objects |
901 | */ | 890 | */ |
@@ -904,16 +893,8 @@ static void localmarkthread (lua_State *l) { | |||
904 | if (o == NULL) | 893 | if (o == NULL) |
905 | return; /* stack not completely built yet */ | 894 | return; /* stack not completely built yet */ |
906 | for (; o < l->top; o++) { /* mark live elements in the stack */ | 895 | for (; o < l->top; o++) { /* mark live elements in the stack */ |
907 | if (iscollectable(o)) { | 896 | if (iscollectable(o)) |
908 | GCObject *obj = gcvalue(o); | 897 | l_setbit(gcvalue(o)->gch.marked, LOCALBLACK); |
909 | if (obj->gch.tt == LUA_TLCL && /* is it a Lua closure? */ | ||
910 | islocal(obj) && /* is it still local? */ | ||
911 | !testbit(obj->gch.marked, LOCALBLACK)) { /* not visited yet? */ | ||
912 | /* mark its upvalues as local black */ | ||
913 | localmarkclosure(gco2lcl(obj), LOCALBLACK); | ||
914 | } | ||
915 | l_setbit(obj->gch.marked, LOCALBLACK); | ||
916 | } | ||
917 | } | 898 | } |
918 | } | 899 | } |
919 | 900 | ||
@@ -937,10 +918,6 @@ static void localsweep (lua_State *L, global_State *g, GCObject **p) { | |||
937 | *p = curr->gch.next; /* remove 'curr' from list */ | 918 | *p = curr->gch.next; /* remove 'curr' from list */ |
938 | curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */ | 919 | curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */ |
939 | g->allgc = curr; | 920 | g->allgc = curr; |
940 | if (curr->gch.tt == LUA_TLCL) { /* is it a Lua closure? */ | ||
941 | /* mark its upvalues as non local */ | ||
942 | localmarkclosure(gco2lcl(curr), LOCALBIT); | ||
943 | } | ||
944 | } | 921 | } |
945 | else { /* still local */ | 922 | else { /* still local */ |
946 | if (testbit(curr->gch.marked, LOCALBLACK)) { /* locally alive? */ | 923 | if (testbit(curr->gch.marked, LOCALBLACK)) { /* locally alive? */ |
@@ -965,7 +942,6 @@ static void luaC_localcollection (lua_State *L) { | |||
965 | lua_assert(g->gcstate == GCSpause); | 942 | lua_assert(g->gcstate == GCSpause); |
966 | localmark(g); | 943 | localmark(g); |
967 | localsweep(L, g, &g->localgc); | 944 | localsweep(L, g, &g->localgc); |
968 | localsweep(L, g, &g->localupv); | ||
969 | } | 945 | } |
970 | 946 | ||
971 | /* }====================================================== */ | 947 | /* }====================================================== */ |
@@ -1036,7 +1012,6 @@ void luaC_freeallobjects (lua_State *L) { | |||
1036 | g->gckind = KGC_NORMAL; | 1012 | g->gckind = KGC_NORMAL; |
1037 | sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ | 1013 | sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ |
1038 | sweepwholelist(L, &g->localgc); | 1014 | sweepwholelist(L, &g->localgc); |
1039 | sweepwholelist(L, &g->localupv); | ||
1040 | sweepwholelist(L, &g->allgc); | 1015 | sweepwholelist(L, &g->allgc); |
1041 | sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ | 1016 | sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ |
1042 | lua_assert(g->strt.nuse == 0); | 1017 | lua_assert(g->strt.nuse == 0); |
@@ -1119,7 +1094,6 @@ static lu_mem singlestep (lua_State *L) { | |||
1119 | } | 1094 | } |
1120 | else { | 1095 | else { |
1121 | sweepwholelist(L, &g->localgc); | 1096 | sweepwholelist(L, &g->localgc); |
1122 | sweepwholelist(L, &g->localupv); | ||
1123 | g->gcstate = GCSsweep; | 1097 | g->gcstate = GCSsweep; |
1124 | return GCLOCALPAUSE / 4; /* some magic for now */ | 1098 | return GCLOCALPAUSE / 4; /* some magic for now */ |
1125 | } | 1099 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 2.65 2013/08/21 20:09:51 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.66 2013/08/23 13:34:54 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 | */ |
@@ -55,7 +55,7 @@ | |||
55 | ** all objects are white again. | 55 | ** all objects are white again. |
56 | */ | 56 | */ |
57 | 57 | ||
58 | #define keepinvariant(g) (g->gcstate <= GCSatomic) | 58 | #define keepinvariant(g) ((g)->gcstate <= GCSatomic) |
59 | 59 | ||
60 | 60 | ||
61 | /* | 61 | /* |
@@ -91,7 +91,7 @@ | |||
91 | 91 | ||
92 | #define tofinalize(x) testbit((x)->gch.marked, FINALIZEDBIT) | 92 | #define tofinalize(x) testbit((x)->gch.marked, FINALIZEDBIT) |
93 | 93 | ||
94 | #define otherwhite(g) (g->currentwhite ^ WHITEBITS) | 94 | #define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) |
95 | #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) | 95 | #define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) |
96 | #define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked) | 96 | #define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked) |
97 | 97 | ||
@@ -127,6 +127,10 @@ | |||
127 | { if (nolocal(obj2gco(o)), isblack(obj2gco(p)) && iswhite(obj2gco(o))) \ | 127 | { if (nolocal(obj2gco(o)), isblack(obj2gco(p)) && iswhite(obj2gco(o))) \ |
128 | luaC_barrierback_(L,p); } | 128 | luaC_barrierback_(L,p); } |
129 | 129 | ||
130 | #define luaC_upvalbarrier(L,uv) \ | ||
131 | { if (iscollectable((uv)->v) && !upisopen(uv)) \ | ||
132 | luaC_upvalbarrier_(L,uv); } | ||
133 | |||
130 | LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); | 134 | LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); |
131 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); | 135 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); |
132 | LUAI_FUNC void luaC_step (lua_State *L); | 136 | LUAI_FUNC void luaC_step (lua_State *L); |
@@ -138,7 +142,9 @@ LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, | |||
138 | LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); | 142 | LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); |
139 | LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); | 143 | LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); |
140 | LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); | 144 | LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); |
145 | LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); | ||
141 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); | 146 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); |
142 | LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); | 147 | LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); |
148 | |||
143 | 149 | ||
144 | #endif | 150 | #endif |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.h,v 2.79 2013/08/07 12:18:11 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 2.80 2013/08/18 16:12:18 roberto Exp roberto $ |
3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -20,13 +20,12 @@ | |||
20 | ** Extra tags for non-values | 20 | ** Extra tags for non-values |
21 | */ | 21 | */ |
22 | #define LUA_TPROTO LUA_NUMTAGS | 22 | #define LUA_TPROTO LUA_NUMTAGS |
23 | #define LUA_TUPVAL (LUA_NUMTAGS+1) | 23 | #define LUA_TDEADKEY (LUA_NUMTAGS+1) |
24 | #define LUA_TDEADKEY (LUA_NUMTAGS+2) | ||
25 | 24 | ||
26 | /* | 25 | /* |
27 | ** number of all possible tags (including LUA_TNONE but excluding DEADKEY) | 26 | ** number of all possible tags (including LUA_TNONE but excluding DEADKEY) |
28 | */ | 27 | */ |
29 | #define LUA_TOTALTAGS (LUA_TUPVAL+2) | 28 | #define LUA_TOTALTAGS (LUA_TPROTO + 2) |
30 | 29 | ||
31 | 30 | ||
32 | /* | 31 | /* |
@@ -392,11 +391,7 @@ typedef struct Proto { | |||
392 | /* | 391 | /* |
393 | ** Lua Upvalues | 392 | ** Lua Upvalues |
394 | */ | 393 | */ |
395 | typedef struct UpVal { | 394 | typedef struct UpVal UpVal; |
396 | CommonHeader; | ||
397 | TValue *v; /* points to stack or to its own value */ | ||
398 | TValue value; /* the value (when closed) */ | ||
399 | } UpVal; | ||
400 | 395 | ||
401 | 396 | ||
402 | /* | 397 | /* |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.105 2013/08/23 13:34:54 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.106 2013/08/26 12:41:10 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -289,7 +289,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
289 | g->version = lua_version(NULL); | 289 | g->version = lua_version(NULL); |
290 | g->gcstate = GCSpause; | 290 | g->gcstate = GCSpause; |
291 | g->allgc = NULL; | 291 | g->allgc = NULL; |
292 | g->localgc = g->localupv = NULL; | 292 | g->localgc = NULL; |
293 | g->finobj = NULL; | 293 | g->finobj = NULL; |
294 | g->tobefnz = NULL; | 294 | g->tobefnz = NULL; |
295 | g->fixedgc = NULL; | 295 | g->fixedgc = NULL; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 2.89 2013/08/23 13:34:54 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.90 2013/08/26 12:41:10 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -27,13 +27,6 @@ | |||
27 | ** List 'fixedgc' keep objects that are not to be collected (currently | 27 | ** List 'fixedgc' keep objects that are not to be collected (currently |
28 | ** only small strings, such as reserved words). | 28 | ** only small strings, such as reserved words). |
29 | ** | 29 | ** |
30 | ** Open upvalues are not subject to independent garbage collection. They | ||
31 | ** are collected together with their respective threads. (They are | ||
32 | ** always gray, so they must be remarked in the atomic step. Usually | ||
33 | ** their contents would be marked when traversing the respective | ||
34 | ** threads, but the thread may already be dead, while the upvalue is | ||
35 | ** still accessible through closures.) | ||
36 | ** | ||
37 | ** Live objects with finalizers are kept in the list g->finobj. The | 30 | ** Live objects with finalizers are kept in the list g->finobj. The |
38 | ** list g->tobefnz links all objects being finalized. In particular, an | 31 | ** list g->tobefnz links all objects being finalized. In particular, an |
39 | ** object has its FINALIZEDBIT set iff it is in one of these lists. | 32 | ** object has its FINALIZEDBIT set iff it is in one of these lists. |
@@ -128,7 +121,6 @@ typedef struct global_State { | |||
128 | lu_byte gcrunning; /* true if GC is running */ | 121 | lu_byte gcrunning; /* true if GC is running */ |
129 | GCObject *allgc; /* list of all collectable objects */ | 122 | GCObject *allgc; /* list of all collectable objects */ |
130 | GCObject *localgc; /* list of local objects */ | 123 | GCObject *localgc; /* list of local objects */ |
131 | GCObject *localupv; /* list of local upvalues */ | ||
132 | GCObject *finobj; /* list of collectable objects with finalizers */ | 124 | GCObject *finobj; /* list of collectable objects with finalizers */ |
133 | GCObject **sweepgc; /* current position of sweep in list 'allgc' */ | 125 | GCObject **sweepgc; /* current position of sweep in list 'allgc' */ |
134 | GCObject **sweepfin; /* current position of sweep in list 'finobj' */ | 126 | GCObject **sweepfin; /* current position of sweep in list 'finobj' */ |
@@ -171,7 +163,7 @@ struct lua_State { | |||
171 | int basehookcount; | 163 | int basehookcount; |
172 | int hookcount; | 164 | int hookcount; |
173 | lua_Hook hook; | 165 | lua_Hook hook; |
174 | GCObject *openupval; /* list of open upvalues in this stack */ | 166 | UpVal *openupval; /* list of open upvalues in this stack */ |
175 | GCObject *gclist; | 167 | GCObject *gclist; |
176 | struct lua_longjmp *errorJmp; /* current error recover point */ | 168 | struct lua_longjmp *errorJmp; /* current error recover point */ |
177 | ptrdiff_t errfunc; /* current error handling function (stack index) */ | 169 | ptrdiff_t errfunc; /* current error handling function (stack index) */ |
@@ -192,7 +184,6 @@ union GCObject { | |||
192 | union Closure cl; | 184 | union Closure cl; |
193 | struct Table h; | 185 | struct Table h; |
194 | struct Proto p; | 186 | struct Proto p; |
195 | struct UpVal uv; | ||
196 | struct lua_State th; /* thread */ | 187 | struct lua_State th; /* thread */ |
197 | }; | 188 | }; |
198 | 189 | ||
@@ -211,7 +202,6 @@ union GCObject { | |||
211 | check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl)) | 202 | check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl)) |
212 | #define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) | 203 | #define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) |
213 | #define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) | 204 | #define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) |
214 | #define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) | ||
215 | #define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) | 205 | #define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) |
216 | 206 | ||
217 | /* macro to convert any Lua object into a GCObject */ | 207 | /* macro to convert any Lua object into a GCObject */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 2.148 2013/08/22 15:21:48 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.149 2013/08/26 12:41:10 roberto Exp roberto $ |
3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -195,14 +195,6 @@ static int testobjref2 (GCObject *f, GCObject *t) { | |||
195 | /* not a local or pointed by a thread? */ | 195 | /* not a local or pointed by a thread? */ |
196 | if (!islocal(t) || gch(f)->tt == LUA_TTHREAD) | 196 | if (!islocal(t) || gch(f)->tt == LUA_TTHREAD) |
197 | return 1; /* ok */ | 197 | return 1; /* ok */ |
198 | if (gch(t)->tt == LUA_TUPVAL) { | ||
199 | lua_assert(gch(f)->tt == LUA_TLCL); | ||
200 | return 1; /* upvalue pointed by a closure */ | ||
201 | } | ||
202 | if (gch(f)->tt == LUA_TUPVAL) { | ||
203 | UpVal *uv = gco2uv(f); | ||
204 | return (uv->v != &uv->value); /* open upvalue can point to local stuff */ | ||
205 | } | ||
206 | if (gch(f)->tt == LUA_TPROTO && gch(t)->tt == LUA_TLCL) | 198 | if (gch(f)->tt == LUA_TPROTO && gch(t)->tt == LUA_TLCL) |
207 | return 1; /* cache from a prototype */ | 199 | return 1; /* cache from a prototype */ |
208 | return 0; | 200 | return 0; |
@@ -311,9 +303,11 @@ static void checkLclosure (global_State *g, LClosure *cl) { | |||
311 | int i; | 303 | int i; |
312 | if (cl->p) checkobjref(g, clgc, cl->p); | 304 | if (cl->p) checkobjref(g, clgc, cl->p); |
313 | for (i=0; i<cl->nupvalues; i++) { | 305 | for (i=0; i<cl->nupvalues; i++) { |
314 | if (cl->upvals[i]) { | 306 | UpVal *uv = cl->upvals[i]; |
315 | lua_assert(cl->upvals[i]->tt == LUA_TUPVAL); | 307 | if (uv) { |
316 | checkobjref(g, clgc, cl->upvals[i]); | 308 | if (!upisopen(uv)) /* only closed upvalues matter to invariant */ |
309 | checkvalref(g, clgc, uv->v); | ||
310 | lua_assert(uv->refcount > 0); | ||
317 | } | 311 | } |
318 | } | 312 | } |
319 | } | 313 | } |
@@ -332,13 +326,10 @@ static int lua_checkpc (pCallInfo ci) { | |||
332 | static void checkstack (global_State *g, lua_State *L1) { | 326 | static void checkstack (global_State *g, lua_State *L1) { |
333 | StkId o; | 327 | StkId o; |
334 | CallInfo *ci; | 328 | CallInfo *ci; |
335 | GCObject *uvo; | 329 | UpVal *uv; |
336 | lua_assert(!isdead(g, obj2gco(L1))); | 330 | lua_assert(!isdead(g, obj2gco(L1))); |
337 | for (uvo = L1->openupval; uvo != NULL; uvo = gch(uvo)->next) { | 331 | for (uv = L1->openupval; uv != NULL; uv = uv->u.op.next) |
338 | UpVal *uv = gco2uv(uvo); | 332 | lua_assert(upisopen(uv)); /* must be open */ |
339 | lua_assert(uv->v != &uv->value); /* must be open */ | ||
340 | lua_assert(!isblack(uvo)); /* open upvalues cannot be black */ | ||
341 | } | ||
342 | for (ci = L1->ci; ci != NULL; ci = ci->previous) { | 333 | for (ci = L1->ci; ci != NULL; ci = ci->previous) { |
343 | lua_assert(ci->top <= L1->stack_last); | 334 | lua_assert(ci->top <= L1->stack_last); |
344 | lua_assert(lua_checkpc(ci)); | 335 | lua_assert(lua_checkpc(ci)); |
@@ -357,13 +348,6 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) { | |||
357 | else { | 348 | else { |
358 | lua_assert(g->gcstate != GCSpause || iswhite(o)); | 349 | lua_assert(g->gcstate != GCSpause || iswhite(o)); |
359 | switch (gch(o)->tt) { | 350 | switch (gch(o)->tt) { |
360 | case LUA_TUPVAL: { | ||
361 | UpVal *uv = gco2uv(o); | ||
362 | lua_assert(uv->v == &uv->value); /* must be closed */ | ||
363 | lua_assert(!isgray(o)); /* closed upvalues are never gray */ | ||
364 | checkvalref(g, o, uv->v); | ||
365 | break; | ||
366 | } | ||
367 | case LUA_TUSERDATA: { | 351 | case LUA_TUSERDATA: { |
368 | Table *mt = gco2u(o)->metatable; | 352 | Table *mt = gco2u(o)->metatable; |
369 | if (mt) checkobjref(g, o, mt); | 353 | if (mt) checkobjref(g, o, mt); |
@@ -490,12 +474,6 @@ int lua_checkmemory (lua_State *L) { | |||
490 | for (o = g->localgc; o != NULL; o = gch(o)->next) { | 474 | for (o = g->localgc; o != NULL; o = gch(o)->next) { |
491 | checkobject(g, o, 1); | 475 | checkobject(g, o, 1); |
492 | } | 476 | } |
493 | /* check 'localupv' list */ | ||
494 | checkgray(g, g->localupv); | ||
495 | for (o = g->localupv; o != NULL; o = gch(o)->next) { | ||
496 | lua_assert(gch(o)->tt == LUA_TUPVAL); | ||
497 | checkobject(g, o, 1); | ||
498 | } | ||
499 | return 0; | 477 | return 0; |
500 | } | 478 | } |
501 | 479 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.c,v 2.20 2013/05/06 17:19:11 roberto Exp roberto $ | 2 | ** $Id: ltm.c,v 2.21 2013/08/21 20:09:51 roberto Exp roberto $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -28,7 +28,7 @@ LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { | |||
28 | "no value", | 28 | "no value", |
29 | "nil", "boolean", udatatypename, "number", | 29 | "nil", "boolean", udatatypename, "number", |
30 | "string", "table", "function", udatatypename, "thread", | 30 | "string", "table", "function", udatatypename, "thread", |
31 | "proto", "upval" /* these last two cases are used for tests only */ | 31 | "proto" /* this last case is used for tests only */ |
32 | }; | 32 | }; |
33 | 33 | ||
34 | 34 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.177 2013/08/16 18:55:49 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.178 2013/08/19 14:18:43 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 | */ |
@@ -416,7 +416,8 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, | |||
416 | ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx); | 416 | ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx); |
417 | else /* get upvalue from enclosing function */ | 417 | else /* get upvalue from enclosing function */ |
418 | ncl->l.upvals[i] = encup[uv[i].idx]; | 418 | ncl->l.upvals[i] = encup[uv[i].idx]; |
419 | /* new closure is white and local, so we do not need a barrier here */ | 419 | ncl->l.upvals[i]->refcount++; |
420 | /* new closure is white, so we do not need a barrier here */ | ||
420 | } | 421 | } |
421 | if (!isblack(obj2gco(p))) /* cache will not break GC invariant? */ | 422 | if (!isblack(obj2gco(p))) /* cache will not break GC invariant? */ |
422 | p->cache = ncl; /* save it on cache for reuse */ | 423 | p->cache = ncl; /* save it on cache for reuse */ |
@@ -591,7 +592,7 @@ void luaV_execute (lua_State *L) { | |||
591 | vmcase(OP_SETUPVAL, | 592 | vmcase(OP_SETUPVAL, |
592 | UpVal *uv = cl->upvals[GETARG_B(i)]; | 593 | UpVal *uv = cl->upvals[GETARG_B(i)]; |
593 | setobj(L, uv->v, ra); | 594 | setobj(L, uv->v, ra); |
594 | luaC_barrier(L, uv, ra); | 595 | luaC_upvalbarrier(L, uv); |
595 | ) | 596 | ) |
596 | vmcase(OP_SETTABLE, | 597 | vmcase(OP_SETTABLE, |
597 | Protect(luaV_settable(L, ra, RKB(i), RKC(i))); | 598 | Protect(luaV_settable(L, ra, RKB(i), RKC(i))); |