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;
~this()15 ~this() { dtors++; }
16
17 C next;
18 size_t val;
19 }
20
21 struct S
22 {
23 __gshared int dtors;
~thisS24 ~this() { dtors++; }
25
26 size_t val;
27 S* next;
28 }
29
30 struct L
31 {
32 __gshared int dtors;
~this()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
init()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
verifyPointers()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
makeFalsePointers()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
moveRoot()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
verifyFalsePointers()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
main()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