1import core.gc.registry;
2import core.gc.gcinterface;
3import core.stdc.stdlib;
4
5static import core.memory;
6
7extern (C) __gshared string[] rt_options = ["gcopt=gc:malloc"];
8
9extern (C) pragma(crt_constructor) void register_mygc()
10{
11    registerGCFactory("malloc", &MallocGC.initialize);
12}
13
14extern (C) void register_default_gcs()
15{
16    // remove default GCs
17}
18
19/** Simple GC that requires any pointers passed to it's API
20    to point to start of the allocation.
21 */
22class MallocGC : GC
23{
24nothrow @nogc:
25    static GC initialize()
26    {
27        import core.stdc.string : memcpy;
28
29        __gshared ubyte[__traits(classInstanceSize, MallocGC)] buf;
30
31        auto init = typeid(MallocGC).initializer();
32        assert(init.length == buf.length);
33        auto instance = cast(MallocGC) memcpy(buf.ptr, init.ptr, init.length);
34        instance.__ctor();
35        return instance;
36    }
37
38    this()
39    {
40    }
41
42    void Dtor()
43    {
44    }
45
46    void enable()
47    {
48    }
49
50    void disable()
51    {
52    }
53
54    void collect() nothrow
55    {
56    }
57
58    void collectNoStack() nothrow
59    {
60    }
61
62    void minimize() nothrow
63    {
64    }
65
66    uint getAttr(void* p) nothrow
67    {
68        return 0;
69    }
70
71    uint setAttr(void* p, uint mask) nothrow
72    {
73        return mask;
74    }
75
76    uint clrAttr(void* p, uint mask) nothrow
77    {
78        return mask;
79    }
80
81    void* malloc(size_t size, uint bits, const TypeInfo ti) nothrow
82    {
83        return sentinelAdd(.malloc(size + sentinelSize), size);
84    }
85
86    BlkInfo qalloc(size_t size, uint bits, const scope TypeInfo ti) nothrow
87    {
88        return BlkInfo(malloc(size, bits, ti), size);
89    }
90
91    void* calloc(size_t size, uint bits, const TypeInfo ti) nothrow
92    {
93        return sentinelAdd(.calloc(1, size + sentinelSize), size);
94    }
95
96    void* realloc(void* p, size_t size, uint bits, const TypeInfo ti) nothrow
97    {
98        return sentinelAdd(.realloc(p - sentinelSize, size + sentinelSize), size);
99    }
100
101    size_t extend(void* p, size_t minsize, size_t maxsize, const TypeInfo ti) nothrow
102    {
103        return 0;
104    }
105
106    size_t reserve(size_t size) nothrow
107    {
108        return 0;
109    }
110
111    void free(void* p) nothrow
112    {
113        free(p - sentinelSize);
114    }
115
116    void* addrOf(void* p) nothrow
117    {
118        return p;
119    }
120
121    size_t sizeOf(void* p) nothrow
122    {
123        return query(p).size;
124    }
125
126    BlkInfo query(void* p) nothrow
127    {
128        return p ? BlkInfo(p, sentinelGet(p)) : BlkInfo.init;
129    }
130
131    core.memory.GC.Stats stats() nothrow
132    {
133        return core.memory.GC.Stats.init;
134    }
135
136    core.memory.GC.ProfileStats profileStats() nothrow
137    {
138        return typeof(return).init;
139    }
140
141    void addRoot(void* p) nothrow @nogc
142    {
143    }
144
145    void removeRoot(void* p) nothrow @nogc
146    {
147    }
148
149    @property RootIterator rootIter() @nogc
150    {
151        return null;
152    }
153
154    void addRange(void* p, size_t sz, const TypeInfo ti) nothrow @nogc
155    {
156    }
157
158    void removeRange(void* p) nothrow @nogc
159    {
160    }
161
162    @property RangeIterator rangeIter() @nogc
163    {
164        return null;
165    }
166
167    void runFinalizers(const scope void[] segment) nothrow
168    {
169    }
170
171    bool inFinalizer() nothrow
172    {
173        return false;
174    }
175
176    ulong allocatedInCurrentThread() nothrow
177    {
178        return stats().allocatedInCurrentThread;
179    }
180
181private:
182    // doesn't care for alignment
183    static void* sentinelAdd(void* p, size_t value)
184    {
185        *cast(size_t*) p = value;
186        return p + sentinelSize;
187    }
188
189    static size_t sentinelGet(void* p)
190    {
191        return *cast(size_t*)(p - sentinelSize);
192    }
193
194    enum sentinelSize = size_t.sizeof;
195}
196
197void main()
198{
199    // test array append cache
200    char[] s;
201    foreach (char c; char.min .. char.max + 1)
202        s ~= c;
203}
204