diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-04-29 14:33:51 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-04-29 14:33:51 -0300 |
| commit | ee7478e884adc6991f786f30c371a4a3da4e1992 (patch) | |
| tree | 0ab37fca3095f18c0288121836b5e150cbb9844c | |
| parent | aaa5d7adab1fd4a2f2d0c1f2996e354445ad163f (diff) | |
| download | lua-ee7478e884adc6991f786f30c371a4a3da4e1992.tar.gz lua-ee7478e884adc6991f786f30c371a4a3da4e1992.tar.bz2 lua-ee7478e884adc6991f786f30c371a4a3da4e1992.zip | |
improved 'lua_checkmemory', with better control over gray objects
| -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 && |
