Skip to content

Commit 439d74e

Browse files
committedAug 16, 2013
added 'local' bit (true => object is only refered by local variables)
1 parent 3679d33 commit 439d74e

10 files changed

+96
-53
lines changed
 

‎lapi.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: lapi.c,v 2.185 2013/07/05 14:29:51 roberto Exp roberto $
2+
** $Id: lapi.c,v 2.186 2013/08/05 16:58:28 roberto Exp roberto $
33
** Lua API
44
** See Copyright Notice in lua.h
55
*/
@@ -586,8 +586,11 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
586586
cl = luaF_newCclosure(L, n);
587587
cl->c.f = fn;
588588
L->top -= n;
589-
while (n--)
589+
while (n--) {
590590
setobj2n(L, &cl->c.upvalue[n], L->top + n);
591+
/* does not need barrier because closure is white */
592+
valnolocal(L->top + n); /* but needs 'local barrier' */
593+
}
591594
setclCvalue(L, L->top, cl);
592595
}
593596
api_incr_top(L);
@@ -861,6 +864,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
861864
}
862865
default: {
863866
G(L)->mt[ttnov(obj)] = mt;
867+
if (mt) nolocal(obj2gco(mt));
864868
break;
865869
}
866870
}

‎lfunc.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: lfunc.c,v 2.31 2013/08/05 16:58:28 roberto Exp roberto $
2+
** $Id: lfunc.c,v 2.32 2013/08/07 12:18:11 roberto Exp roberto $
33
** Auxiliary functions to manipulate prototypes and closures
44
** See Copyright Notice in lua.h
55
*/
@@ -80,6 +80,7 @@ void luaF_close (lua_State *L, StkId level) {
8080
uv->v = &uv->value; /* now current value lives here */
8181
gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */
8282
g->allgc = o;
83+
valnolocal(uv->v); /* keep local invariant */
8384
luaC_checkupvalcolor(g, uv);
8485
}
8586
}
@@ -88,6 +89,7 @@ void luaF_close (lua_State *L, StkId level) {
8889

8990
Proto *luaF_newproto (lua_State *L) {
9091
Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p;
92+
nolocal(obj2gco(f)); /* prototypes are never local */
9193
f->k = NULL;
9294
f->sizek = 0;
9395
f->p = NULL;

‎lgc.c

+17-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: lgc.c,v 2.144 2013/08/07 15:39:09 roberto Exp roberto $
2+
** $Id: lgc.c,v 2.145 2013/08/13 17:36:44 roberto Exp roberto $
33
** Garbage Collector
44
** See Copyright Notice in lua.h
55
*/
@@ -74,11 +74,19 @@
7474
lua_longassert(!iscollectable(obj) || righttt(obj))
7575

7676

77-
#define markvalue(g,o) { checkconsistency(o); \
77+
#define marklocalvalue(g,o) { checkconsistency(o); \
7878
if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
7979

80-
#define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \
81-
reallymarkobject(g, obj2gco(t)); }
80+
#define markvalue(g,o) { \
81+
lua_longassert(!(iscollectable(o) && islocal(gcvalue(o)))); \
82+
marklocalvalue(g,o); }
83+
84+
#define marklocalobject(g,t) { \
85+
if ((t) && iswhite(obj2gco(t))) \
86+
reallymarkobject(g, obj2gco(t)); }
87+
88+
#define markobject(g,t) \
89+
{ lua_assert((t) == NULL || !islocal(obj2gco(t))); marklocalobject(g,t); }
8290

8391
static void reallymarkobject (global_State *g, GCObject *o);
8492

