diff options
-rw-r--r-- | ltests.c | 69 |
1 files changed, 45 insertions, 24 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 2.95 2010/04/16 17:42:49 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.96 2010/04/19 16:38:25 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 | */ |
@@ -179,17 +179,12 @@ void *debug_realloc (void *ud, void *b, size_t oldsize, size_t size) { | |||
179 | ** ======================================================= | 179 | ** ======================================================= |
180 | */ | 180 | */ |
181 | 181 | ||
182 | #define issweep(g) (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) | ||
183 | |||
184 | 182 | ||
185 | static int testobjref1 (global_State *g, GCObject *f, GCObject *t) { | 183 | static int testobjref1 (global_State *g, GCObject *f, GCObject *t) { |
186 | if (isdead(g,t)) return 0; | 184 | if (isdead(g,t)) return 0; |
187 | if (g->gcstate == GCSpropagate) | 185 | if (g->gckind == KGC_GEN || !issweepphase(g)) |
188 | return !isblack(f) || !iswhite(t); | 186 | return !isblack(f) || !iswhite(t); |
189 | else if (g->gcstate == GCSfinalize) | 187 | else return 1; |
190 | return iswhite(f); | ||
191 | else | ||
192 | return 1; | ||
193 | } | 188 | } |
194 | 189 | ||
195 | 190 | ||
@@ -227,23 +222,13 @@ static void checkvalref (global_State *g, GCObject *f, const TValue *t) { | |||
227 | 222 | ||
228 | static void checktable (global_State *g, Table *h) { | 223 | static void checktable (global_State *g, Table *h) { |
229 | int i; | 224 | int i; |
230 | int weakkey = 0; | 225 | Node *n, *limit = gnode(h, sizenode(h)); |
231 | int weakvalue = 0; | ||
232 | const TValue *mode; | ||
233 | GCObject *hgc = obj2gco(h); | 226 | GCObject *hgc = obj2gco(h); |
234 | if (h->metatable) | 227 | if (h->metatable) |
235 | checkobjref(g, hgc, h->metatable); | 228 | checkobjref(g, hgc, h->metatable); |
236 | mode = gfasttm(g, h->metatable, TM_MODE); | 229 | for (i = 0; i < h->sizearray; i++) |
237 | if (mode && ttisstring(mode)) { /* is there a weak mode? */ | ||
238 | weakkey = (strchr(svalue(mode), 'k') != NULL); | ||
239 | weakvalue = (strchr(svalue(mode), 'v') != NULL); | ||
240 | } | ||
241 | i = h->sizearray; | ||
242 | while (i--) | ||
243 | checkvalref(g, hgc, &h->array[i]); | 230 | checkvalref(g, hgc, &h->array[i]); |
244 | i = sizenode(h); | 231 | for (n = gnode(h, 0); n < limit; n++) { |
245 | while (i--) { | ||
246 | Node *n = gnode(h, i); | ||
247 | if (!ttisnil(gval(n))) { | 232 | if (!ttisnil(gval(n))) { |
248 | lua_assert(!ttisnil(gkey(n))); | 233 | lua_assert(!ttisnil(gkey(n))); |
249 | checkvalref(g, hgc, gkey(n)); | 234 | checkvalref(g, hgc, gkey(n)); |
@@ -336,9 +321,9 @@ static void checkstack (global_State *g, lua_State *L1) { | |||
336 | 321 | ||
337 | static void checkobject (global_State *g, GCObject *o) { | 322 | static void checkobject (global_State *g, GCObject *o) { |
338 | if (isdead(g, o)) | 323 | if (isdead(g, o)) |
339 | lua_assert(issweep(g)); | 324 | lua_assert(issweepphase(g)); |
340 | else { | 325 | else { |
341 | if (g->gcstate == GCSfinalize) | 326 | if (g->gcstate == GCSpause) |
342 | lua_assert(iswhite(o)); | 327 | lua_assert(iswhite(o)); |
343 | switch (gch(o)->tt) { | 328 | switch (gch(o)->tt) { |
344 | case LUA_TUPVAL: { | 329 | case LUA_TUPVAL: { |
@@ -376,15 +361,51 @@ static void checkobject (global_State *g, GCObject *o) { | |||
376 | } | 361 | } |
377 | 362 | ||
378 | 363 | ||
364 | #define GRAYBIT 7 | ||
365 | |||
366 | static void checkgraylist (GCObject *l) { | ||
367 | while (l) { | ||
368 | lua_assert(isgray(l)); | ||
369 | lua_assert(!testbit(l->gch.marked, GRAYBIT)); | ||
370 | //if (testbit(l->gch.marked, GRAYBIT)) | ||
371 | // printf("%s (%02x) %p\n", ttypename(l->gch.tt), l->gch.marked, l); | ||
372 | l->gch.marked = l_setbit(l->gch.marked, GRAYBIT); | ||
373 | switch (gch(l)->tt) { | ||
374 | case LUA_TTABLE: l = gco2t(l)->gclist; break; | ||
375 | case LUA_TFUNCTION: l = gco2cl(l)->c.gclist; break; | ||
376 | case LUA_TTHREAD: l = gco2th(l)->gclist; break; | ||
377 | case LUA_TPROTO: l = gco2p(l)->gclist; break; | ||
378 | default: lua_assert(0); /* other objects cannot be gray */ | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | |||
383 | |||
384 | static void markgrays (global_State *g) { | ||
385 | checkgraylist(g->gray); | ||
386 | checkgraylist(g->grayagain); | ||
387 | checkgraylist(g->weak); | ||
388 | checkgraylist(g->ephemeron); | ||
389 | checkgraylist(g->allweak); | ||
390 | } | ||
391 | |||
392 | |||
379 | int lua_checkmemory (lua_State *L) { | 393 | int lua_checkmemory (lua_State *L) { |
380 | global_State *g = G(L); | 394 | global_State *g = G(L); |
381 | GCObject *o; | 395 | GCObject *o; |
382 | UpVal *uv; | 396 | UpVal *uv; |
383 | checkliveness(g, &g->l_registry); | 397 | checkliveness(g, &g->l_registry); |
384 | checkstack(g, g->mainthread); | 398 | checkstack(g, g->mainthread); |
399 | g->mainthread->marked = resetbit(g->mainthread->marked, GRAYBIT); | ||
400 | markgrays(g); | ||
385 | for (o = g->allgc; o != NULL; o = gch(o)->next) { | 401 | for (o = g->allgc; o != NULL; o = gch(o)->next) { |
386 | lua_assert(!testbits(o->gch.marked, bitmask(SEPARATED))); | ||
387 | checkobject(g, o); | 402 | checkobject(g, o); |
403 | if (isgray(o)) { | ||
404 | lua_assert(issweepphase(g) || testbit(o->gch.marked, GRAYBIT)); | ||
405 | o->gch.marked = resetbit(o->gch.marked, GRAYBIT); | ||
406 | } | ||
407 | lua_assert(!testbit(o->gch.marked, SEPARATED)); | ||
408 | lua_assert(!testbit(o->gch.marked, GRAYBIT)); | ||
388 | } | 409 | } |
389 | for (o = g->udgc; o != NULL; o = gch(o)->next) { | 410 | for (o = g->udgc; o != NULL; o = gch(o)->next) { |
390 | lua_assert(gch(o)->tt == LUA_TUSERDATA && | 411 | lua_assert(gch(o)->tt == LUA_TUSERDATA && |