| // 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); | |
| } | |
| } |