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 |