| // precise GC related: |
| // https://issues.dlang.org/show_bug.cgi?id=3463 |
| // https://issues.dlang.org/show_bug.cgi?id=4358 |
| // https://issues.dlang.org/show_bug.cgi?id=9094 |
| // https://issues.dlang.org/show_bug.cgi?id=13801 |
| // https://issues.dlang.org/show_bug.cgi?id=18900 |
| module testgc; |
| |
| import core.memory; |
| import core.stdc.stdio; |
| |
| class C |
| { |
| __gshared int dtors; |
| ~this() { dtors++; } |
| |
| C next; |
| size_t val; |
| } |
| |
| struct S |
| { |
| __gshared int dtors; |
| ~this() { dtors++; } |
| |
| size_t val; |
| S* next; |
| } |
| |
| struct L |
| { |
| __gshared int dtors; |
| ~this() { dtors++; } |
| |
| size_t[1000] data; |
| S* node; |
| } |
| |
| struct Roots |
| { |
| C c; |
| S *s; |
| L *l; |
| }; |
| |
| Roots* roots; |
| size_t iroots; |
| |
| void init() |
| { |
| roots = new Roots; |
| roots.c = new C; |
| roots.c.next = new C; |
| |
| roots.s = new S; |
| roots.s.next = new S; |
| |
| roots.l = new L; |
| roots.l.node = new S; |
| } |
| |
| void verifyPointers() |
| { |
| assert(C.dtors == 0); |
| assert(S.dtors == 0); |
| assert(L.dtors == 0); |
| } |
| |
| // compiling with -gx should help eliminating false pointers on the stack |
| Roots makeFalsePointers() |
| { |
| roots.c.val = cast(size_t) cast(void*) roots.c.next; |
| roots.c.next = null; |
| roots.s.val = cast(size_t) cast(void*) roots.s.next; |
| roots.s.next = null; |
| roots.l.data[7] = cast(size_t) cast(void*) roots.l.node; |
| roots.l.node = null; |
| |
| return Roots(null, null, null); // try to spill register contents |
| } |
| |
| Roots moveRoot() |
| { |
| iroots = cast(size_t)roots; |
| roots = null; |
| |
| return Roots(null, null, null); // try to spill register contents |
| } |
| |
| // compiling with -gx should help eliminating false pointers on the stack |
| void verifyFalsePointers() |
| { |
| assert(C.dtors <= 1); |
| if (C.dtors < 1) printf ("False pointers? C.dtors = %d, 1 expected\n", C.dtors); |
| assert(S.dtors <= 2); |
| if (S.dtors < 2) printf ("False pointers? S.dtors = %d, 2 expected\n", S.dtors); |
| assert(L.dtors == 0); |
| } |
| |
| extern(C) __gshared string[] rt_options = [ "gcopt=gc:precise", "scanDataSeg=precise" ]; |
| |
| void main() |
| { |
| GC.collect(); // cleanup from unittests |
| |
| init(); |
| GC.collect(); // should collect nothing |
| verifyPointers(); |
| |
| makeFalsePointers(); |
| GC.collect(); // should collect roots.c.next, roots.s.next and roots.l.node |
| verifyFalsePointers(); |
| |
| moveRoot(); |
| GC.collect(); // should collect all |
| |
| version(Windows) // precise DATA scanning only implemented on Windows |
| { |
| assert(C.dtors <= 2); |
| if (C.dtors < 2) printf ("False DATA pointers? C.dtors = %d, 2 expected\n", C.dtors); |
| assert(S.dtors <= 3); |
| if (S.dtors < 3) printf ("False DATA pointers? S.dtors = %d, 2 expected\n", S.dtors); |
| assert(L.dtors <= 1); |
| if (L.dtors < 1) printf ("False DATA pointers? L.dtors = %d, 1 expected\n", L.dtors); |
| } |
| } |