1
2module core.internal.gc.impl.proto.gc;
3
4import core.gc.gcinterface;
5
6import core.internal.container.array;
7
8import cstdlib = core.stdc.stdlib : calloc, free, malloc, realloc;
9static import core.memory;
10
11extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc; /* dmd @@@BUG11461@@@ */
12
13private
14{
15    extern (C) void gc_init_nothrow() nothrow @nogc;
16    extern (C) void gc_term();
17
18    extern (C) void gc_enable() nothrow;
19    extern (C) void gc_disable() nothrow;
20
21    extern (C) void*    gc_malloc( size_t sz, uint ba = 0, const scope TypeInfo = null ) pure nothrow;
22    extern (C) void*    gc_calloc( size_t sz, uint ba = 0, const scope TypeInfo = null ) pure nothrow;
23    extern (C) BlkInfo  gc_qalloc( size_t sz, uint ba = 0, const scope TypeInfo = null ) pure nothrow;
24    extern (C) void*    gc_realloc(return scope void* p, size_t sz, uint ba = 0, const scope TypeInfo = null ) pure nothrow;
25    extern (C) size_t   gc_reserve( size_t sz ) nothrow;
26
27    extern (C) void gc_addRange(const void* p, size_t sz, const scope TypeInfo ti = null ) nothrow @nogc;
28    extern (C) void gc_addRoot(const void* p ) nothrow @nogc;
29}
30
31class ProtoGC : GC
32{
33    Array!Root roots;
34    Array!Range ranges;
35
36    // Call this function when initializing the real GC
37    // upon ProtoGC term. This function should be called
38    // after the real GC is in place.
39    void transferRangesAndRoots()
40    {
41        // Transfer all ranges
42        foreach (ref r; ranges)
43        {
44            // Range(p, p + sz, cast() ti)
45            gc_addRange(r.pbot, r.ptop - r.pbot, r.ti);
46        }
47
48        // Transfer all roots
49        foreach (ref r; roots)
50        {
51            gc_addRoot(r.proot);
52        }
53    }
54
55    this()
56    {
57    }
58
59    void Dtor()
60    {
61    }
62
63    void enable()
64    {
65        .gc_init_nothrow();
66        .gc_enable();
67    }
68
69    void disable()
70    {
71        .gc_init_nothrow();
72        .gc_disable();
73    }
74
75    void collect() nothrow
76    {
77    }
78
79    void collectNoStack() nothrow
80    {
81    }
82
83    void minimize() nothrow
84    {
85    }
86
87    uint getAttr(void* p) nothrow
88    {
89        return 0;
90    }
91
92    uint setAttr(void* p, uint mask) nothrow
93    {
94        return 0;
95    }
96
97    uint clrAttr(void* p, uint mask) nothrow
98    {
99        return 0;
100    }
101
102    void* malloc(size_t size, uint bits, const scope TypeInfo ti) nothrow
103    {
104        .gc_init_nothrow();
105        return .gc_malloc(size, bits, ti);
106    }
107
108    BlkInfo qalloc(size_t size, uint bits, const scope TypeInfo ti) nothrow
109    {
110        .gc_init_nothrow();
111        return .gc_qalloc(size, bits, ti);
112    }
113
114    void* calloc(size_t size, uint bits, const scope TypeInfo ti) nothrow
115    {
116        .gc_init_nothrow();
117        return .gc_calloc(size, bits, ti);
118    }
119
120    void* realloc(void* p, size_t size, uint bits, const scope TypeInfo ti) nothrow
121    {
122        .gc_init_nothrow();
123        return .gc_realloc(p, size, bits, ti);
124    }
125
126    size_t extend(void* p, size_t minsize, size_t maxsize, const scope TypeInfo ti) nothrow
127    {
128        return 0;
129    }
130
131    size_t reserve(size_t size) nothrow
132    {
133        .gc_init_nothrow();
134        return .gc_reserve(size);
135    }
136
137    void free(void* p) nothrow @nogc
138    {
139        if (p) assert(false, "Invalid memory deallocation");
140    }
141
142    void* addrOf(void* p) nothrow @nogc
143    {
144        return null;
145    }
146
147    size_t sizeOf(void* p) nothrow @nogc
148    {
149        return 0;
150    }
151
152    BlkInfo query(void* p) nothrow
153    {
154        return BlkInfo.init;
155    }
156
157    core.memory.GC.Stats stats() nothrow
158    {
159        return typeof(return).init;
160    }
161
162
163    core.memory.GC.ProfileStats profileStats() nothrow
164    {
165        return typeof(return).init;
166    }
167
168
169    void addRoot(void* p) nothrow @nogc
170    {
171        roots.insertBack(Root(p));
172    }
173
174    void removeRoot(void* p) nothrow @nogc
175    {
176        foreach (ref r; roots)
177        {
178            if (r is p)
179            {
180                r = roots.back;
181                roots.popBack();
182                return;
183            }
184        }
185    }
186
187    @property RootIterator rootIter() return @nogc
188    {
189        return &rootsApply;
190    }
191
192    private int rootsApply(scope int delegate(ref Root) nothrow dg)
193    {
194        foreach (ref r; roots)
195        {
196            if (auto result = dg(r))
197                return result;
198        }
199        return 0;
200    }
201
202    void addRange(void* p, size_t sz, const TypeInfo ti = null) nothrow @nogc
203    {
204        ranges.insertBack(Range(p, p + sz, cast() ti));
205    }
206
207    void removeRange(void* p) nothrow @nogc
208    {
209        foreach (ref r; ranges)
210        {
211            if (r.pbot is p)
212            {
213                r = ranges.back;
214                ranges.popBack();
215                return;
216            }
217        }
218    }
219
220    @property RangeIterator rangeIter() return @nogc
221    {
222        return &rangesApply;
223    }
224
225    private int rangesApply(scope int delegate(ref Range) nothrow dg)
226    {
227        foreach (ref r; ranges)
228        {
229            if (auto result = dg(r))
230                return result;
231        }
232        return 0;
233    }
234
235    void runFinalizers(const scope void[] segment) nothrow
236    {
237    }
238
239    bool inFinalizer() nothrow
240    {
241        return false;
242    }
243
244    ulong allocatedInCurrentThread() nothrow
245    {
246        return stats().allocatedInCurrentThread;
247    }
248}
249