Browse Source

upvalues collected by reference count

pull/9/head
Roberto Ierusalimschy 11 years ago
parent
commit
af35c7f398
  1. 22
      lapi.c
  2. 15
      ldo.c
  3. 65
      lfunc.c
  4. 22
      lfunc.h
  5. 142
      lgc.c
  6. 14
      lgc.h
  7. 13
      lobject.h
  8. 4
      lstate.c
  9. 14
      lstate.h
  10. 40
      ltests.c
  11. 4
      ltm.c
  12. 7
      lvm.c

22
lapi.c

@ -1,5 +1,5 @@
/*
** $Id: lapi.c,v 2.186 2013/08/05 16:58:28 roberto Exp roberto $
** $Id: lapi.c,v 2.187 2013/08/16 18:55:49 roberto Exp roberto $
** Lua API
** See Copyright Notice in lua.h
*/
@ -1192,7 +1192,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
static const char *aux_upvalue (StkId fi, int n, TValue **val,
GCObject **owner) {
GCObject **owner, UpVal **uv) {
switch (ttype(fi)) {
case LUA_TCCL: { /* C closure */
CClosure *f = clCvalue(fi);
@ -1207,7 +1207,7 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val,
Proto *p = f->p;
if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
*val = f->upvals[n-1]->v;
if (owner) *owner = obj2gco(f->upvals[n - 1]);
if (uv) *uv = f->upvals[n - 1];
name = p->upvalues[n-1].name;
return (name == NULL) ? "" : getstr(name);
}
@ -1220,7 +1220,7 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
const char *name;
TValue *val = NULL; /* to avoid warnings */
lua_lock(L);
name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL);
name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL);
if (name) {
setobj2s(L, L->top, val);
api_incr_top(L);
@ -1233,16 +1233,18 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
const char *name;
TValue *val = NULL; /* to avoid warnings */
GCObject *owner = NULL; /* to avoid warnings */
GCObject *owner = NULL;
UpVal *uv = NULL;
StkId fi;
lua_lock(L);
fi = index2addr(L, funcindex);
api_checknelems(L, 1);
name = aux_upvalue(fi, n, &val, &owner);
name = aux_upvalue(fi, n, &val, &owner, &uv);
if (name) {
L->top--;
setobj(L, val, L->top);
luaC_barrier(L, owner, L->top);
if (owner) { luaC_barrier(L, owner, L->top); }
else if (uv) { luaC_upvalbarrier(L, uv); }
}
lua_unlock(L);
return name;
@ -1284,7 +1286,11 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
LClosure *f1;
UpVal **up1 = getupvalref(L, fidx1, n1, &f1);
UpVal **up2 = getupvalref(L, fidx2, n2, NULL);
luaC_upvdeccount(L, *up1);
*up1 = *up2;
luaC_objbarrier(L, f1, *up2);
(*up1)->refcount++;
if (upisopen(*up1)) (*up1)->u.op.touched = 1;
luaC_upvalbarrier(L, *up1);
}

15
ldo.c

@ -1,5 +1,5 @@
/*
** $Id: ldo.c,v 2.108.1.2 2013/04/19 21:03:23 roberto Exp $
** $Id: ldo.c,v 2.109 2013/04/19 21:05:04 roberto Exp roberto $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@ -141,10 +141,10 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
static void correctstack (lua_State *L, TValue *oldstack) {
CallInfo *ci;
GCObject *up;
UpVal *up;
L->top = (L->top - oldstack) + L->stack;
for (up = L->openupval; up != NULL; up = up->gch.next)
gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
for (up = L->openupval; up != NULL; up = up->u.op.next)
up->v = (up->v - oldstack) + L->stack;
for (ci = L->ci; ci != NULL; ci = ci->previous) {
ci->top = (ci->top - oldstack) + L->stack;
ci->func = (ci->func - oldstack) + L->stack;
@ -637,7 +637,6 @@ static void checkmode (lua_State *L, const char *mode, const char *x) {
static void f_parser (lua_State *L, void *ud) {
int i;
Closure *cl;
struct SParser *p = cast(struct SParser *, ud);
int c = zgetc(p->z); /* read first character */
@ -650,11 +649,7 @@ static void f_parser (lua_State *L, void *ud) {
cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
}
lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues);
for (i = 0; i < cl->l.nupvalues; i++) { /* initialize upvalues */
UpVal *up = luaF_newupval(L);
cl->l.upvals[i] = up;
luaC_objbarrier(L, cl, up);
}
luaF_initupvals(L, &cl->l);
}