@@ -259,7 +267,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
259267
}
260268
case LUA_TUPVAL: {
261269
UpVal *uv = gco2uv(o);
262-
markvalue(g, uv->v);
270+
marklocalvalue(g, uv->v);
263271
if (uv->v != &uv->value) /* open? */
264272
return; /* open upvalues remain gray */
265273
size = sizeof(UpVal);
@@ -331,7 +339,7 @@ static void remarkupvals (global_State *g) {
331339
GCObject *uv = gco2th(thread)->openupval;
332340
for (; uv != NULL; uv = gch(uv)->next) {
333341
if (isgray(uv)) /* marked? */
334-
markvalue(g, gco2uv(uv)->v); /* remark upvalue's value */
342+
marklocalvalue(g, gco2uv(uv)->v); /* remark upvalue's value */
335343
}
336344
}
337345
}
@@ -486,15 +494,15 @@ static int traverseproto (global_State *g, Proto *f) {
486494
static lu_mem traverseCclosure (global_State *g, CClosure *cl) {
487495
int i;
488496
for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
489-
markvalue(g, &cl->upvalue[i]);
497+
marklocalvalue(g, &cl->upvalue[i]);
490498
return sizeCclosure(cl->nupvalues);
491499
}
492500

493501
static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
494502
int i;
495503
markobject(g, cl->p); /* mark its prototype */
496504
for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
497-
markobject(g, cl->upvals[i]);
505+
marklocalobject(g, cl->upvals[i]);
498506
return sizeLclosure(cl->nupvalues);
499507
}
500508

@@ -505,7 +513,7 @@ static lu_mem traversestack (global_State *g, lua_State *th) {
505513
if (o == NULL)
506514
return 1; /* stack not completely built yet */
507515
for (; o < th->top; o++) /* mark live elements in the stack */
508-
markvalue(g, o);
516+
marklocalvalue(g, o);
509517
if (g->gcstate == GCSatomic) { /* final traversal? */
510518
StkId lim = th->stack + th->stacksize; /* real end of stack */
511519
for (; o < lim; o++) /* clear not-marked stack slice */

‎lgc.h

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: lgc.h,v 2.59 2013/08/05 16:58:28 roberto Exp roberto $
2+
** $Id: lgc.h,v 2.60 2013/08/13 17:36:44 roberto Exp roberto $
33
** Garbage Collector
44
** See Copyright Notice in lua.h
55
*/
@@ -79,6 +79,7 @@
7979
#define FINALIZEDBIT 3 /* object has been separated for finalization */
8080
#define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */
8181
#define FIXEDBIT 5 /* object is fixed (should not be collected) */
82+
#define LOCALBIT 6 /* object is not local */
8283
/* bit 7 is currently used by tests (luaL_checkmemory) */
8384

8485
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
@@ -88,6 +89,7 @@
8889
#define isblack(x) testbit((x)->gch.marked, BLACKBIT)
8990
#define isgray(x) /* neither white nor black */ \
9091
(!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT)))
92+
#define islocal(x) (!testbit((x)->gch.marked, LOCALBIT))
9193

9294

9395
#define otherwhite(g) (g->currentwhite ^ WHITEBITS)
@@ -97,6 +99,9 @@
9799
#define changewhite(x) ((x)->gch.marked ^= WHITEBITS)
98100
#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT)
99101

102+
#define nolocal(x) l_setbit((x)->gch.marked, LOCALBIT)
103+
#define valnolocal(v) { if (iscollectable(v)) nolocal(gcvalue(v)); }
104+
100105
#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
101106

102107

@@ -106,22 +111,25 @@
106111

107112

108113
#define luaC_barrier(L,p,v) { \
109-
if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \
114+
if (iscollectable(v) && \
115+
(nolocal(gcvalue(v)), isblack(obj2gco(p)) && iswhite(gcvalue(v)))) \
110116
luaC_barrier_(L,obj2gco(p),gcvalue(v)); }
111117

112118
#define luaC_barrierback(L,p,v) { \
113-
if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \
119+
if (iscollectable(v) && \
120+
(nolocal(gcvalue(v)), isblack(obj2gco(p)) && iswhite(gcvalue(v)))) \
114121
luaC_barrierback_(L,p); }
115122

116123
#define luaC_objbarrier(L,p,o) { \
117-
if (isblack(obj2gco(p)) && iswhite(obj2gco(o))) \
124+
if (nolocal(obj2gco(o)), isblack(obj2gco(p)) && iswhite(obj2gco(o))) \
118125
luaC_barrier_(L,obj2gco(p),obj2gco(o)); }
119126

120127
#define luaC_objbarrierback(L,p,o) \
121-
{ if (isblack(obj2gco(p)) && iswhite(obj2gco(o))) luaC_barrierback_(L,p); }
128+
{ if (nolocal(obj2gco(o)), isblack(obj2gco(p)) && iswhite(obj2gco(o))) \
129+
luaC_barrierback_(L,p); }
122130

123131
#define luaC_barrierproto(L,p,c) \
124-
{ if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); }
132+
{ if (nolocal(obj2gco(c)), isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); }
125133

