mirror of https://github.com/rusefi/lua.git
more and better tools (assertions & inspectors) to check incremental GC
This commit is contained in:
parent
b3ce450529
commit
2aaf7394ad
9
lfunc.c
9
lfunc.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lfunc.c,v 1.74 2003/12/09 16:56:11 roberto Exp roberto $
|
||||
** $Id: lfunc.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
|
||||
** Auxiliary functions to manipulate prototypes and closures
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -57,7 +57,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
|
|||
}
|
||||
uv = luaM_new(L, UpVal); /* not found: create a new one */
|
||||
uv->tt = LUA_TUPVAL;
|
||||
uv->marked = bitmask(FIXEDBIT); /* open upvalues cannot be collected */
|
||||
uv->marked = luaC_white(G(L));
|
||||
uv->v = level; /* current value lives in the stack */
|
||||
uv->next = *pp; /* chain it in the proper position */
|
||||
*pp = obj2gco(uv);
|
||||
|
@ -68,11 +68,16 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
|
|||
void luaF_close (lua_State *L, StkId level) {
|
||||
UpVal *uv;
|
||||
while ((uv = ngcotouv(L->openupval)) != NULL && uv->v >= level) {
|
||||
lu_byte mark = uv->marked;
|
||||
lua_assert(!isblack(obj2gco(uv)));
|
||||
setobj(L, &uv->value, uv->v);
|
||||
luaC_barrier(L, uv, uv->v);
|
||||
uv->v = &uv->value; /* now current value lives here */
|
||||
L->openupval = uv->next; /* remove from `open' list */
|
||||
luaC_link(L, obj2gco(uv), LUA_TUPVAL);
|
||||
if (G(L)->gcstate == GCSpropagate)
|
||||
uv->marked = mark; /* preserve previous mark */
|
||||
lua_assert(!isdead(G(L), obj2gco(uv)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
61
lgc.c
61
lgc.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lgc.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
|
||||
** $Id: lgc.c,v 2.2 2003/12/12 18:29:34 roberto Exp roberto $
|
||||
** Garbage Collector
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -60,6 +60,7 @@
|
|||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** computes the size of a collectible object
|
||||
*/
|
||||
|
@ -152,7 +153,7 @@ static void marktmu (global_State *g) {
|
|||
|
||||
|
||||
/* move `dead' udata that need finalization to list `tmudata' */
|
||||
size_t luaC_separateudata (lua_State *L) {
|
||||
size_t luaC_separateudata (lua_State *L, int all) {
|
||||
size_t deadmem = 0;
|
||||
GCObject **p = &G(L)->firstudata;
|
||||
GCObject *curr;
|
||||
|
@ -160,7 +161,7 @@ size_t luaC_separateudata (lua_State *L) {
|
|||
GCObject **lastcollected = &collected;
|
||||
while ((curr = *p) != NULL) {
|
||||
lua_assert(curr->gch.tt == LUA_TUSERDATA);
|
||||
if (!iswhite(curr) || isfinalized(gco2u(curr)))
|
||||
if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))
|
||||
p = &curr->gch.next; /* don't bother with them */
|
||||
else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {
|
||||
markfinalized(gco2u(curr)); /* don't need finalization */
|
||||
|
@ -182,7 +183,7 @@ size_t luaC_separateudata (lua_State *L) {
|
|||
}
|
||||
|
||||
|
||||
static void traversetable (global_State *g, Table *h) {
|
||||
static int traversetable (global_State *g, Table *h) {
|
||||
int i;
|
||||
int weakkey = 0;
|
||||
int weakvalue = 0;
|
||||
|
@ -202,7 +203,7 @@ static void traversetable (global_State *g, Table *h) {
|
|||
g->weak = obj2gco(h); /* ... so put in the appropriate list */
|
||||
}
|
||||
}
|
||||
if (weakkey && weakvalue) return;
|
||||
if (weakkey && weakvalue) return 1;
|
||||
if (!weakvalue) {
|
||||
i = h->sizearray;
|
||||
while (i--)
|
||||
|
@ -217,6 +218,7 @@ static void traversetable (global_State *g, Table *h) {
|
|||
condmarkobject(g, gval(n), !weakvalue);
|
||||
}
|
||||
}
|
||||
return weakkey || weakvalue;
|
||||
}
|
||||
|
||||
|
||||
|
@ -227,10 +229,8 @@ static void traversetable (global_State *g, Table *h) {
|
|||
static void traverseproto (global_State *g, Proto *f) {
|
||||
int i;
|
||||
if (f->source) stringmark(f->source);
|
||||
for (i=0; i<f->sizek; i++) { /* mark literal strings */
|
||||
if (ttisstring(f->k+i))
|
||||
stringmark(rawtsvalue(f->k+i));
|
||||
}
|
||||
for (i=0; i<f->sizek; i++) /* mark literals */
|
||||
markvalue(g, &f->k[i]);
|
||||
for (i=0; i<f->sizeupvalues; i++) { /* mark upvalue names */
|
||||
if (f->upvalues[i])
|
||||
stringmark(f->upvalues[i]);
|
||||
|
@ -258,9 +258,8 @@ static void traverseclosure (global_State *g, Closure *cl) {
|
|||
lua_assert(cl->l.nupvalues == cl->l.p->nups);
|
||||
markobject(g, hvalue(&cl->l.g));
|
||||
markobject(g, cl->l.p);
|
||||
for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
|
||||
for (i=0; i<cl->l.nupvalues; i++) /* mark its upvalues */
|
||||
markobject(g, cl->l.upvals[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,7 +306,8 @@ static l_mem propagatemarks (global_State *g, l_mem lim) {
|
|||
case LUA_TTABLE: {
|
||||
Table *h = gco2h(o);
|
||||
g->gray = h->gclist;
|
||||
traversetable(g, h);
|
||||
if (traversetable(g, h)) /* table is weak? */
|
||||
black2gray(o); /* keep it gray */
|
||||
break;
|
||||
}
|
||||
case LUA_TFUNCTION: {
|
||||
|
@ -339,7 +339,8 @@ static l_mem propagatemarks (global_State *g, l_mem lim) {
|
|||
g->grayagain = o;
|
||||
black2gray(o);
|
||||
}
|
||||
markvalue(g, &uv->value);
|
||||
else
|
||||
markvalue(g, &uv->value);
|
||||
break;
|
||||
}
|
||||
default: lua_assert(0);
|
||||
|
@ -428,6 +429,13 @@ static void freeobj (lua_State *L, GCObject *o) {
|
|||
}
|
||||
|
||||
|
||||
static void sweepupvalues (global_State *g, lua_State *L1) {
|
||||
GCObject *curr;
|
||||
for (curr = L1->openupval; curr != NULL; curr = curr->gch.next)
|
||||
makewhite(g, curr);
|
||||
}
|
||||
|
||||
|
||||
static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
|
||||
l_mem *plim) {
|
||||
GCObject *curr;
|
||||
|
@ -439,10 +447,14 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all,
|
|||
lim -= objsize(curr);
|
||||
if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) {
|
||||
makewhite(g, curr);
|
||||
if (curr->gch.tt == LUA_TTHREAD)
|
||||
sweepupvalues(g, gco2th(curr));
|
||||
p = &curr->gch.next;
|
||||
}
|
||||
else {
|
||||
*p = curr->gch.next;
|
||||
if (curr == g->rootgc) /* is the first element of the list? */
|
||||
g->rootgc = curr->gch.next; /* adjust first */
|
||||
freeobj(L, curr);
|
||||
}
|
||||
if (lim <= 0) break;
|
||||
|
@ -537,7 +549,8 @@ void luaC_sweepall (lua_State *L) {
|
|||
/* mark root set */
|
||||
static void markroot (lua_State *L) {
|
||||
global_State *g = G(L);
|
||||
lua_assert(g->gray == NULL && g->grayagain == NULL);
|
||||
lua_assert(g->gray == NULL);
|
||||
g->grayagain = NULL;
|
||||
g->weak = NULL;
|
||||
makewhite(g, obj2gco(g->mainthread));
|
||||
markobject(g, g->mainthread);
|
||||
|
@ -550,28 +563,30 @@ static void markroot (lua_State *L) {
|
|||
static void atomic (lua_State *L) {
|
||||
global_State *g = G(L);
|
||||
lua_assert(g->gray == NULL);
|
||||
/* remark weak tables */
|
||||
g->gray = g->weak;
|
||||
g->weak = NULL;
|
||||
propagatemarks(g, MAXLMEM);
|
||||
/* remark gray again */
|
||||
g->gray = g->grayagain;
|
||||
g->grayagain = NULL;
|
||||
propagatemarks(g, MAXLMEM);
|
||||
luaC_separateudata(L); /* separate userdata to be preserved */
|
||||
luaC_separateudata(L, 0); /* separate userdata to be preserved */
|
||||
marktmu(g); /* mark `preserved' userdata */
|
||||
propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */
|
||||
cleartable(g->weak); /* remove collected objects from weak tables */
|
||||
/* flip current white */
|
||||
g->currentwhite = otherwhite(g);
|
||||
/* first element of root list will be used as temporary head for sweep
|
||||
phase, so it won't be swept */
|
||||
makewhite(g, g->rootgc);
|
||||
g->sweepgc = &g->rootgc->gch.next;
|
||||
g->sweepgc = &g->rootgc;
|
||||
g->sweepstrgc = 0;
|
||||
g->gcstate = GCSsweepstring;
|
||||
g->grayagain = NULL;
|
||||
}
|
||||
|
||||
|
||||
void luaC_step (lua_State *L) {
|
||||
global_State *g = G(L);
|
||||
l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * 2;
|
||||
luaC_checkall(L);
|
||||
switch (g->gcstate) {
|
||||
case GCSpropagate: {
|
||||
if (g->gray)
|
||||
|
@ -593,8 +608,9 @@ void luaC_step (lua_State *L) {
|
|||
case GCSsweep: {
|
||||
g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim);
|
||||
if (*g->sweepgc == NULL) { /* nothing more to sweep? */
|
||||
g->gcstate = GCSfinalize; /* end sweep phase */
|
||||
checkSizes(L);
|
||||
sweepupvalues(g, g->mainthread);
|
||||
g->gcstate = GCSfinalize; /* end sweep phase */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -610,13 +626,14 @@ void luaC_step (lua_State *L) {
|
|||
default: lua_assert(0);
|
||||
}
|
||||
g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/2;
|
||||
luaC_checkall(L);
|
||||
}
|
||||
|
||||
|
||||
void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
|
||||
global_State *g = G(L);
|
||||
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
|
||||
if (g->gcstate >= GCSsweepstring) /* sweeping phases? */
|
||||
if (g->gcstate != GCSpropagate) /* sweeping phases? */
|
||||
black2gray(o); /* just mark as gray to avoid other barriers */
|
||||
else /* breaking invariant! */
|
||||
reallymarkobject(g, v); /* restore it */
|
||||
|
|
4
lgc.h
4
lgc.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lgc.h,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
|
||||
** $Id: lgc.h,v 2.2 2003/12/12 18:29:34 roberto Exp roberto $
|
||||
** Garbage Collector
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -81,7 +81,7 @@
|
|||
{ if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \
|
||||
luaC_barrierf(L,obj2gco(p),obj2gco(o)); }
|
||||
|
||||
size_t luaC_separateudata (lua_State *L);
|
||||
size_t luaC_separateudata (lua_State *L, int all);
|
||||
void luaC_callGCTM (lua_State *L);
|
||||
void luaC_sweepall (lua_State *L);
|
||||
void luaC_step (lua_State *L);
|
||||
|
|
20
lobject.h
20
lobject.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lobject.h,v 1.162 2003/11/18 14:55:11 roberto Exp roberto $
|
||||
** $Id: lobject.h,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
|
||||
** Type definitions for Lua objects
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -99,9 +99,9 @@ typedef struct lua_TValue {
|
|||
#define checkconsistency(obj) \
|
||||
lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))
|
||||
|
||||
#define checkliveness(L,obj) \
|
||||
#define checkliveness(g,obj) \
|
||||
lua_assert(!iscollectable(obj) || \
|
||||
((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(G(L), (obj)->value.gc)))
|
||||
((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))
|
||||
|
||||
|
||||
/* Macros to set values */
|
||||
|
@ -122,32 +122,32 @@ typedef struct lua_TValue {
|
|||
#define setsvalue(L,obj,x) \
|
||||
{ TValue *i_o=(obj); \
|
||||
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \
|
||||
checkliveness(L,i_o); }
|
||||
checkliveness(G(L),i_o); }
|
||||
|
||||
#define setuvalue(L,obj,x) \
|
||||
{ TValue *i_o=(obj); \
|
||||
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \
|
||||
checkliveness(L,i_o); }
|
||||
checkliveness(G(L),i_o); }
|
||||
|
||||
#define setthvalue(L,obj,x) \
|
||||
{ TValue *i_o=(obj); \
|
||||
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \
|
||||
checkliveness(L,i_o); }
|
||||
checkliveness(G(L),i_o); }
|
||||
|
||||
#define setclvalue(L,obj,x) \
|
||||
{ TValue *i_o=(obj); \
|
||||
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \
|
||||
checkliveness(L,i_o); }
|
||||
checkliveness(G(L),i_o); }
|
||||
|
||||
#define sethvalue(L,obj,x) \
|
||||
{ TValue *i_o=(obj); \
|
||||
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \
|
||||
checkliveness(L,i_o); }
|
||||
checkliveness(G(L),i_o); }
|
||||
|
||||
#define setptvalue(L,obj,x) \
|
||||
{ TValue *i_o=(obj); \
|
||||
i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
|
||||
checkliveness(L,i_o); }
|
||||
checkliveness(G(L),i_o); }
|
||||
|
||||
|
||||
|
||||
|
@ -155,7 +155,7 @@ typedef struct lua_TValue {
|
|||
#define setobj(L,obj1,obj2) \
|
||||
{ const TValue *o2=(obj2); TValue *o1=(obj1); \
|
||||
o1->tt=o2->tt; o1->value = o2->value; \
|
||||
checkliveness(L,o1); }
|
||||
checkliveness(G(L),o1); }
|
||||
|
||||
|
||||
/*
|
||||
|
|
4
lstate.c
4
lstate.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: lstate.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
|
||||
** $Id: lstate.c,v 2.2 2003/12/12 18:29:34 roberto Exp roberto $
|
||||
** Global State
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -200,7 +200,7 @@ LUA_API void lua_close (lua_State *L) {
|
|||
lua_lock(L);
|
||||
L = G(L)->mainthread; /* only the main thread can be closed */
|
||||
luaF_close(L, L->stack); /* close all upvalues for this thread */
|
||||
luaC_separateudata(L); /* separate udata that have GC metamethods */
|
||||
luaC_separateudata(L, 1); /* separate udata that have GC metamethods */
|
||||
L->errfunc = 0; /* no error function during GC metamethods */
|
||||
do { /* repeat until no more errors */
|
||||
L->ci = L->base_ci;
|
||||
|
|
184
ltests.c
184
ltests.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: ltests.c,v 1.169 2003/11/19 12:21:57 roberto Exp roberto $
|
||||
** $Id: ltests.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
|
||||
** Internal Module for Debugging of the Lua Implementation
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -141,6 +141,188 @@ void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) {
|
|||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Functions to check memory consistency
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
|
||||
if (isdead(g,t)) return 0;
|
||||
if (g->gcstate == GCSpropagate)
|
||||
return !isblack(f) || !iswhite(t);
|
||||
else if (g->gcstate == GCSfinalize)
|
||||
return iswhite(f);
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void printobj (global_State *g, GCObject *o) {
|
||||
int i = 0;
|
||||
GCObject *p;
|
||||
for (p = g->rootgc; p != o && p != NULL; p = p->gch.next) i++;
|
||||
if (p == NULL) i = -1;
|
||||
printf("%d:%s(%p)-%c",
|
||||
i, luaT_typenames[o->gch.tt], (void *)o,
|
||||
isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g');
|
||||
}
|
||||
|
||||
|
||||
static int testobjref (global_State *g, GCObject *f, GCObject *t) {
|
||||
int r = testobjref1(g,f,t);
|
||||
if (!r) {
|
||||
printf("%d - ", g->gcstate);
|
||||
printobj(g, f);
|
||||
printf("\t-> ");
|
||||
printobj(g, t);
|
||||
printf("\n");
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t)))
|
||||
|
||||
#define checkvalref(g,f,t) lua_assert(!iscollectable(t) || \
|
||||
((ttype(t) == (t)->value.gc->gch.tt) && testobjref(g,f,gcvalue(t))))
|
||||
|
||||
|
||||
|
||||
static void checktable (global_State *g, Table *h) {
|
||||
int i;
|
||||
int weakkey = 0;
|
||||
int weakvalue = 0;
|
||||
const TValue *mode;
|
||||
GCObject *hgc = obj2gco(h);
|
||||
if (h->metatable)
|
||||
checkobjref(g, hgc, h->metatable);
|
||||
lua_assert(h->lsizenode || h->node == g->dummynode);
|
||||
mode = gfasttm(g, h->metatable, TM_MODE);
|
||||
if (mode && ttisstring(mode)) { /* is there a weak mode? */
|
||||
weakkey = (strchr(svalue(mode), 'k') != NULL);
|
||||
weakvalue = (strchr(svalue(mode), 'v') != NULL);
|
||||
}
|
||||
i = h->sizearray;
|
||||
while (i--)
|
||||
checkvalref(g, hgc, &h->array[i]);
|
||||
i = sizenode(h);
|
||||
while (i--) {
|
||||
Node *n = gnode(h, i);
|
||||
if (!ttisnil(gval(n))) {
|
||||
lua_assert(!ttisnil(gkey(n)));
|
||||
checkvalref(g, hgc, gkey(n));
|
||||
checkvalref(g, hgc, gval(n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** All marks are conditional because a GC may happen while the
|
||||
** prototype is still being created
|
||||
*/
|
||||
static void checkproto (global_State *g, Proto *f) {
|
||||
int i;
|
||||
GCObject *fgc = obj2gco(f);
|
||||
if (f->source) checkobjref(g, fgc, f->source);
|
||||
for (i=0; i<f->sizek; i++) {
|
||||
if (ttisstring(f->k+i))
|
||||
checkobjref(g, fgc, rawtsvalue(f->k+i));
|
||||
}
|
||||
for (i=0; i<f->sizeupvalues; i++) {
|
||||
if (f->upvalues[i])
|
||||
checkobjref(g, fgc, f->upvalues[i]);
|
||||
}
|
||||
for (i=0; i<f->sizep; i++) {
|
||||
if (f->p[i])
|
||||
checkobjref(g, fgc, f->p[i]);
|
||||
}
|
||||
for (i=0; i<f->sizelocvars; i++) {
|
||||
if (f->locvars[i].varname)
|
||||
checkobjref(g, fgc, f->locvars[i].varname);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void checkclosure (global_State *g, Closure *cl) {
|
||||
GCObject *clgc = obj2gco(cl);
|
||||
if (cl->c.isC) {
|
||||
int i;
|
||||
for (i=0; i<cl->c.nupvalues; i++)
|
||||
checkvalref(g, clgc, &cl->c.upvalue[i]);
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
lua_assert(cl->l.nupvalues == cl->l.p->nups);
|
||||
checkobjref(g, clgc, hvalue(&cl->l.g));
|
||||
checkobjref(g, clgc, cl->l.p);
|
||||
for (i=0; i<cl->l.nupvalues; i++) {
|
||||
lua_assert(cl->l.upvals[i]->tt == LUA_TUPVAL);
|
||||
checkobjref(g, clgc, cl->l.upvals[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void checkstack (global_State *g, lua_State *L1) {
|
||||
StkId o;
|
||||
CallInfo *ci;
|
||||
lua_assert(!isdead(g, obj2gco(L1)));
|
||||
checkliveness(g, gt(L1));
|
||||
for (ci = L1->base_ci; ci <= L1->ci; ci++)
|
||||
lua_assert(ci->top <= L1->stack_last);
|
||||
for (o = L1->stack; o < L1->top; o++)
|
||||
checkliveness(g, o);
|
||||
}
|
||||
|
||||
|
||||
void luaC_checkall (lua_State *L) {
|
||||
global_State *g = G(L);
|
||||
GCObject *o;
|
||||
checkstack(g, g->mainthread);
|
||||
for (o = g->rootgc; o; o = o->gch.next) {
|
||||
if (isdead(g, o))
|
||||
lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
|
||||
else {
|
||||
switch (o->gch.tt) {
|
||||
case LUA_TUPVAL: {
|
||||
UpVal *uv = gco2uv(o);
|
||||
lua_assert(uv->v == &uv->value); /* must be closed */
|
||||
checkvalref(g, o, uv->v);
|
||||
break;
|
||||
}
|
||||
case LUA_TUSERDATA: {
|
||||
Table *mt = gco2u(o)->metatable;
|
||||
if (mt) checkobjref(g, o, mt);
|
||||
break;
|
||||
}
|
||||
case LUA_TTABLE: {
|
||||
checktable(g, gco2h(o));
|
||||
break;
|
||||
}
|
||||
case LUA_TTHREAD: {
|
||||
checkstack(g, gco2th(o));
|
||||
break;
|
||||
}
|
||||
case LUA_TFUNCTION: {
|
||||
checkclosure(g, gco2cl(o));
|
||||
break;
|
||||
}
|
||||
case LUA_TPROTO: {
|
||||
checkproto(g, gco2p(o));
|
||||
break;
|
||||
}
|
||||
default: lua_assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Disassembler
|
||||
|
|
4
ltests.h
4
ltests.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: ltests.h,v 1.21 2003/10/02 20:31:17 roberto Exp roberto $
|
||||
** $Id: ltests.h,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
|
||||
** Internal Header for Debugging of the Lua Implementation
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -42,6 +42,8 @@ void *debug_realloc (void *ud, void *block, size_t osize, size_t nsize);
|
|||
#endif
|
||||
|
||||
|
||||
void luaC_checkall (lua_State *L);
|
||||
|
||||
|
||||
/* test for lock/unlock */
|
||||
extern int islocked;
|
||||
|
|
5
ltm.c
5
ltm.c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
** $Id: ltm.c,v 1.107 2003/12/01 18:22:56 roberto Exp roberto $
|
||||
** $Id: ltm.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
|
||||
** Tag methods
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
@ -21,7 +21,8 @@
|
|||
|
||||
const char *const luaT_typenames[] = {
|
||||
"nil", "boolean", "userdata", "number",
|
||||
"string", "table", "function", "userdata", "thread"
|
||||
"string", "table", "function", "userdata", "thread",
|
||||
"proto", "upval"
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue