summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lapi.c22
-rw-r--r--ldo.c15
-rw-r--r--lfunc.c65
-rw-r--r--lfunc.h22
-rw-r--r--lgc.c142
-rw-r--r--lgc.h14
-rw-r--r--lobject.h13
-rw-r--r--lstate.c4
-rw-r--r--lstate.h14
-rw-r--r--ltests.c40
-rw-r--r--ltm.c4
-rw-r--r--lvm.c7
12 files changed, 157 insertions, 205 deletions
diff --git a/lapi.c b/lapi.c
index 62b5f1a3..f4a8beb4 100644
--- a/lapi.c
+++ b/lapi.c
@@ -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
1194static const char *aux_upvalue (StkId fi, int n, TValue **val, 1194static 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) {
1233LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { 1233LUA_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
diff --git a/ldo.c b/ldo.c
index 47e80f8a..d90bf263 100644
--- a/ldo.c
+++ b/ldo.c
@@ -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
142static void correctstack (lua_State *L, TValue *oldstack) { 142static 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
639static void f_parser (lua_State *L, void *ud) { 639static 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
diff --git a/lfunc.c b/lfunc.c
index 654344a6..5bbae69c 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -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
41UpVal *luaF_newupval (lua_State *L) { 41void 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
50UpVal *luaF_findupval (lua_State *L, StkId level) { 53UpVal *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
72void luaF_close (lua_State *L, StkId level) { 73void 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}
diff --git a/lfunc.h b/lfunc.h
index c5e8b89c..39dbc901 100644
--- a/lfunc.h
+++ b/lfunc.h
@@ -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*/
24struct 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
21LUAI_FUNC Proto *luaF_newproto (lua_State *L); 39LUAI_FUNC Proto *luaF_newproto (lua_State *L);
22LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems); 40LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems);
23LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems); 41LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems);
24LUAI_FUNC UpVal *luaF_newupval (lua_State *L); 42LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
25LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); 43LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
26LUAI_FUNC void luaF_close (lua_State *L, StkId level); 44LUAI_FUNC void luaF_close (lua_State *L, StkId level);
27LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); 45LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
diff --git a/lgc.c b/lgc.c
index d87d5afe..f09af8e7 100644
--- a/lgc.c
+++ b/lgc.c
@@ -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
95static void reallymarkobject (global_State *g, GCObject *o); 92static 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*/
182void luaC_checkupvalcolor (global_State *g, UpVal *uv) { 181LUAI_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) {
493static lu_mem traverseLclosure (global_State *g, LClosure *cl) { 480static 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
668void 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
676static 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
670static void freeobj (lua_State *L, GCObject *o) { 687static 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*/
705static 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
889static 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 }
diff --git a/lgc.h b/lgc.h
index b931ae1a..13563db3 100644
--- a/lgc.h
+++ b/lgc.h
@@ -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
130LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); 134LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
131LUAI_FUNC void luaC_freeallobjects (lua_State *L); 135LUAI_FUNC void luaC_freeallobjects (lua_State *L);
132LUAI_FUNC void luaC_step (lua_State *L); 136LUAI_FUNC void luaC_step (lua_State *L);
@@ -138,7 +142,9 @@ LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz,
138LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); 142LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v);
139LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); 143LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o);
140LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); 144LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c);
145LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv);
141LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); 146LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
142LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); 147LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv);
148
143 149
144#endif 150#endif
diff --git a/lobject.h b/lobject.h
index 3ab75ad5..e9a20915 100644
--- a/lobject.h
+++ b/lobject.h
@@ -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*/
395typedef struct UpVal { 394typedef 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/*
diff --git a/lstate.c b/lstate.c
index e6a75dbb..4d141aec 100644
--- a/lstate.c
+++ b/lstate.c
@@ -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;
diff --git a/lstate.h b/lstate.h
index 02180df7..e0aed2d9 100644
--- a/lstate.h
+++ b/lstate.h
@@ -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 */
diff --git a/ltests.c b/ltests.c
index 199a492f..e2057736 100644
--- a/ltests.c
+++ b/ltests.c
@@ -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) {
332static void checkstack (global_State *g, lua_State *L1) { 326static 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
diff --git a/ltm.c b/ltm.c
index aa290185..62c1430c 100644
--- a/ltm.c
+++ b/ltm.c
@@ -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
diff --git a/lvm.c b/lvm.c
index d29c0118..5ebeb30d 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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)));