126134
LUAI_FUNC void luaC_freeallobjects (lua_State *L);
127135
LUAI_FUNC void luaC_step (lua_State *L);

‎lparser.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: lparser.c,v 2.132 2013/04/25 19:35:19 roberto Exp roberto $
2+
** $Id: lparser.c,v 2.133 2013/04/26 13:07:53 roberto Exp roberto $
33
** Lua Parser
44
** See Copyright Notice in lua.h
55
*/
@@ -1632,6 +1632,7 @@ Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
16321632
incr_top(L);
16331633
funcstate.f = cl->l.p = luaF_newproto(L);
16341634
funcstate.f->source = luaS_new(L, name); /* create and anchor TString */
1635+
luaC_objbarrier(L, funcstate.f, funcstate.f->source);
16351636
lexstate.buff = buff;
16361637
lexstate.dyd = dyd;
16371638
dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;

‎lstate.c

+10-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: lstate.c,v 2.100 2013/08/05 16:58:28 roberto Exp roberto $
2+
** $Id: lstate.c,v 2.101 2013/08/07 12:18:11 roberto Exp roberto $
33
** Global State
44
** See Copyright Notice in lua.h
55
*/
@@ -159,17 +159,19 @@ static void freestack (lua_State *L) {
159159
** Create registry table and its predefined values
160160
*/
161161
static void init_registry (lua_State *L, global_State *g) {
162-
TValue mt;
162+
TValue temp;
163163
/* create registry */
164164
Table *registry = luaH_new(L);
165165
sethvalue(L, &g->l_registry, registry);
166166
luaH_resize(L, registry, LUA_RIDX_LAST, 0);
167+
nolocal(obj2gco(registry));
167168
/* registry[LUA_RIDX_MAINTHREAD] = L */
168-
setthvalue(L, &mt, L);
169-
luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt);
169+
setthvalue(L, &temp, L); /* temp = L */
170+
luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp);
170171
/* registry[LUA_RIDX_GLOBALS] = table of globals */
171-
sethvalue(L, &mt, luaH_new(L));
172-
luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt);
172+
sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */
173+
luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp);
174+
valnolocal(&temp); /* keep local invariant */
173175
}
174176

175177

@@ -236,6 +238,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
236238
setthvalue(L, L->top, L1);
237239
api_incr_top(L);
238240
preinit_state(L1, G(L));
241+
nolocal(obj2gco(L1)); /* threads are never local */
239242
L1->hookmask = L->hookmask;
240243
L1->basehookcount = L->basehookcount;
241244
L1->hook = L->hook;
@@ -268,7 +271,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
268271
L->next = NULL;
269272
L->tt = LUA_TTHREAD;
270273
g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
271-
L->marked = luaC_white(g);
274+
L->marked = luaC_white(g) | bitmask(LOCALBIT);
272275
g->gckind = KGC_NORMAL;
273276
preinit_state(L, g);
274277
g->frealloc = f;

‎lstring.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: lstring.h,v 1.48 2012/01/25 21:05:40 roberto Exp roberto $
2+
** $Id: lstring.h,v 1.49 2012/02/01 21:57:15 roberto Exp roberto $
33
** String table (keep all strings handled by Lua)
44
** See Copyright Notice in lua.h
55
*/
@@ -19,7 +19,7 @@
1919
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
2020
(sizeof(s)/sizeof(char))-1))
2121

22-
#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT)
22+
#define luaS_fix(s) setbits((s)->tsv.marked, bit2mask(FIXEDBIT, LOCALBIT))
2323

2424

2525
/*

‎ltests.c

+35-22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: ltests.c,v 2.140 2013/08/05 16:58:28 roberto Exp roberto $
2+
** $Id: ltests.c,v 2.141 2013/08/07 12:18:11 roberto Exp roberto $
33
** Internal Module for Debugging of the Lua Implementation
44
** See Copyright Notice in lua.h
55
*/
@@ -188,6 +188,25 @@ static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
188188
}
189189

190190

