diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-08-07 14:45:20 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-08-07 14:45:20 -0300 |
| commit | f13dc59416afa8fc93bb3d784d1a73e49e1b5b09 (patch) | |
| tree | 4719b653c8cbb3e0651e97ebb7acb96ac3a7a13d | |
| parent | 7c3cb71fa48fbe84d9d9c664eb646446fb80898b (diff) | |
| download | lua-f13dc59416afa8fc93bb3d784d1a73e49e1b5b09.tar.gz lua-f13dc59416afa8fc93bb3d784d1a73e49e1b5b09.tar.bz2 lua-f13dc59416afa8fc93bb3d784d1a73e49e1b5b09.zip | |
Better tests for gray lists
Test uses an extra bit in 'marked' to mark all elements in gray lists
and then check against elements colored gray.
| -rw-r--r-- | lgc.h | 5 | ||||
| -rw-r--r-- | ltests.c | 40 | ||||
| -rw-r--r-- | testes/nextvar.lua | 2 |
3 files changed, 37 insertions, 10 deletions
| @@ -69,13 +69,16 @@ | |||
| 69 | 69 | ||
| 70 | /* | 70 | /* |
| 71 | ** Layout for bit use in 'marked' field. First three bits are | 71 | ** Layout for bit use in 'marked' field. First three bits are |
| 72 | ** used for object "age" in generational mode. | 72 | ** used for object "age" in generational mode. Last bit is used |
| 73 | ** by tests. | ||
| 73 | */ | 74 | */ |
| 74 | #define WHITE0BIT 3 /* object is white (type 0) */ | 75 | #define WHITE0BIT 3 /* object is white (type 0) */ |
| 75 | #define WHITE1BIT 4 /* object is white (type 1) */ | 76 | #define WHITE1BIT 4 /* object is white (type 1) */ |
| 76 | #define BLACKBIT 5 /* object is black */ | 77 | #define BLACKBIT 5 /* object is black */ |
| 77 | #define FINALIZEDBIT 6 /* object has been marked for finalization */ | 78 | #define FINALIZEDBIT 6 /* object has been marked for finalization */ |
| 78 | 79 | ||
| 80 | #define TESTBIT 7 | ||
| 81 | |||
| 79 | 82 | ||
| 80 | 83 | ||
| 81 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) | 84 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) |
| @@ -522,7 +522,11 @@ static lu_mem checkgraylist (global_State *g, GCObject *o) { | |||
| 522 | int total = 0; /* count number of elements in the list */ | 522 | int total = 0; /* count number of elements in the list */ |
| 523 | ((void)g); /* better to keep it available if we need to print an object */ | 523 | ((void)g); /* better to keep it available if we need to print an object */ |
| 524 | while (o) { | 524 | while (o) { |
| 525 | lua_assert(isgray(o) || getage(o) == G_TOUCHED2); | 525 | lua_assert(!!isgray(o) ^ (getage(o) == G_TOUCHED2)); |
| 526 | //lua_assert(isgray(o) || getage(o) == G_TOUCHED2); | ||
| 527 | lua_assert(!testbit(o->marked, TESTBIT)); | ||
| 528 | if (keepinvariant(g)) | ||
| 529 | l_setbit(o->marked, TESTBIT); /* mark that object is in a gray list */ | ||
| 526 | total++; | 530 | total++; |
| 527 | switch (o->tt) { | 531 | switch (o->tt) { |
| 528 | case LUA_VTABLE: o = gco2t(o)->gclist; break; | 532 | case LUA_VTABLE: o = gco2t(o)->gclist; break; |
| @@ -556,9 +560,27 @@ static lu_mem checkgrays (global_State *g) { | |||
| 556 | } | 560 | } |
| 557 | 561 | ||
| 558 | 562 | ||
| 559 | /* Increment 't' if 'o' should be in a gray list */ | 563 | /* |
| 560 | #define incifingray(o,t) \ | 564 | ** Check whether 'o' should be in a gray list. If so, increment |
| 561 | if (isgray(o) || getage(o) == G_TOUCHED2) (t)++ | 565 | ** 'count' and check its TESTBIT. (It must have been previously set by |
| 566 | ** 'checkgraylist'.) | ||
| 567 | */ | ||
| 568 | static void incifingray (global_State *g, GCObject *o, lu_mem *count) { | ||
| 569 | if (!keepinvariant(g)) | ||
| 570 | return; /* gray lists not being kept in these phases */ | ||
| 571 | if (o->tt == LUA_VUPVAL) { | ||
| 572 | /* only open upvalues can be gray */ | ||
| 573 | lua_assert(!isgray(o) || upisopen(gco2upv(o))); | ||
| 574 | return; /* upvalues are never in gray lists */ | ||
| 575 | } | ||
| 576 | /* these are the ones that must be in gray lists */ | ||
| 577 | if (isgray(o) || getage(o) == G_TOUCHED2) { | ||
| 578 | (*count)++; | ||
| 579 | lua_assert(testbit(o->marked, TESTBIT)); | ||
| 580 | resetbit(o->marked, TESTBIT); /* prepare for next cycle */ | ||
| 581 | } | ||
| 582 | } | ||
| 583 | |||
| 562 | 584 | ||
| 563 | static lu_mem checklist (global_State *g, int maybedead, int tof, | 585 | static lu_mem checklist (global_State *g, int maybedead, int tof, |
| 564 | GCObject *newl, GCObject *survival, GCObject *old, GCObject *reallyold) { | 586 | GCObject *newl, GCObject *survival, GCObject *old, GCObject *reallyold) { |
| @@ -566,22 +588,22 @@ static lu_mem checklist (global_State *g, int maybedead, int tof, | |||
| 566 | lu_mem total = 0; /* number of object that should be in gray lists */ | 588 | lu_mem total = 0; /* number of object that should be in gray lists */ |
| 567 | for (o = newl; o != survival; o = o->next) { | 589 | for (o = newl; o != survival; o = o->next) { |
| 568 | checkobject(g, o, maybedead, G_NEW); | 590 | checkobject(g, o, maybedead, G_NEW); |
| 569 | incifingray(o, total); | 591 | incifingray(g, o, &total); |
| 570 | lua_assert(!tof == !tofinalize(o)); | 592 | lua_assert(!tof == !tofinalize(o)); |
| 571 | } | 593 | } |
| 572 | for (o = survival; o != old; o = o->next) { | 594 | for (o = survival; o != old; o = o->next) { |
| 573 | checkobject(g, o, 0, G_SURVIVAL); | 595 | checkobject(g, o, 0, G_SURVIVAL); |
| 574 | incifingray(o, total); | 596 | incifingray(g, o, &total); |
| 575 | lua_assert(!tof == !tofinalize(o)); | 597 | lua_assert(!tof == !tofinalize(o)); |
| 576 | } | 598 | } |
| 577 | for (o = old; o != reallyold; o = o->next) { | 599 | for (o = old; o != reallyold; o = o->next) { |
| 578 | checkobject(g, o, 0, G_OLD1); | 600 | checkobject(g, o, 0, G_OLD1); |
| 579 | incifingray(o, total); | 601 | incifingray(g, o, &total); |
| 580 | lua_assert(!tof == !tofinalize(o)); | 602 | lua_assert(!tof == !tofinalize(o)); |
| 581 | } | 603 | } |
| 582 | for (o = reallyold; o != NULL; o = o->next) { | 604 | for (o = reallyold; o != NULL; o = o->next) { |
| 583 | checkobject(g, o, 0, G_OLD); | 605 | checkobject(g, o, 0, G_OLD); |
| 584 | incifingray(o, total); | 606 | incifingray(g, o, &total); |
| 585 | lua_assert(!tof == !tofinalize(o)); | 607 | lua_assert(!tof == !tofinalize(o)); |
| 586 | } | 608 | } |
| 587 | return total; | 609 | return total; |
| @@ -619,7 +641,7 @@ int lua_checkmemory (lua_State *L) { | |||
| 619 | /* check 'tobefnz' list */ | 641 | /* check 'tobefnz' list */ |
| 620 | for (o = g->tobefnz; o != NULL; o = o->next) { | 642 | for (o = g->tobefnz; o != NULL; o = o->next) { |
| 621 | checkobject(g, o, 0, G_NEW); | 643 | checkobject(g, o, 0, G_NEW); |
| 622 | incifingray(o, totalshould); | 644 | incifingray(g, o, &totalshould); |
| 623 | lua_assert(tofinalize(o)); | 645 | lua_assert(tofinalize(o)); |
| 624 | lua_assert(o->tt == LUA_VUSERDATA || o->tt == LUA_VTABLE); | 646 | lua_assert(o->tt == LUA_VUSERDATA || o->tt == LUA_VTABLE); |
| 625 | } | 647 | } |
diff --git a/testes/nextvar.lua b/testes/nextvar.lua index 73af77dd..a16d557b 100644 --- a/testes/nextvar.lua +++ b/testes/nextvar.lua | |||
| @@ -88,6 +88,7 @@ for _, sa in ipairs(sizes) do -- 'sa' is size of the array part | |||
| 88 | arr[1 + sa + sh + 1] = "}" | 88 | arr[1 + sa + sh + 1] = "}" |
| 89 | local prog = table.concat(arr) | 89 | local prog = table.concat(arr) |
| 90 | local f = assert(load(prog)) | 90 | local f = assert(load(prog)) |
| 91 | collectgarbage("stop") | ||
| 91 | f() -- call once to ensure stack space | 92 | f() -- call once to ensure stack space |
| 92 | -- make sure table is not resized after being created | 93 | -- make sure table is not resized after being created |
| 93 | if sa == 0 or sh == 0 then | 94 | if sa == 0 or sh == 0 then |
| @@ -97,6 +98,7 @@ for _, sa in ipairs(sizes) do -- 'sa' is size of the array part | |||
| 97 | end | 98 | end |
| 98 | local t = f() | 99 | local t = f() |
| 99 | T.alloccount(); | 100 | T.alloccount(); |
| 101 | collectgarbage("restart") | ||
| 100 | assert(#t == sa) | 102 | assert(#t == sa) |
| 101 | check(t, sa, mp2(sh)) | 103 | check(t, sa, mp2(sh)) |
| 102 | end | 104 | end |
