new tests to check memory consistency (for incremental GC)

This commit is contained in:
Roberto Ierusalimschy 2004-03-15 18:04:54 -03:00
parent a4e1230f95
commit 48a8d78102
2 changed files with 139 additions and 74 deletions

128
ltests.c
View File

@ -1,5 +1,5 @@
/*
** $Id: ltests.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
** $Id: ltests.c,v 2.2 2004/02/16 19:09:52 roberto Exp roberto $
** Internal Module for Debugging of the Lua Implementation
** See Copyright Notice in lua.h
*/
@ -36,12 +36,15 @@
#ifdef LUA_DEBUG
int Trick = 0;
static lua_State *lua_state = NULL;
int islocked = 0;
#define func_at(L,k) (L->ci->base+(k) - 1)
#define obj_at(L,k) (L->ci->base+(k) - 1)
static void setnameval (lua_State *L, const char *name, int val) {
@ -159,25 +162,24 @@ static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
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');
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(%02X)", i, luaT_typenames[o->gch.tt], (void *)o,
isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', o->gch.marked);
}
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");
}
if (!r) {
printf("%d(%02X) - ", g->gcstate, g->currentwhite);
printobj(g, f);
printf("\t-> ");
printobj(g, t);
printf("\n");
}
return r;
}
@ -258,10 +260,12 @@ static void checkclosure (global_State *g, Closure *cl) {
checkobjref(g, clgc, hvalue(&cl->l.g));
checkobjref(g, clgc, cl->l.p);
for (i=0; i<cl->l.nupvalues; i++) {
if (cl->l.upvals[i]) {
lua_assert(cl->l.upvals[i]->tt == LUA_TUPVAL);
checkobjref(g, clgc, cl->l.upvals[i]);
}
}
}
}
@ -270,21 +274,25 @@ static void checkstack (global_State *g, lua_State *L1) {
CallInfo *ci;
lua_assert(!isdead(g, obj2gco(L1)));
checkliveness(g, gt(L1));
if (L1->base_ci) {
for (ci = L1->base_ci; ci <= L1->ci; ci++)
lua_assert(ci->top <= L1->stack_last);
}
else lua_assert(L1->size_ci == 0);
if (L1->stack) {
for (o = L1->stack; o < L1->top; o++)
checkliveness(g, o);
}
else lua_assert(L1->stacksize == 0);
}
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) {
static void checkobject (global_State *g, GCObject *o) {
if (isdead(g, o))
lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
else {
if (g->gcstate == GCSfinalize)
lua_assert(iswhite(o));
switch (o->gch.tt) {
case LUA_TUPVAL: {
UpVal *uv = gco2uv(o);
@ -316,7 +324,24 @@ void luaC_checkall (lua_State *L) {
default: lua_assert(0);
}
}
}
int lua_checkmemory (lua_State *L) {
global_State *g = G(L);
GCObject *o;
checkstack(g, g->mainthread);
for (o = g->rootgc; o->gch.tt != LUA_TUSERDATA; o = o->gch.next)
checkobject(g, o);
lua_assert(o == g->firstudata);
for (; o->gch.tt != LUA_TTHREAD; o = o->gch.next)
checkobject(g, o);
lua_assert(o == obj2gco(g->mainthread));
for (; o; o = o->gch.next) {
lua_assert(o->gch.tt == LUA_TTHREAD);
checkobject(g, o);
}
return 0;
}
/* }====================================================== */
@ -369,7 +394,7 @@ static int listcode (lua_State *L) {
Proto *p;
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
1, "Lua function expected");
p = clvalue(func_at(L, 1))->l.p;
p = clvalue(obj_at(L, 1))->l.p;
lua_newtable(L);
setnameval(L, "maxstack", p->maxstacksize);
setnameval(L, "numparams", p->numparams);
@ -388,7 +413,7 @@ static int listk (lua_State *L) {
int i;
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
1, "Lua function expected");
p = clvalue(func_at(L, 1))->l.p;
p = clvalue(obj_at(L, 1))->l.p;
lua_createtable(L, p->sizek, 0);
for (i=0; i<p->sizek; i++) {
luaA_pushobject(L, p->k+i);
@ -405,7 +430,7 @@ static int listlocals (lua_State *L) {
const char *name;
luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
1, "Lua function expected");
p = clvalue(func_at(L, 1))->l.p;
p = clvalue(obj_at(L, 1))->l.p;
while ((name = luaF_getlocalname(p, ++i, pc)) != NULL)
lua_pushstring(L, name);
return i-1;
@ -428,12 +453,6 @@ static int get_limits (lua_State *L) {
}
static int setgcthreshold (lua_State *L) {
lua_setgcthreshold(L, luaL_checkint(L, 1));
return 0;
}
static int mem_query (lua_State *L) {
if (lua_isnone(L, 1)) {
lua_pushinteger(L, memcontrol.total);
@ -448,16 +467,52 @@ static int mem_query (lua_State *L) {
}
static int settrick (lua_State *L) {
Trick = lua_tointeger(L, 1);
return 0;
}
/*static int set_gcstate (lua_State *L) {
static const char *const state[] = {"propagate", "sweep", "finalize"};
return 0;
}*/
static int get_gccolor (lua_State *L) {
TValue *o;
luaL_checkany(L, 1);
o = obj_at(L, 1);
if (!iscollectable(o))
lua_pushstring(L, "no collectable");
else
lua_pushstring(L, iswhite(gcvalue(o)) ? "white" :
isblack(gcvalue(o)) ? "black" : "grey");
return 1;
}
static int gcstate (lua_State *L) {
switch(G(L)->gcstate) {
case GCSpropagate: lua_pushstring(L, "propagate"); break;
case GCSsweepstring: lua_pushstring(L, "sweep strings"); break;
case GCSsweep: lua_pushstring(L, "sweep"); break;
case GCSfinalize: lua_pushstring(L, "finalize"); break;
}
return 1;
}
static int hash_query (lua_State *L) {
if (lua_isnone(L, 2)) {
luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected");
lua_pushinteger(L, tsvalue(func_at(L, 1))->hash);
lua_pushinteger(L, tsvalue(obj_at(L, 1))->hash);
}
else {
TValue *o = func_at(L, 1);
TValue *o = obj_at(L, 1);
Table *t;
luaL_checktype(L, 2, LUA_TTABLE);
t = hvalue(func_at(L, 2));
t = hvalue(obj_at(L, 2));
lua_pushinteger(L, luaH_mainposition(t, o) - t->node);
}
return 1;
@ -479,7 +534,7 @@ static int table_query (lua_State *L) {
const Table *t;
int i = luaL_optint(L, 2, -1);
luaL_checktype(L, 1, LUA_TTABLE);
t = hvalue(func_at(L, 1));
t = hvalue(obj_at(L, 1));
if (i == -1) {
lua_pushinteger(L, t->sizearray);
lua_pushinteger(L, sizenode(t));
@ -979,6 +1034,10 @@ static const struct luaL_reg tests_funcs[] = {
{"querytab", table_query},
{"doit", test_do},
{"testC", testC},
{"checkmemory", lua_checkmemory},
{"gccolor", get_gccolor},
{"gcstate", gcstate},
{"trick", settrick},
{"ref", tref},
{"getref", getref},
{"unref", unref},
@ -995,7 +1054,6 @@ static const struct luaL_reg tests_funcs[] = {
{"doremote", doremote},
{"log2", log2_aux},
{"int2fb", int2fb_aux},
{"setgcthreshold", setgcthreshold},
{"totalmem", mem_query},
{"resume", coresume},
{"setyhook", setyhook},

View File

@ -1,5 +1,5 @@
/*
** $Id: ltests.h,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
** $Id: ltests.h,v 2.2 2004/02/16 19:09:52 roberto Exp roberto $
** Internal Header for Debugging of the Lua Implementation
** See Copyright Notice in lua.h
*/
@ -35,6 +35,13 @@ typedef struct Memcontrol {
extern Memcontrol memcontrol;
/*
** generic variable for debug tricks
*/
extern int Trick;
void *debug_realloc (void *ud, void *block, size_t osize, size_t nsize);
#ifdef lua_c
@ -42,7 +49,7 @@ void *debug_realloc (void *ud, void *block, size_t osize, size_t nsize);
#endif
void luaC_checkall (lua_State *L);
int lua_checkmemory (lua_State *L);
/* test for lock/unlock */