65
lfunc.c

@ -1,5 +1,5 @@
/*
** $Id: lfunc.c,v 2.34 2013/08/23 13:34:54 roberto Exp roberto $
** $Id: lfunc.c,v 2.35 2013/08/26 12:41:10 roberto Exp roberto $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@ -38,32 +38,33 @@ Closure *luaF_newLclosure (lua_State *L, int n) {
}
UpVal *luaF_newupval (lua_State *L) {
UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal),
&G(L)->localupv, 0)->uv;
uv->v = &uv->value;
setnilvalue(uv->v);
return uv;
void luaF_initupvals (lua_State *L, LClosure *cl) {
int i;
for (i = 0; i < cl->nupvalues; i++) {
UpVal *uv = luaM_new(L, UpVal);
uv->refcount = 1;
uv->v = &uv->u.value; /* make it closed */
setnilvalue(uv->v);
cl->upvals[i] = uv;
}
}
UpVal *luaF_findupval (lua_State *L, StkId level) {
global_State *g = G(L);
GCObject **pp = &L->openupval;
UpVal **pp = &L->openupval;
UpVal *p;
UpVal *uv;
while (*pp != NULL && (p = gco2uv(*pp))->v >= level) {
GCObject *o = obj2gco(p);
lua_assert(p->v != &p->value);
if (p->v == level) { /* found a corresponding upvalue? */
if (isdead(g, o)) /* is it dead? */
changewhite(o); /* resurrect it */
return p;
}
pp = &p->next;
while (*pp != NULL && (p = *pp)->v >= level) {
lua_assert(upisopen(p));
if (p->v == level) /* found a corresponding upvalue? */
return p; /* return it */
pp = &p->u.op.next;
}
/* not found: create a new one */
uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv;
uv = luaM_new(L, UpVal);
uv->refcount = 0;
uv->u.op.next = *pp;
*pp = uv;
uv->v = level; /* current value lives in the stack */
return uv;
}
@ -71,27 +72,15 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
void luaF_close (lua_State *L, StkId level) {
UpVal *uv;
global_State *g = G(L);
while (L->openupval != NULL && (uv = gco2uv(L->openupval))->v >= level) {
GCObject *o = obj2gco(uv);
lua_assert(!isblack(o) && uv->v != &uv->value);
L->openupval = uv->next; /* remove from `open' list */
if (isdead(g, o))
while (L->openupval != NULL && (uv = L->openupval)->v >= level) {
lua_assert(upisopen(uv));
L->openupval = uv->u.op.next; /* remove from `open' list */
if (uv->refcount == 0) /* no references? */
luaM_free(L, uv); /* free upvalue */
else {
setobj(L, &uv->value, uv->v); /* move value to upvalue slot */
uv->v = &uv->value; /* now current value lives here */
if (islocal(o)) {
gch(o)->next = g->localupv; /* link upvalue into 'localupv' list */
g->localupv = o;
resetbit(o->gch.marked, LOCALBLACK);
}
else { /* link upvalue into 'allgc' list */
gch(o)->next = g->allgc;
g->allgc = o;
}
valnolocal(uv->v); /* keep local invariant */
luaC_checkupvalcolor(g, uv);
setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */
uv->v = &uv->u.value; /* now current value lives here */
luaC_upvalbarrier(L, uv);
}
}
}

22
lfunc.h

@ -1,5 +1,5 @@
/*
** $Id: lfunc.h,v 2.8 2012/05/08 13:53:33 roberto Exp roberto $
** $Id: lfunc.h,v 2.9 2013/08/07 12:18:11 roberto Exp roberto $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@ -18,10 +18,28 @@
cast(int, sizeof(TValue *)*((n)-1)))
/*
** Upvalues for Lua closures
*/
struct UpVal {
TValue *v; /* points to stack or to its own value */
unsigned int refcount; /* reference counter */
union {
struct { /* (when open) */
UpVal *next; /* linked list */
int touched; /* mark to avoid cycles with dead threads */
} op;
TValue value; /* the value (when closed) */
} u;
};
#define upisopen(up) ((up)->v != &(up)->u.value)
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems);
LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems);
LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
LUAI_FUNC void luaF_close (lua_State *L, StkId level);
LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);

142
lgc.c

@ -1,5 +1,5 @@
/*
** $Id: lgc.c,v 2.151 2013/08/23 13:34:54 roberto Exp roberto $
** $Id: lgc.c,v 2.152 2013/08/26 12:41:10 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@ -85,12 +85,9 @@
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); }
{ lua_assert((t) == NULL || !islocal(obj2gco(t))); \
if ((t) && iswhite(obj2gco(t))) reallymarkobject(g, obj2gco(t)); }
static void reallymarkobject (global_State *g, GCObject *o);
@ -176,22 +173,18 @@ void luaC_barrierback_ (lua_State *L, GCObject *o) {
/*
** check color (and invariants) for an upvalue that is being closed,
** i.e., moved into the 'allgc' list
** barrier for assignments to closed upvalues. Because upvalues are
** shared among closures, it is impossible to know the color of all
** closured pointing to it. So, we assume that the object being assigned
** must be marked.
*/
void luaC_checkupvalcolor (global_State *g, UpVal *uv) {
GCObject *o = obj2gco(uv);
lua_assert(!isblack(o)); /* open upvalues are never black */
if (isgray(o)) {
if (keepinvariant(g)) {
gray2black(o); /* it is being visited now */
markvalue(g, uv->v);
}
else {
lua_assert(issweepphase(g));
makewhite(g, o);
}
}
LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
global_State *g = G(L);
GCObject *o = gcvalue(uv->v);
lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */
nolocal(o);
if (keepinvariant(g))
markobject(g, o);
}
@ -257,14 +250,6 @@ static void reallymarkobject (global_State *g, GCObject *o) {
size = sizeudata(gco2u(o));
break;
}
case LUA_TUPVAL: {
UpVal *uv = gco2uv(o);
marklocalvalue(g, uv->v);
if (uv->v != &uv->value) /* open? */
return; /* open upvalues remain gray */
size = sizeof(UpVal);
break;
}
case LUA_TLCL: {
gco2lcl(o)->gclist = g->gray;
g->gray = o;
@ -328,10 +313,12 @@ static void remarkupvals (global_State *g) {
for (; thread != NULL; thread = gch(thread)->next) {
lua_assert(!isblack(thread)); /* threads are never black */
if (!isgray(thread)) { /* dead thread? */
GCObject *uv = gco2th(thread)->openupval;
for (; uv != NULL; uv = gch(uv)->next) {
if (isgray(uv)) /* marked? */
marklocalvalue(g, gco2uv(uv)->v); /* remark upvalue's value */
UpVal *uv = gco2th(thread)->openupval;
for (; uv != NULL; uv = uv->u.op.next) {
if (uv->u.op.touched) {
marklocalvalue(g, uv->v); /* remark upvalue's value */
uv->u.op.touched = 0;
}
}
}
}
@ -493,8 +480,15 @@ static lu_mem traverseCclosure (global_State *g, CClosure *cl) {
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 */
marklocalobject(g, cl->upvals[i]);
for (i = 0; i < cl->nupvalues; i++) { /* mark its upvalues */
UpVal *uv = cl->upvals[i];
if (uv != NULL) {
if (upisopen(uv))
uv->u.op.touched = 1; /* can be marked in 'remarkupvals' */
else
markvalue(g, uv->v);
}
}
return sizeLclosure(cl->nupvalues);
}
@ -511,10 +505,14 @@ static lu_mem traversestack (global_State *g, lua_State *th) {
for (; o < lim; o++) /* clear not-marked stack slice */
setnilvalue(o);
}
else { /* count call infos to compute size */
else {
CallInfo *ci;
luaE_freeCI(th); /* free extra CallInfo slots */
for (ci = &th->base_ci; ci != th->ci; ci = ci->next)
n++;
n++; /* count call infos to compute size */
/* should not change the stack during an emergency gc cycle */
if (g->gckind != KGC_EMERGENCY)
luaD_shrinkstack(th);
}
return sizeof(lua_State) + sizeof(TValue) * th->stacksize +
sizeof(CallInfo) * n;
@ -667,18 +665,36 @@ static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
}
void luaC_upvdeccount (lua_State *L, UpVal *uv) {
lua_assert(uv->refcount > 0);
uv->refcount--;
if (uv->refcount == 0 && !upisopen(uv))
luaM_free(L, uv);
}
static void freeLclosure (lua_State *L, LClosure *cl) {
int i;
for (i = 0; i < cl->nupvalues; i++) {
UpVal *uv = cl->upvals[i];
if (uv)
luaC_upvdeccount(L, uv);
}
luaM_freemem(L, cl, sizeLclosure(cl->nupvalues));
}
static void freeobj (lua_State *L, GCObject *o) {
switch (gch(o)->tt) {
case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;
case LUA_TLCL: {
luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues));
freeLclosure(L, gco2lcl(o));
break;
}
case LUA_TCCL: {
luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues));
break;
}
case LUA_TUPVAL: luaM_free(L, gco2uv(o)); break;
case LUA_TTABLE: luaH_free(L, gco2t(o)); break;
case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break;
case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
@ -698,20 +714,6 @@ static void freeobj (lua_State *L, GCObject *o) {
static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count);
/*
** sweep the (open) upvalues of a thread and resize its stack and
** list of call-info structures.
*/
static void sweepthread (lua_State *L, lua_State *L1) {
if (L1->stack == NULL) return; /* stack not completely built yet */
sweepwholelist(L, &L1->openupval); /* sweep open upvalues */
luaE_freeCI(L1); /* free extra CallInfo slots */
/* should not change the stack during an emergency gc cycle */
if (G(L)->gckind != KGC_EMERGENCY)
luaD_shrinkstack(L1);
}
/*
** sweep at most 'count' elements from a list of GCObjects erasing dead
** objects, where a dead (not alive) object is one marked with the "old"
@ -730,10 +732,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
*p = gch(curr)->next; /* remove 'curr' from list */
freeobj(L, curr); /* erase 'curr' */
}
else {
if (gch(curr)->tt == LUA_TTHREAD)
sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */
/* update marks */
else { /* update marks */
gch(curr)->marked = cast_byte((marked & maskcolors) | white);
p = &gch(curr)->next; /* go to next element */
}
@ -886,16 +885,6 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
*/
static void localmarkclosure (LClosure *cl, int bit) {
int i;
for (i = 0; i < cl->nupvalues; i++) {
if (cl->upvals[i]) {
l_setbit(cl->upvals[i]->marked, bit);
}
}
}
/*
** Traverse a thread, local marking all its collectable objects
*/
@ -904,16 +893,8 @@ static void localmarkthread (lua_State *l) {
if (o == NULL)
return; /* stack not completely built yet */
for (; o < l->top; o++) { /* mark live elements in the stack */
if (iscollectable(o)) {
GCObject *obj = gcvalue(o);
if (obj->gch.tt == LUA_TLCL && /* is it a Lua closure? */
islocal(obj) && /* is it still local? */
!testbit(obj->gch.marked, LOCALBLACK)) { /* not visited yet? */
/* mark its upvalues as local black */
localmarkclosure(gco2lcl(obj), LOCALBLACK);
}
l_setbit(obj->gch.marked, LOCALBLACK);
}
if (iscollectable(o))
l_setbit(gcvalue(o)->gch.marked, LOCALBLACK);
}
}
@ -937,10 +918,6 @@ static void localsweep (lua_State *L, global_State *g, GCObject **p) {
*p = curr->gch.next; /* remove 'curr' from list */
curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */
g->allgc = curr;
if (curr->gch.tt == LUA_TLCL) { /* is it a Lua closure? */
/* mark its upvalues as non local */
localmarkclosure(gco2lcl(curr), LOCALBIT);
}
}
else { /* still local */
if (testbit(curr->gch.marked, LOCALBLACK)) { /* locally alive? */
@ -965,7 +942,6 @@ static void luaC_localcollection (lua_State *L) {
lua_assert(g->gcstate == GCSpause);
localmark(g);
localsweep(L, g, &g->localgc);
localsweep(L, g, &g->localupv);
}
/* }====================================================== */
@ -1036,7 +1012,6 @@ void luaC_freeallobjects (lua_State *L) {
g->gckind = KGC_NORMAL;
sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */
sweepwholelist(L, &g->localgc);
sweepwholelist(L, &g->localupv);
sweepwholelist(L, &g->allgc);
sweepwholelist(L, &g->fixedgc); /* collect fixed objects */
lua_assert(g->strt.nuse == 0);
@ -1119,7 +1094,6 @@ static lu_mem singlestep (lua_State *L) {
}
else {
sweepwholelist(L, &g->localgc);
sweepwholelist(L, &g->localupv);
g->gcstate = GCSsweep;
return GCLOCALPAUSE / 4; /* some magic for now */
}

14
lgc.h

@ -1,5 +1,5 @@
/*
** $Id: lgc.h,v 2.65 2013/08/21 20:09:51 roberto Exp roberto $
** $Id: lgc.h,v 2.66 2013/08/23 13:34:54 roberto Exp roberto $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@ -55,7 +55,7 @@
** all objects are white again.
*/
#define keepinvariant(g) (g->gcstate <= GCSatomic)
#define keepinvariant(g) ((g)->gcstate <= GCSatomic)
/*
@ -91,7 +91,7 @@
#define tofinalize(x) testbit((x)->gch.marked, FINALIZEDBIT)
#define otherwhite(g) (g->currentwhite ^ WHITEBITS)
#define otherwhite(g) ((g)->currentwhite ^ WHITEBITS)
#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow)))
#define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked)
@ -127,6 +127,10 @@
{ if (nolocal(obj2gco(o)), isblack(obj2gco(p)) && iswhite(obj2gco(o))) \
luaC_barrierback_(L,p); }
#define luaC_upvalbarrier(L,uv) \
{ if (iscollectable((uv)->v) && !upisopen(uv)) \
luaC_upvalbarrier_(L,uv); }
LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
LUAI_FUNC void luaC_freeallobjects (lua_State *L);
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,
LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v);
LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o);
LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c);
LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv);
LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt);
LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv);
LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv);
#endif

13
lobject.h

@ -1,5 +1,5 @@
/*
** $Id: lobject.h,v 2.79 2013/08/07 12:18:11 roberto Exp roberto $
** $Id: lobject.h,v 2.80 2013/08/18 16:12:18 roberto Exp roberto $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
@ -20,13 +20,12 @@
** Extra tags for non-values
*/
#define LUA_TPROTO LUA_NUMTAGS
#define LUA_TUPVAL (LUA_NUMTAGS+1)
#define LUA_TDEADKEY (LUA_NUMTAGS+2)
#define LUA_TDEADKEY (LUA_NUMTAGS+1)
/*
** number of all possible tags (including LUA_TNONE but excluding DEADKEY)
*/
#define LUA_TOTALTAGS (LUA_TUPVAL+2)
#define LUA_TOTALTAGS (LUA_TPROTO + 2)
/*
@ -392,11 +391,7 @@ typedef struct Proto {
/*
** Lua Upvalues
*/
typedef struct UpVal {
CommonHeader;
TValue *v; /* points to stack or to its own value */
TValue value; /* the value (when closed) */
} UpVal;
typedef struct UpVal UpVal;
/*

4
lstate.c

@ -1,5 +1,5 @@
/*
** $Id: lstate.c,v 2.105 2013/08/23 13:34:54 roberto Exp roberto $
** $Id: lstate.c,v 2.106 2013/08/26 12:41:10 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@ -289,7 +289,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->version = lua_version(NULL);
g->gcstate = GCSpause;
g->allgc = NULL;
g->localgc = g->localupv = NULL;
g->localgc = NULL;
g->finobj = NULL;
g->tobefnz = NULL;
g->fixedgc = NULL;

14
lstate.h

@ -1,5 +1,5 @@
/*
** $Id: lstate.h,v 2.89 2013/08/23 13:34:54 roberto Exp roberto $
** $Id: lstate.h,v 2.90 2013/08/26 12:41:10 roberto Exp roberto $
** Global State
** See Copyright Notice in lua.h
*/
@ -27,13 +27,6 @@
** List 'fixedgc' keep objects that are not to be collected (currently
** only small strings, such as reserved words).
**
** Open upvalues are not subject to independent garbage collection. They
** are collected together with their respective threads. (They are
** always gray, so they must be remarked in the atomic step. Usually
** their contents would be marked when traversing the respective
** threads, but the thread may already be dead, while the upvalue is
** still accessible through closures.)
**
** Live objects with finalizers are kept in the list g->finobj. The
** list g->tobefnz links all objects being finalized. In particular, an
** object has its FINALIZEDBIT set iff it is in one of these lists.
@ -128,7 +121,6 @@ typedef struct global_State {
lu_byte gcrunning; /* true if GC is running */
GCObject *allgc; /* list of all collectable objects */
GCObject *localgc; /* list of local objects */
GCObject *localupv; /* list of local upvalues */
GCObject *finobj; /* list of collectable objects with finalizers */
GCObject **sweepgc; /* current position of sweep in list 'allgc' */
GCObject **sweepfin; /* current position of sweep in list 'finobj' */
@ -171,7 +163,7 @@ struct lua_State {
int basehookcount;
int hookcount;
lua_Hook hook;
GCObject *openupval; /* list of open upvalues in this stack */
UpVal *openupval; /* list of open upvalues in this stack */
GCObject *gclist;
struct lua_longjmp *errorJmp; /* current error recover point */
ptrdiff_t errfunc; /* current error handling function (stack index) */
@ -192,7 +184,6 @@ union GCObject {
union Closure cl;
struct Table h;
struct Proto p;
struct UpVal uv;
struct lua_State th; /* thread */
};
@ -211,7 +202,6 @@ union GCObject {
check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl))
#define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
/* macro to convert any Lua object into a GCObject */

40
ltests.c

@ -1,5 +1,5 @@
/*
** $Id: ltests.c,v 2.148 2013/08/22 15:21:48 roberto Exp roberto $
** $Id: ltests.c,v 2.149 2013/08/26 12:41:10 roberto Exp roberto $
** Internal Module for Debugging of the Lua Implementation
** See Copyright Notice in lua.h
*/
@ -195,14 +195,6 @@ 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 */
}
if (gch(f)->tt == LUA_TPROTO && gch(t)->tt == LUA_TLCL)
return 1; /* cache from a prototype */
return 0;
@ -311,9 +303,11 @@ static void checkLclosure (global_State *g, LClosure *cl) {
int i;
if (cl->p) checkobjref(g, clgc, cl->p);
for (i=0; i<cl->nupvalues; i++) {
if (cl->upvals[i]) {
lua_assert(cl->upvals[i]->tt == LUA_TUPVAL);
checkobjref(g, clgc, cl->upvals[i]);
UpVal *uv = cl->upvals[i];
if (uv) {
if (!upisopen(uv)) /* only closed upvalues matter to invariant */
checkvalref(g, clgc, uv->v);
lua_assert(uv->refcount > 0);
}
}
}
@ -332,13 +326,10 @@ static int lua_checkpc (pCallInfo ci) {
static void checkstack (global_State *g, lua_State *L1) {
StkId o;
CallInfo *ci;
GCObject *uvo;
UpVal *uv;
lua_assert(!isdead(g, obj2gco(L1)));
for (uvo = L1->openupval; uvo != NULL; uvo = gch(uvo)->next) {
UpVal *uv = gco2uv(uvo);
lua_assert(uv->v != &uv->value); /* must be open */
lua_assert(!isblack(uvo)); /* open upvalues cannot be black */
}
for (uv = L1->openupval; uv != NULL; uv = uv->u.op.next)
lua_assert(upisopen(uv)); /* must be open */
for (ci = L1->ci; ci != NULL; ci = ci->previous) {
lua_assert(ci->top <= L1->stack_last);
lua_assert(lua_checkpc(ci));
@ -357,13 +348,6 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) {
else {
lua_assert(g->gcstate != GCSpause || iswhite(o));
switch (gch(o)->tt) {
case LUA_TUPVAL: {
UpVal *uv = gco2uv(o);
lua_assert(uv->v == &uv->value); /* must be closed */
lua_assert(!isgray(o)); /* closed upvalues are never gray */
checkvalref(g, o, uv->v);
break;
}
case LUA_TUSERDATA: {
Table *mt = gco2u(o)->metatable;
if (mt) checkobjref(g, o, mt);
@ -490,12 +474,6 @@ int lua_checkmemory (lua_State *L) {
for (o = g->localgc; o != NULL; o = gch(o)->next) {
checkobject(g, o, 1);
}
/* check 'localupv' list */
checkgray(g, g->localupv);
for (o = g->localupv; o != NULL; o = gch(o)->next) {
lua_assert(gch(o)->tt == LUA_TUPVAL);
checkobject(g, o, 1);
}
return 0;
}

4
ltm.c

@ -1,5 +1,5 @@
/*
** $Id: ltm.c,v 2.20 2013/05/06 17:19:11 roberto Exp roberto $
** $Id: ltm.c,v 2.21 2013/08/21 20:09:51 roberto Exp roberto $
** Tag methods
** See Copyright Notice in lua.h
*/
@ -28,7 +28,7 @@ LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = {
"no value",
"nil", "boolean", udatatypename, "number",
"string", "table", "function", udatatypename, "thread",
"proto", "upval" /* these last two cases are used for tests only */
"proto" /* this last case is used for tests only */
};

7
lvm.c

@ -1,5 +1,5 @@
/*
** $Id: lvm.c,v 2.177 2013/08/16 18:55:49 roberto Exp roberto $
** $Id: lvm.c,v 2.178 2013/08/19 14:18:43 roberto Exp roberto $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@ -416,7 +416,8 @@ 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 */
ncl->l.upvals[i]->refcount++;
/* new closure is white, so we do not need a barrier here */
}
if (!isblack(obj2gco(p))) /* cache will not break GC invariant? */
p->cache = ncl; /* save it on cache for reuse */
@ -591,7 +592,7 @@ void luaV_execute (lua_State *L) {
vmcase(OP_SETUPVAL,
UpVal *uv = cl->upvals[GETARG_B(i)];
setobj(L, uv->v, ra);
luaC_barrier(L, uv, ra);
luaC_upvalbarrier(L, uv);
)
vmcase(OP_SETTABLE,
Protect(luaV_settable(L, ra, RKB(i), RKC(i)));

Loading…
Cancel
Save