1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
// 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);
}
}
|