1169691Skanimport core.gc.registry; 2169691Skanimport core.gc.gcinterface; 3169691Skanimport core.stdc.stdlib; 4169691Skan 5169691Skanstatic import core.memory; 6169691Skan 7169691Skanextern (C) __gshared string[] rt_options = ["gcopt=gc:malloc"]; 8169691Skan 9169691Skanextern (C) pragma(crt_constructor) void register_mygc() 10169691Skan{ 11169691Skan registerGCFactory("malloc", &MallocGC.initialize); 12169691Skan} 13169691Skan 14169691Skanextern (C) void register_default_gcs() 15169691Skan{ 16169691Skan // remove default GCs 17169691Skan} 18169691Skan 19169691Skan/** Simple GC that requires any pointers passed to it's API 20169691Skan to point to start of the allocation. 21169691Skan */ 22169691Skanclass MallocGC : GC 23169691Skan{ 24169691Skannothrow @nogc: 25169691Skan static GC initialize() 26169691Skan { 27169691Skan import core.stdc.string : memcpy; 28169691Skan 29169691Skan __gshared ubyte[__traits(classInstanceSize, MallocGC)] buf; 30169691Skan 31169691Skan auto init = typeid(MallocGC).initializer(); 32169691Skan assert(init.length == buf.length); 33169691Skan auto instance = cast(MallocGC) memcpy(buf.ptr, init.ptr, init.length); 34169691Skan instance.__ctor(); 35169691Skan return instance; 36169691Skan } 37169691Skan 38169691Skan this() 39169691Skan { 40169691Skan } 41169691Skan 42169691Skan void Dtor() 43169691Skan { 44169691Skan } 45169691Skan 46169691Skan void enable() 47169691Skan { 48169691Skan } 49169691Skan 50169691Skan void disable() 51169691Skan { 52169691Skan } 53169691Skan 54169691Skan void collect() nothrow 55169691Skan { 56169691Skan } 57169691Skan 58169691Skan void collectNoStack() nothrow 59169691Skan { 60169691Skan } 61169691Skan 62169691Skan void minimize() nothrow 63169691Skan { 64169691Skan } 65169691Skan 66169691Skan uint getAttr(void* p) nothrow 67169691Skan { 68169691Skan return 0; 69169691Skan } 70169691Skan 71169691Skan uint setAttr(void* p, uint mask) nothrow 72169691Skan { 73169691Skan return mask; 74169691Skan } 75169691Skan 76169691Skan uint clrAttr(void* p, uint mask) nothrow 77169691Skan { 78169691Skan return mask; 79169691Skan } 80169691Skan 81169691Skan void* malloc(size_t size, uint bits, const TypeInfo ti) nothrow 82169691Skan { 83169691Skan return sentinelAdd(.malloc(size + sentinelSize), size); 84169691Skan } 85169691Skan 86169691Skan BlkInfo qalloc(size_t size, uint bits, const scope TypeInfo ti) nothrow 87169691Skan { 88169691Skan return BlkInfo(malloc(size, bits, ti), size); 89169691Skan } 90169691Skan 91169691Skan void* calloc(size_t size, uint bits, const TypeInfo ti) nothrow 92169691Skan { 93169691Skan return sentinelAdd(.calloc(1, size + sentinelSize), size); 94169691Skan } 95169691Skan 96169691Skan void* realloc(void* p, size_t size, uint bits, const TypeInfo ti) nothrow 97169691Skan { 98169691Skan return sentinelAdd(.realloc(p - sentinelSize, size + sentinelSize), size); 99169691Skan } 100169691Skan 101169691Skan size_t extend(void* p, size_t minsize, size_t maxsize, const TypeInfo ti) nothrow 102169691Skan { 103169691Skan return 0; 104169691Skan } 105169691Skan 106169691Skan size_t reserve(size_t size) nothrow 107169691Skan { 108169691Skan return 0; 109169691Skan } 110169691Skan 111169691Skan void free(void* p) nothrow 112169691Skan { 113169691Skan free(p - sentinelSize); 114169691Skan } 115169691Skan 116169691Skan void* addrOf(void* p) nothrow 117169691Skan { 118169691Skan return p; 119169691Skan } 120169691Skan 121169691Skan size_t sizeOf(void* p) nothrow 122169691Skan { 123169691Skan return query(p).size; 124169691Skan } 125169691Skan 126169691Skan BlkInfo query(void* p) nothrow 127169691Skan { 128169691Skan return p ? BlkInfo(p, sentinelGet(p)) : BlkInfo.init; 129169691Skan } 130169691Skan 131169691Skan core.memory.GC.Stats stats() nothrow 132169691Skan { 133169691Skan return core.memory.GC.Stats.init; 134169691Skan } 135169691Skan 136169691Skan core.memory.GC.ProfileStats profileStats() nothrow 137169691Skan { 138169691Skan return typeof(return).init; 139169691Skan } 140169691Skan 141169691Skan void addRoot(void* p) nothrow @nogc 142169691Skan { 143169691Skan } 144169691Skan 145169691Skan void removeRoot(void* p) nothrow @nogc 146169691Skan { 147169691Skan } 148169691Skan 149169691Skan @property RootIterator rootIter() @nogc 150169691Skan { 151169691Skan return null; 152169691Skan } 153169691Skan 154169691Skan void addRange(void* p, size_t sz, const TypeInfo ti) nothrow @nogc 155169691Skan { 156169691Skan } 157169691Skan 158169691Skan void removeRange(void* p) nothrow @nogc 159169691Skan { 160169691Skan } 161169691Skan 162169691Skan @property RangeIterator rangeIter() @nogc 163169691Skan { 164169691Skan return null; 165169691Skan } 166169691Skan 167169691Skan void runFinalizers(const scope void[] segment) nothrow 168169691Skan { 169169691Skan } 170169691Skan 171169691Skan bool inFinalizer() nothrow 172169691Skan { 173169691Skan return false; 174169691Skan } 175169691Skan 176169691Skan ulong allocatedInCurrentThread() nothrow 177169691Skan { 178169691Skan return stats().allocatedInCurrentThread; 179169691Skan } 180169691Skan 181169691Skanprivate: 182169691Skan // doesn't care for alignment 183169691Skan static void* sentinelAdd(void* p, size_t value) 184169691Skan { 185169691Skan *cast(size_t*) p = value; 186169691Skan return p + sentinelSize; 187169691Skan } 188169691Skan 189169691Skan static size_t sentinelGet(void* p) 190169691Skan { 191169691Skan return *cast(size_t*)(p - sentinelSize); 192169691Skan } 193169691Skan 194169691Skan enum sentinelSize = size_t.sizeof; 195169691Skan} 196169691Skan 197169691Skanvoid main() 198169691Skan{ 199169691Skan // test array append cache 200169691Skan char[] s; 201169691Skan foreach (char c; char.min .. char.max + 1) 202169691Skan s ~= c; 203169691Skan} 204169691Skan