mirror of https://github.com/rusefi/lua.git
added 'local' bit (true => object is only refered by local variables)
This commit is contained in:
parent
3679d33b02
commit
439d74e29f
8
lapi.c
8
lapi.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lapi.c,v 2.185 2013/07/05 14:29:51 roberto Exp roberto $
|
||||
** $Id: lapi.c,v 2.186 2013/08/05 16:58:28 roberto Exp roberto $
|
||||
** Lua API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -586,8 +586,11 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
|
|||
cl = luaF_newCclosure(L, n);
|
||||
cl->c.f = fn;
|
||||
L->top -= n;
|
||||
while (n--)
|
||||
while (n--) {
|
||||
setobj2n(L, &cl->c.upvalue[n], L->top + n);
|
||||
/* does not need barrier because closure is white */
|
||||
valnolocal(L->top + n); /* but needs 'local barrier' */
|
||||
}
|
||||
setclCvalue(L, L->top, cl);
|
||||
}
|
||||
api_incr_top(L);
|
||||
|
@ -861,6 +864,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
|
|||
}
|
||||
default: {
|
||||
G(L)->mt[ttnov(obj)] = mt;
|
||||
if (mt) nolocal(obj2gco(mt));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
4
lfunc.c
4
lfunc.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lfunc.c,v 2.31 2013/08/05 16:58:28 roberto Exp roberto $
|
||||
** $Id: lfunc.c,v 2.32 2013/08/07 12:18:11 roberto Exp roberto $
|
||||
** Auxiliary functions to manipulate prototypes and closures
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -80,6 +80,7 @@ void luaF_close (lua_State *L, StkId level) {
|
|||
uv->v = &uv->value; /* now current value lives here */
|
||||
gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */
|
||||
g->allgc = o;
|
||||
valnolocal(uv->v); /* keep local invariant */
|
||||
luaC_checkupvalcolor(g, uv);
|
||||
}
|
||||
}
|
||||
|
@ -88,6 +89,7 @@ void luaF_close (lua_State *L, StkId level) {
|
|||
|
||||
Proto *luaF_newproto (lua_State *L) {
|
||||
Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p;
|
||||
nolocal(obj2gco(f)); /* prototypes are never local */
|
||||
f->k = NULL;
|
||||
f->sizek = 0;
|
||||
f->p = NULL;
|
||||
|
|
26
lgc.c
26
lgc.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lgc.c,v 2.144 2013/08/07 15:39:09 roberto Exp roberto $
|
||||
** $Id: lgc.c,v 2.145 2013/08/13 17:36:44 roberto Exp roberto $
|
||||
** Garbage Collector
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -74,11 +74,19 @@
|
|||
lua_longassert(!iscollectable(obj) || righttt(obj))
|
||||
|
||||
|
||||
#define markvalue(g,o) { checkconsistency(o); \
|
||||
#define marklocalvalue(g,o) { checkconsistency(o); \
|
||||
if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
|
||||
|
||||
#define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \
|
||||
reallymarkobject(g, obj2gco(t)); }
|
||||
#define markvalue(g,o) { \
|
||||
lua_longassert(!(iscollectable(o) && islocal(gcvalue(o)))); \
|
||||
marklocalvalue(g,o); }
|
||||
|
||||
#define marklocalobject(g,t) { \
|
||||
if ((t) && iswhite(obj2gco(t))) \
|
||||
reallymarkobject(g, obj2gco(t)); }
|
||||
|
||||
#define markobject(g,t) \
|
||||
{ lua_assert((t) == NULL || !islocal(obj2gco(t))); marklocalobject(g,t); }
|
||||
|
||||
static void reallymarkobject (global_State *g, GCObject *o);
|
||||
|
||||
|
@ -259,7 +267,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
|
|||
}
|
||||
case LUA_TUPVAL: {
|
||||
UpVal *uv = gco2uv(o);
|
||||
markvalue(g, uv->v);
|
||||
marklocalvalue(g, uv->v);
|
||||
if (uv->v != &uv->value) /* open? */
|
||||
return; /* open upvalues remain gray */
|
||||
size = sizeof(UpVal);
|
||||
|
@ -331,7 +339,7 @@ static void remarkupvals (global_State *g) {
|
|||
GCObject *uv = gco2th(thread)->openupval;
|
||||
for (; uv != NULL; uv = gch(uv)->next) {
|
||||
if (isgray(uv)) /* marked? */
|
||||
markvalue(g, gco2uv(uv)->v); /* remark upvalue's value */
|
||||
marklocalvalue(g, gco2uv(uv)->v); /* remark upvalue's value */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -486,7 +494,7 @@ static int traverseproto (global_State *g, Proto *f) {
|
|||
static lu_mem traverseCclosure (global_State *g, CClosure *cl) {
|
||||
int i;
|
||||
for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
|
||||
markvalue(g, &cl->upvalue[i]);
|
||||
marklocalvalue(g, &cl->upvalue[i]);
|
||||
return sizeCclosure(cl->nupvalues);
|
||||
}
|
||||
|
||||
|
@ -494,7 +502,7 @@ static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
|
|||
int i;
|
||||
markobject(g, cl->p); /* mark its prototype */
|
||||
for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
|
||||
markobject(g, cl->upvals[i]);
|
||||
marklocalobject(g, cl->upvals[i]);
|
||||
return sizeLclosure(cl->nupvalues);
|
||||
}
|
||||
|
||||
|
@ -505,7 +513,7 @@ static lu_mem traversestack (global_State *g, lua_State *th) {
|
|||
if (o == NULL)
|
||||
return 1; /* stack not completely built yet */
|
||||
for (; o < th->top; o++) /* mark live elements in the stack */
|
||||
markvalue(g, o);
|
||||
marklocalvalue(g, o);
|
||||
if (g->gcstate == GCSatomic) { /* final traversal? */
|
||||
StkId lim = th->stack + th->stacksize; /* real end of stack */
|
||||
for (; o < lim; o++) /* clear not-marked stack slice */
|
||||
|
|
20
lgc.h
20
lgc.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lgc.h,v 2.59 2013/08/05 16:58:28 roberto Exp roberto $
|
||||
** $Id: lgc.h,v 2.60 2013/08/13 17:36:44 roberto Exp roberto $
|
||||
** Garbage Collector
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -79,6 +79,7 @@
|
|||
#define FINALIZEDBIT 3 /* object has been separated for finalization */
|
||||
#define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */
|
||||
#define FIXEDBIT 5 /* object is fixed (should not be collected) */
|
||||
#define LOCALBIT 6 /* object is not local */
|
||||
/* bit 7 is currently used by tests (luaL_checkmemory) */
|
||||
|
||||
#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
|
||||
|
@ -88,6 +89,7 @@
|
|||
#define isblack(x) testbit((x)->gch.marked, BLACKBIT)
|
||||
#define isgray(x) /* neither white nor black */ \
|
||||
(!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT)))
|
||||
#define islocal(x) (!testbit((x)->gch.marked, LOCALBIT))
|
||||
|
||||
|
||||
#define otherwhite(g) (g->currentwhite ^ WHITEBITS)
|
||||
|
@ -97,6 +99,9 @@
|
|||
#define changewhite(x) ((x)->gch.marked ^= WHITEBITS)
|
||||
#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT)
|
||||
|
||||
#define nolocal(x) l_setbit((x)->gch.marked, LOCALBIT)
|
||||
#define valnolocal(v) { if (iscollectable(v)) nolocal(gcvalue(v)); }
|
||||
|
||||
#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
|
||||
|
||||
|
||||
|
@ -106,22 +111,25 @@
|
|||
|
||||
|
||||
#define luaC_barrier(L,p,v) { \
|
||||
if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \
|
||||
if (iscollectable(v) && \
|
||||
(nolocal(gcvalue(v)), isblack(obj2gco(p)) && iswhite(gcvalue(v)))) \
|
||||
luaC_barrier_(L,obj2gco(p),gcvalue(v)); }
|
||||
|
||||
#define luaC_barrierback(L,p,v) { \
|
||||
if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \
|
||||
if (iscollectable(v) && \
|
||||
(nolocal(gcvalue(v)), isblack(obj2gco(p)) && iswhite(gcvalue(v)))) \
|
||||
luaC_barrierback_(L,p); }
|
||||
|
||||
#define luaC_objbarrier(L,p,o) { \
|
||||
if (isblack(obj2gco(p)) && iswhite(obj2gco(o))) \
|
||||
if (nolocal(obj2gco(o)), isblack(obj2gco(p)) && iswhite(obj2gco(o))) \
|
||||
luaC_barrier_(L,obj2gco(p),obj2gco(o)); }
|
||||
|
||||
#define luaC_objbarrierback(L,p,o) \
|
||||
{ if (isblack(obj2gco(p)) && iswhite(obj2gco(o))) luaC_barrierback_(L,p); }
|
||||
{ if (nolocal(obj2gco(o)), isblack(obj2gco(p)) && iswhite(obj2gco(o))) \
|
||||
luaC_barrierback_(L,p); }
|
||||
|
||||
#define luaC_barrierproto(L,p,c) \
|
||||
{ if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); }
|
||||
{ if (nolocal(obj2gco(c)), isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); }
|
||||
|
||||
LUAI_FUNC void luaC_freeallobjects (lua_State *L);
|
||||
LUAI_FUNC void luaC_step (lua_State *L);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lparser.c,v 2.132 2013/04/25 19:35:19 roberto Exp roberto $
|
||||
** $Id: lparser.c,v 2.133 2013/04/26 13:07:53 roberto Exp roberto $
|
||||
** Lua Parser
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -1632,6 +1632,7 @@ Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
|
|||
incr_top(L);
|
||||
funcstate.f = cl->l.p = luaF_newproto(L);
|
||||
funcstate.f->source = luaS_new(L, name); /* create and anchor TString */
|
||||
luaC_objbarrier(L, funcstate.f, funcstate.f->source);
|
||||
lexstate.buff = buff;
|
||||
lexstate.dyd = dyd;
|
||||
dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
|
||||
|
|
17
lstate.c
17
lstate.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lstate.c,v 2.100 2013/08/05 16:58:28 roberto Exp roberto $
|
||||
** $Id: lstate.c,v 2.101 2013/08/07 12:18:11 roberto Exp roberto $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -159,17 +159,19 @@ static void freestack (lua_State *L) {
|
|||
** Create registry table and its predefined values
|
||||
*/
|
||||
static void init_registry (lua_State *L, global_State *g) {
|
||||
TValue mt;
|
||||
TValue temp;
|
||||
/* create registry */
|
||||
Table *registry = luaH_new(L);
|
||||
sethvalue(L, &g->l_registry, registry);
|
||||
luaH_resize(L, registry, LUA_RIDX_LAST, 0);
|
||||
nolocal(obj2gco(registry));
|
||||
/* registry[LUA_RIDX_MAINTHREAD] = L */
|
||||
setthvalue(L, &mt, L);
|
||||
luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt);
|
||||
setthvalue(L, &temp, L); /* temp = L */
|
||||
luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp);
|
||||
/* registry[LUA_RIDX_GLOBALS] = table of globals */
|
||||
sethvalue(L, &mt, luaH_new(L));
|
||||
luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt);
|
||||
sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */
|
||||
luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp);
|
||||
valnolocal(&temp); /* keep local invariant */
|
||||
}
|
||||
|
||||
|
||||
|
@ -236,6 +238,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
|
|||
setthvalue(L, L->top, L1);
|
||||
api_incr_top(L);
|
||||
preinit_state(L1, G(L));
|
||||
nolocal(obj2gco(L1)); /* threads are never local */
|
||||
L1->hookmask = L->hookmask;
|
||||
L1->basehookcount = L->basehookcount;
|
||||
L1->hook = L->hook;
|
||||
|
@ -268,7 +271,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
|
|||
L->next = NULL;
|
||||
L->tt = LUA_TTHREAD;
|
||||
g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
|
||||
L->marked = luaC_white(g);
|
||||
L->marked = luaC_white(g) | bitmask(LOCALBIT);
|
||||
g->gckind = KGC_NORMAL;
|
||||
preinit_state(L, g);
|
||||
g->frealloc = f;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lstring.h,v 1.48 2012/01/25 21:05:40 roberto Exp roberto $
|
||||
** $Id: lstring.h,v 1.49 2012/02/01 21:57:15 roberto Exp roberto $
|
||||
** String table (keep all strings handled by Lua)
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -19,7 +19,7 @@
|
|||
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
|
||||
(sizeof(s)/sizeof(char))-1))
|
||||
|
||||
#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT)
|
||||
#define luaS_fix(s) setbits((s)->tsv.marked, bit2mask(FIXEDBIT, LOCALBIT))
|
||||
|
||||
|
||||
/*
|
||||
|
|
57
ltests.c
57
ltests.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: ltests.c,v 2.140 2013/08/05 16:58:28 roberto Exp roberto $
|
||||
** $Id: ltests.c,v 2.141 2013/08/07 12:18:11 roberto Exp roberto $
|
||||
** Internal Module for Debugging of the Lua Implementation
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -188,6 +188,25 @@ static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check locality
|
||||
*/
|
||||
static int testobjref2 (GCObject *f, GCObject *t) {
|
||||
/* not a local or pointed by a thread? */
|
||||
if (!islocal(t) || gch(f)->tt == LUA_TTHREAD)
|
||||
return 1; /* ok */
|
||||
if (gch(t)->tt == LUA_TUPVAL) {
|
||||
lua_assert(gch(f)->tt == LUA_TLCL);
|
||||
return 1; /* upvalue pointed by a closure */
|
||||
}
|
||||
if (gch(f)->tt == LUA_TUPVAL) {
|
||||
UpVal *uv = gco2uv(f);
|
||||
return (uv->v != &uv->value); /* open upvalue can point to local stuff */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void printobj (global_State *g, GCObject *o) {
|
||||
int i = 1;
|
||||
GCObject *p;
|
||||
|
@ -198,24 +217,30 @@ static void printobj (global_State *g, GCObject *o) {
|
|||
if (p == NULL) i = 0; /* zero means 'not found' */
|
||||
else i = -i; /* negative means 'found in findobj list */
|
||||
}
|
||||
printf("||%d:%s(%p)-%c(%02X)||", i, ttypename(gch(o)->tt), (void *)o,
|
||||
printf("||%d:%s(%p)-%s-%c(%02X)||",
|
||||
i, ttypename(novariant(gch(o)->tt)), (void *)o,
|
||||
islocal(o)?"L":"NL",
|
||||
isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked);
|
||||
}
|
||||
|
||||
|
||||
static int testobjref (global_State *g, GCObject *f, GCObject *t) {
|
||||
int r = testobjref1(g,f,t);
|
||||
if (!r) {
|
||||
printf("%d(%02X) - ", g->gcstate, g->currentwhite);
|
||||
int r1 = testobjref1(g,f,t);
|
||||
int r2 = testobjref2(f,t);
|
||||
if (!r1 || !r2) {
|
||||
if (!r1)
|
||||
printf("%d(%02X) - ", g->gcstate, g->currentwhite);
|
||||
else
|
||||
printf("local violation - ");
|
||||
printobj(g, f);
|
||||
printf("\t-> ");
|
||||
printf(" -> ");
|
||||
printobj(g, t);
|
||||
printf("\n");
|
||||
}
|
||||
return r;
|
||||
return r1 && r2;
|
||||
}
|
||||
|
||||
#define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t)))
|
||||
#define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t)))
|
||||
|
||||
|
||||
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) {
|
|||
break;
|
||||
}
|
||||
case LUA_TTHREAD: {
|
||||
lua_assert(!islocal(o));
|
||||
checkstack(g, gco2th(o));
|
||||
break;
|
||||
}
|
||||
|
@ -617,22 +643,9 @@ static int get_gccolor (lua_State *L) {
|
|||
o = obj_at(L, 1);
|
||||
if (!iscollectable(o))
|
||||
lua_pushstring(L, "no collectable");
|
||||
else {
|
||||
int marked = gcvalue(o)->gch.marked;
|
||||
int n = 1;
|
||||
else
|
||||
lua_pushstring(L, iswhite(gcvalue(o)) ? "white" :
|
||||
isblack(gcvalue(o)) ? "black" : "grey");
|
||||
if (testbit(marked, FINALIZEDBIT)) {
|
||||
lua_pushliteral(L, "/finalized"); n++;
|
||||
}
|
||||
if (testbit(marked, SEPARATED)) {
|
||||
lua_pushliteral(L, "/separated"); n++;
|
||||
}
|
||||
if (testbit(marked, FIXEDBIT)) {
|
||||
lua_pushliteral(L, "/fixed"); n++;
|
||||
}
|
||||
lua_concat(L, n);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lundump.c,v 2.22 2012/05/08 13:53:33 roberto Exp roberto $
|
||||
** $Id: lundump.c,v 2.23 2013/04/26 18:48:35 roberto Exp roberto $
|
||||
** load precompiled Lua chunks
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -84,9 +84,12 @@ static TString* LoadString(LoadState* S)
|
|||
return NULL;
|
||||
else
|
||||
{
|
||||
TString* ts;
|
||||
char* s=luaZ_openspace(S->L,S->b,size);
|
||||
LoadBlock(S,s,size*sizeof(char));
|
||||
return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
|
||||
ts = luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
|
||||
nolocal(obj2gco(ts)); /* all strings here anchored in non-thread objects */
|
||||
return ts;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
3
lvm.c
3
lvm.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lvm.c,v 2.175 2013/06/20 15:02:49 roberto Exp roberto $
|
||||
** $Id: lvm.c,v 2.176 2013/07/10 17:15:12 roberto Exp roberto $
|
||||
** Lua virtual machine
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -416,6 +416,7 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
|
|||
ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx);
|
||||
else /* get upvalue from enclosing function */
|
||||
ncl->l.upvals[i] = encup[uv[i].idx];
|
||||
/* new closure is white and local, so we do not need a barrier here */
|
||||
}
|
||||
luaC_barrierproto(L, p, ncl);
|
||||
p->cache = ncl; /* save it on cache for reuse */
|
||||
|
|
Loading…
Reference in New Issue