1 // precise GC related: 2 // https://issues.dlang.org/show_bug.cgi?id=3463 3 // https://issues.dlang.org/show_bug.cgi?id=4358 4 // https://issues.dlang.org/show_bug.cgi?id=9094 5 // https://issues.dlang.org/show_bug.cgi?id=13801 6 // https://issues.dlang.org/show_bug.cgi?id=18900 7 module testgc; 8 9 import core.memory; 10 import core.stdc.stdio; 11 12 class C 13 { 14 __gshared int dtors; 15 ~this() { dtors++; } 16 17 C next; 18 size_t val; 19 } 20 21 struct S 22 { 23 __gshared int dtors; 24 ~this() { dtors++; } 25 26 size_t val; 27 S* next; 28 } 29 30 struct L 31 { 32 __gshared int dtors; 33 ~this() { dtors++; } 34 35 size_t[1000] data; 36 S* node; 37 } 38 39 struct Roots 40 { 41 C c; 42 S *s; 43 L *l; 44 }; 45 46 Roots* roots; 47 size_t iroots; 48 49 void init() 50 { 51 roots = new Roots; 52 roots.c = new C; 53 roots.c.next = new C; 54 55 roots.s = new S; 56 roots.s.next = new S; 57 58 roots.l = new L; 59 roots.l.node = new S; 60 } 61 62 void verifyPointers() 63 { 64 assert(C.dtors == 0); 65 assert(S.dtors == 0); 66 assert(L.dtors == 0); 67 } 68 69 // compiling with -gx should help eliminating false pointers on the stack 70 Roots makeFalsePointers() 71 { 72 roots.c.val = cast(size_t) cast(void*) roots.c.next; 73 roots.c.next = null; 74 roots.s.val = cast(size_t) cast(void*) roots.s.next; 75 roots.s.next = null; 76 roots.l.data[7] = cast(size_t) cast(void*) roots.l.node; 77 roots.l.node = null; 78 79 return Roots(null, null, null); // try to spill register contents 80 } 81 82 Roots moveRoot() 83 { 84 iroots = cast(size_t)roots; 85 roots = null; 86 87 return Roots(null, null, null); // try to spill register contents 88 } 89 90 // compiling with -gx should help eliminating false pointers on the stack 91 void verifyFalsePointers() 92 { 93 assert(C.dtors <= 1); 94 if (C.dtors < 1) printf ("False pointers? C.dtors = %d, 1 expected\n", C.dtors); 95 assert(S.dtors <= 2); 96 if (S.dtors < 2) printf ("False pointers? S.dtors = %d, 2 expected\n", S.dtors); 97 assert(L.dtors == 0); 98 } 99 100 extern(C) __gshared string[] rt_options = [ "gcopt=gc:precise", "scanDataSeg=precise" ]; 101 102 void main() 103 { 104 GC.collect(); // cleanup from unittests 105 106 init(); 107 GC.collect(); // should collect nothing 108 verifyPointers(); 109 110 makeFalsePointers(); 111 GC.collect(); // should collect roots.c.next, roots.s.next and roots.l.node 112 verifyFalsePointers(); 113 114 moveRoot(); 115 GC.collect(); // should collect all 116 117 version(Windows) // precise DATA scanning only implemented on Windows 118 { 119 assert(C.dtors <= 2); 120 if (C.dtors < 2) printf ("False DATA pointers? C.dtors = %d, 2 expected\n", C.dtors); 121 assert(S.dtors <= 3); 122 if (S.dtors < 3) printf ("False DATA pointers? S.dtors = %d, 2 expected\n", S.dtors); 123 assert(L.dtors <= 1); 124 if (L.dtors < 1) printf ("False DATA pointers? L.dtors = %d, 1 expected\n", L.dtors); 125 } 126 } 127