xref: /netbsd-src/external/gpl3/gcc/dist/libphobos/testsuite/libphobos.gc/precisegc.d (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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