diff options
Diffstat (limited to 'ltests.c')
-rw-r--r-- | ltests.c | 202 |
1 files changed, 130 insertions, 72 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.2 2004/02/16 19:09:52 roberto Exp roberto $ |
3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -36,12 +36,15 @@ | |||
36 | #ifdef LUA_DEBUG | 36 | #ifdef LUA_DEBUG |
37 | 37 | ||
38 | 38 | ||
39 | int Trick = 0; | ||
40 | |||
41 | |||
39 | static lua_State *lua_state = NULL; | 42 | static lua_State *lua_state = NULL; |
40 | 43 | ||
41 | int islocked = 0; | 44 | int islocked = 0; |
42 | 45 | ||
43 | 46 | ||
44 | #define func_at(L,k) (L->ci->base+(k) - 1) | 47 | #define obj_at(L,k) (L->ci->base+(k) - 1) |
45 | 48 | ||
46 | 49 | ||
47 | static void setnameval (lua_State *L, const char *name, int val) { | 50 | 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) { | |||
159 | 162 | ||
160 | 163 | ||
161 | static void printobj (global_State *g, GCObject *o) { | 164 | static void printobj (global_State *g, GCObject *o) { |
162 | int i = 0; | 165 | int i = 0; |
163 | GCObject *p; | 166 | GCObject *p; |
164 | for (p = g->rootgc; p != o && p != NULL; p = p->gch.next) i++; | 167 | for (p = g->rootgc; p != o && p != NULL; p = p->gch.next) i++; |
165 | if (p == NULL) i = -1; | 168 | if (p == NULL) i = -1; |
166 | printf("%d:%s(%p)-%c", | 169 | printf("%d:%s(%p)-%c(%02X)", i, luaT_typenames[o->gch.tt], (void *)o, |
167 | i, luaT_typenames[o->gch.tt], (void *)o, | 170 | isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', o->gch.marked); |
168 | isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g'); | ||
169 | } | 171 | } |
170 | 172 | ||
171 | 173 | ||
172 | static int testobjref (global_State *g, GCObject *f, GCObject *t) { | 174 | static int testobjref (global_State *g, GCObject *f, GCObject *t) { |
173 | int r = testobjref1(g,f,t); | 175 | int r = testobjref1(g,f,t); |
174 | if (!r) { | 176 | if (!r) { |
175 | printf("%d - ", g->gcstate); | 177 | printf("%d(%02X) - ", g->gcstate, g->currentwhite); |
176 | printobj(g, f); | 178 | printobj(g, f); |
177 | printf("\t-> "); | 179 | printf("\t-> "); |
178 | printobj(g, t); | 180 | printobj(g, t); |
179 | printf("\n"); | 181 | printf("\n"); |
180 | } | 182 | } |
181 | return r; | 183 | return r; |
182 | } | 184 | } |
183 | 185 | ||
@@ -258,8 +260,10 @@ static void checkclosure (global_State *g, Closure *cl) { | |||
258 | checkobjref(g, clgc, hvalue(&cl->l.g)); | 260 | checkobjref(g, clgc, hvalue(&cl->l.g)); |
259 | checkobjref(g, clgc, cl->l.p); | 261 | checkobjref(g, clgc, cl->l.p); |
260 | for (i=0; i<cl->l.nupvalues; i++) { | 262 | for (i=0; i<cl->l.nupvalues; i++) { |
261 | lua_assert(cl->l.upvals[i]->tt == LUA_TUPVAL); | 263 | if (cl->l.upvals[i]) { |
262 | checkobjref(g, clgc, cl->l.upvals[i]); | 264 | lua_assert(cl->l.upvals[i]->tt == LUA_TUPVAL); |
265 | checkobjref(g, clgc, cl->l.upvals[i]); | ||
266 | } | ||
263 | } | 267 | } |
264 | } | 268 | } |
265 | } | 269 | } |
@@ -270,53 +274,74 @@ static void checkstack (global_State *g, lua_State *L1) { | |||
270 | CallInfo *ci; | 274 | CallInfo *ci; |
271 | lua_assert(!isdead(g, obj2gco(L1))); | 275 | lua_assert(!isdead(g, obj2gco(L1))); |
272 | checkliveness(g, gt(L1)); | 276 | checkliveness(g, gt(L1)); |
273 | for (ci = L1->base_ci; ci <= L1->ci; ci++) | 277 | if (L1->base_ci) { |
274 | lua_assert(ci->top <= L1->stack_last); | 278 | for (ci = L1->base_ci; ci <= L1->ci; ci++) |
275 | for (o = L1->stack; o < L1->top; o++) | 279 | lua_assert(ci->top <= L1->stack_last); |
276 | checkliveness(g, o); | 280 | } |
281 | else lua_assert(L1->size_ci == 0); | ||
282 | if (L1->stack) { | ||
283 | for (o = L1->stack; o < L1->top; o++) | ||
284 | checkliveness(g, o); | ||
285 | } | ||
286 | else lua_assert(L1->stacksize == 0); | ||
277 | } | 287 | } |
278 | 288 | ||
279 | 289 | ||
280 | void luaC_checkall (lua_State *L) { | 290 | static void checkobject (global_State *g, GCObject *o) { |
291 | if (isdead(g, o)) | ||
292 | lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); | ||
293 | else { | ||
294 | if (g->gcstate == GCSfinalize) | ||
295 | lua_assert(iswhite(o)); | ||
296 | switch (o->gch.tt) { | ||
297 | case LUA_TUPVAL: { | ||
298 | UpVal *uv = gco2uv(o); | ||
299 | lua_assert(uv->v == &uv->value); /* must be closed */ | ||
300 | checkvalref(g, o, uv->v); | ||
301 | break; | ||
302 | } | ||
303 | case LUA_TUSERDATA: { | ||
304 | Table *mt = gco2u(o)->metatable; | ||
305 | if (mt) checkobjref(g, o, mt); | ||
306 | break; | ||
307 | } | ||
308 | case LUA_TTABLE: { | ||
309 | checktable(g, gco2h(o)); | ||
310 | break; | ||
311 | } | ||
312 | case LUA_TTHREAD: { | ||
313 | checkstack(g, gco2th(o)); | ||
314 | break; | ||
315 | } | ||
316 | case LUA_TFUNCTION: { | ||
317 | checkclosure(g, gco2cl(o)); | ||
318 | break; | ||
319 | } | ||
320 | case LUA_TPROTO: { | ||
321 | checkproto(g, gco2p(o)); | ||
322 | break; | ||
323 | } | ||
324 | default: lua_assert(0); | ||
325 | } | ||
326 | } | ||
327 | } | ||
328 | |||
329 | |||
330 | int lua_checkmemory (lua_State *L) { | ||
281 | global_State *g = G(L); | 331 | global_State *g = G(L); |
282 | GCObject *o; | 332 | GCObject *o; |
283 | checkstack(g, g->mainthread); | 333 | checkstack(g, g->mainthread); |
284 | for (o = g->rootgc; o; o = o->gch.next) { | 334 | for (o = g->rootgc; o->gch.tt != LUA_TUSERDATA; o = o->gch.next) |
285 | if (isdead(g, o)) | 335 | checkobject(g, o); |
286 | lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); | 336 | lua_assert(o == g->firstudata); |
287 | else { | 337 | for (; o->gch.tt != LUA_TTHREAD; o = o->gch.next) |
288 | switch (o->gch.tt) { | 338 | checkobject(g, o); |
289 | case LUA_TUPVAL: { | 339 | lua_assert(o == obj2gco(g->mainthread)); |
290 | UpVal *uv = gco2uv(o); | 340 | for (; o; o = o->gch.next) { |
291 | lua_assert(uv->v == &uv->value); /* must be closed */ | 341 | lua_assert(o->gch.tt == LUA_TTHREAD); |
292 | checkvalref(g, o, uv->v); | 342 | checkobject(g, o); |
293 | break; | ||
294 | } | ||
295 | case LUA_TUSERDATA: { | ||
296 | Table *mt = gco2u(o)->metatable; | ||
297 | if (mt) checkobjref(g, o, mt); | ||
298 | break; | ||
299 | } | ||
300 | case LUA_TTABLE: { | ||
301 | checktable(g, gco2h(o)); | ||
302 | break; | ||
303 | } | ||
304 | case LUA_TTHREAD: { | ||
305 | checkstack(g, gco2th(o)); | ||
306 | break; | ||
307 | } | ||
308 | case LUA_TFUNCTION: { | ||
309 | checkclosure(g, gco2cl(o)); | ||
310 | break; | ||
311 | } | ||
312 | case LUA_TPROTO: { | ||
313 | checkproto(g, gco2p(o)); | ||
314 | break; | ||
315 | } | ||
316 | default: lua_assert(0); | ||
317 | } | ||
318 | } | ||
319 | } | 343 | } |
344 | return 0; | ||
320 | } | 345 | } |
321 | 346 | ||
322 | /* }====================================================== */ | 347 | /* }====================================================== */ |
@@ -369,7 +394,7 @@ static int listcode (lua_State *L) { | |||
369 | Proto *p; | 394 | Proto *p; |
370 | luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), | 395 | luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), |
371 | 1, "Lua function expected"); | 396 | 1, "Lua function expected"); |
372 | p = clvalue(func_at(L, 1))->l.p; | 397 | p = clvalue(obj_at(L, 1))->l.p; |
373 | lua_newtable(L); | 398 | lua_newtable(L); |
374 | setnameval(L, "maxstack", p->maxstacksize); | 399 | setnameval(L, "maxstack", p->maxstacksize); |
375 | setnameval(L, "numparams", p->numparams); | 400 | setnameval(L, "numparams", p->numparams); |
@@ -388,7 +413,7 @@ static int listk (lua_State *L) { | |||
388 | int i; | 413 | int i; |
389 | luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), | 414 | luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), |
390 | 1, "Lua function expected"); | 415 | 1, "Lua function expected"); |
391 | p = clvalue(func_at(L, 1))->l.p; | 416 | p = clvalue(obj_at(L, 1))->l.p; |
392 | lua_createtable(L, p->sizek, 0); | 417 | lua_createtable(L, p->sizek, 0); |
393 | for (i=0; i<p->sizek; i++) { | 418 | for (i=0; i<p->sizek; i++) { |
394 | luaA_pushobject(L, p->k+i); | 419 | luaA_pushobject(L, p->k+i); |
@@ -405,7 +430,7 @@ static int listlocals (lua_State *L) { | |||
405 | const char *name; | 430 | const char *name; |
406 | luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), | 431 | luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), |
407 | 1, "Lua function expected"); | 432 | 1, "Lua function expected"); |
408 | p = clvalue(func_at(L, 1))->l.p; | 433 | p = clvalue(obj_at(L, 1))->l.p; |
409 | while ((name = luaF_getlocalname(p, ++i, pc)) != NULL) | 434 | while ((name = luaF_getlocalname(p, ++i, pc)) != NULL) |
410 | lua_pushstring(L, name); | 435 | lua_pushstring(L, name); |
411 | return i-1; | 436 | return i-1; |
@@ -428,12 +453,6 @@ static int get_limits (lua_State *L) { | |||
428 | } | 453 | } |
429 | 454 | ||
430 | 455 | ||
431 | static int setgcthreshold (lua_State *L) { | ||
432 | lua_setgcthreshold(L, luaL_checkint(L, 1)); | ||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | |||
437 | static int mem_query (lua_State *L) { | 456 | static int mem_query (lua_State *L) { |
438 | if (lua_isnone(L, 1)) { | 457 | if (lua_isnone(L, 1)) { |
439 | lua_pushinteger(L, memcontrol.total); | 458 | lua_pushinteger(L, memcontrol.total); |
@@ -448,16 +467,52 @@ static int mem_query (lua_State *L) { | |||
448 | } | 467 | } |
449 | 468 | ||
450 | 469 | ||
470 | static int settrick (lua_State *L) { | ||
471 | Trick = lua_tointeger(L, 1); | ||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | |||
476 | /*static int set_gcstate (lua_State *L) { | ||
477 | static const char *const state[] = {"propagate", "sweep", "finalize"}; | ||
478 | return 0; | ||
479 | }*/ | ||
480 | |||
481 | |||
482 | static int get_gccolor (lua_State *L) { | ||
483 | TValue *o; | ||
484 | luaL_checkany(L, 1); | ||
485 | o = obj_at(L, 1); | ||
486 | if (!iscollectable(o)) | ||
487 | lua_pushstring(L, "no collectable"); | ||
488 | else | ||
489 | lua_pushstring(L, iswhite(gcvalue(o)) ? "white" : | ||
490 | isblack(gcvalue(o)) ? "black" : "grey"); | ||
491 | return 1; | ||
492 | } | ||
493 | |||
494 | |||
495 | static int gcstate (lua_State *L) { | ||
496 | switch(G(L)->gcstate) { | ||
497 | case GCSpropagate: lua_pushstring(L, "propagate"); break; | ||
498 | case GCSsweepstring: lua_pushstring(L, "sweep strings"); break; | ||
499 | case GCSsweep: lua_pushstring(L, "sweep"); break; | ||
500 | case GCSfinalize: lua_pushstring(L, "finalize"); break; | ||
501 | } | ||
502 | return 1; | ||
503 | } | ||
504 | |||
505 | |||
451 | static int hash_query (lua_State *L) { | 506 | static int hash_query (lua_State *L) { |
452 | if (lua_isnone(L, 2)) { | 507 | if (lua_isnone(L, 2)) { |
453 | luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected"); | 508 | luaL_argcheck(L, lua_type(L, 1) == LUA_TSTRING, 1, "string expected"); |
454 | lua_pushinteger(L, tsvalue(func_at(L, 1))->hash); | 509 | lua_pushinteger(L, tsvalue(obj_at(L, 1))->hash); |
455 | } | 510 | } |
456 | else { | 511 | else { |
457 | TValue *o = func_at(L, 1); | 512 | TValue *o = obj_at(L, 1); |
458 | Table *t; | 513 | Table *t; |
459 | luaL_checktype(L, 2, LUA_TTABLE); | 514 | luaL_checktype(L, 2, LUA_TTABLE); |
460 | t = hvalue(func_at(L, 2)); | 515 | t = hvalue(obj_at(L, 2)); |
461 | lua_pushinteger(L, luaH_mainposition(t, o) - t->node); | 516 | lua_pushinteger(L, luaH_mainposition(t, o) - t->node); |
462 | } | 517 | } |
463 | return 1; | 518 | return 1; |
@@ -479,7 +534,7 @@ static int table_query (lua_State *L) { | |||
479 | const Table *t; | 534 | const Table *t; |
480 | int i = luaL_optint(L, 2, -1); | 535 | int i = luaL_optint(L, 2, -1); |
481 | luaL_checktype(L, 1, LUA_TTABLE); | 536 | luaL_checktype(L, 1, LUA_TTABLE); |
482 | t = hvalue(func_at(L, 1)); | 537 | t = hvalue(obj_at(L, 1)); |
483 | if (i == -1) { | 538 | if (i == -1) { |
484 | lua_pushinteger(L, t->sizearray); | 539 | lua_pushinteger(L, t->sizearray); |
485 | lua_pushinteger(L, sizenode(t)); | 540 | lua_pushinteger(L, sizenode(t)); |
@@ -979,6 +1034,10 @@ static const struct luaL_reg tests_funcs[] = { | |||
979 | {"querytab", table_query}, | 1034 | {"querytab", table_query}, |
980 | {"doit", test_do}, | 1035 | {"doit", test_do}, |
981 | {"testC", testC}, | 1036 | {"testC", testC}, |
1037 | {"checkmemory", lua_checkmemory}, | ||
1038 | {"gccolor", get_gccolor}, | ||
1039 | {"gcstate", gcstate}, | ||
1040 | {"trick", settrick}, | ||
982 | {"ref", tref}, | 1041 | {"ref", tref}, |
983 | {"getref", getref}, | 1042 | {"getref", getref}, |
984 | {"unref", unref}, | 1043 | {"unref", unref}, |
@@ -995,7 +1054,6 @@ static const struct luaL_reg tests_funcs[] = { | |||
995 | {"doremote", doremote}, | 1054 | {"doremote", doremote}, |
996 | {"log2", log2_aux}, | 1055 | {"log2", log2_aux}, |
997 | {"int2fb", int2fb_aux}, | 1056 | {"int2fb", int2fb_aux}, |
998 | {"setgcthreshold", setgcthreshold}, | ||
999 | {"totalmem", mem_query}, | 1057 | {"totalmem", mem_query}, |
1000 | {"resume", coresume}, | 1058 | {"resume", coresume}, |
1001 | {"setyhook", setyhook}, | 1059 | {"setyhook", setyhook}, |