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