191+
/*
192+
** Check locality
193+
*/
194+
static int testobjref2 (GCObject *f, GCObject *t) {
195+
/* not a local or pointed by a thread? */
196+
if (!islocal(t) || gch(f)->tt == LUA_TTHREAD)
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+
return 0;
207+
}
208+
209+
191210
static void printobj (global_State *g, GCObject *o) {
192211
int i = 1;
193212
GCObject *p;
@@ -198,24 +217,30 @@ static void printobj (global_State *g, GCObject *o) {
198217
if (p == NULL) i = 0; /* zero means 'not found' */
199218
else i = -i; /* negative means 'found in findobj list */
200219
}
201-
printf("||%d:%s(%p)-%c(%02X)||", i, ttypename(gch(o)->tt), (void *)o,
220+
printf("||%d:%s(%p)-%s-%c(%02X)||",
221+
i, ttypename(novariant(gch(o)->tt)), (void *)o,
222+
islocal(o)?"L":"NL",
202223
isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked);
203224
}
204225

205226

206227
static int testobjref (global_State *g, GCObject *f, GCObject *t) {
207-
int r = testobjref1(g,f,t);
208-
if (!r) {
209-
printf("%d(%02X) - ", g->gcstate, g->currentwhite);
228+
int r1 = testobjref1(g,f,t);
229+
int r2 = testobjref2(f,t);
230+
if (!r1 || !r2) {
231+
if (!r1)
232+
printf("%d(%02X) - ", g->gcstate, g->currentwhite);
233+
else
234+
printf("local violation - ");
210235
printobj(g, f);
211-
printf("\t-> ");
236+
printf(" -> ");
212237
printobj(g, t);
213238
printf("\n");
214239
}
215-
return r;
240+
return r1 && r2;
216241
}
217242

218-
#define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t)))
243+
#define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t)))
219244

220245

221246
static void checkvalref (global_State *g, GCObject *f, const TValue *t) {
@@ -349,6 +374,7 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) {
349374
break;
350375
}
351376
case LUA_TTHREAD: {
377+
lua_assert(!islocal(o));
352378
checkstack(g, gco2th(o));
353379
break;
354380
}
@@ -617,22 +643,9 @@ static int get_gccolor (lua_State *L) {
617643
o = obj_at(L, 1);
618644
if (!iscollectable(o))
619645
lua_pushstring(L, "no collectable");
620-
else {
621-
int marked = gcvalue(o)->gch.marked;
622-
int n = 1;
646+
else
623647
lua_pushstring(L, iswhite(gcvalue(o)) ? "white" :
624648
isblack(gcvalue(o)) ? "black" : "grey");
625-
if (testbit(marked, FINALIZEDBIT)) {
626-
lua_pushliteral(L, "/finalized"); n++;
627-
}
628-
if (testbit(marked, SEPARATED)) {
629-
lua_pushliteral(L, "/separated"); n++;
630-
}
631-
if (testbit(marked, FIXEDBIT)) {
632-
lua_pushliteral(L, "/fixed"); n++;
633-
}
634-
lua_concat(L, n);
635-
}
636649
return 1;
637650
}
638651

‎lundump.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: lundump.c,v 2.22 2012/05/08 13:53:33 roberto Exp roberto $
2+
** $Id: lundump.c,v 2.23 2013/04/26 18:48:35 roberto Exp roberto $
33
** load precompiled Lua chunks
44
** See Copyright Notice in lua.h
55
*/
@@ -84,9 +84,12 @@ static TString* LoadString(LoadState* S)
8484
return NULL;
8585
else
8686
{
87+
TString* ts;
8788
char* s=luaZ_openspace(S->L,S->b,size);
8889
LoadBlock(S,s,size*sizeof(char));
89-
return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
90+
ts = luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
91+
nolocal(obj2gco(ts)); /* all strings here anchored in non-thread objects */
92+
return ts;
9093
}
9194
}
9295

‎lvm.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
** $Id: lvm.c,v 2.175 2013/06/20 15:02:49 roberto Exp roberto $
2+
** $Id: lvm.c,v 2.176 2013/07/10 17:15:12 roberto Exp roberto $
33
** Lua virtual machine
44
** See Copyright Notice in lua.h
55
*/
@@ -416,6 +416,7 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
416416
ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx);
417417
else /* get upvalue from enclosing function */
418418
ncl->l.upvals[i] = encup[uv[i].idx];
419+
/* new closure is white and local, so we do not need a barrier here */
419420
}
420421
luaC_barrierproto(L, p, ncl);
421422
p->cache = ncl; /* save it on cache for reuse */

0 commit comments

Comments
 (0)
Please sign in to comment.