aboutsummaryrefslogtreecommitdiff
path: root/libphobos/testsuite/libphobos.gc/precisegc.d
blob: 9bcaf3f4faad0de69227aabcb664d1d9b8f8214e (plain)
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);
    }
}