1 /** 2 * Compiler implementation of the D programming language 3 * http://dlang.org 4 * 5 * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved 6 * Authors: Walter Bright, http://www.digitalmars.com 7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(DMDSRC root/_rmem.d) 9 */ 10 11 module ddmd.root.rmem; 12 13 import core.stdc..string; 14 15 version (GC) 16 { 17 import core.memory : GC; 18 19 extern (C++) struct Mem 20 { 21 static char* xstrdup(const(char)* p) nothrow 22 { 23 return p[0 .. strlen(p) + 1].dup.ptr; 24 } 25 26 static void xfree(void* p) nothrow 27 { 28 } 29 30 static void* xmalloc(size_t n) nothrow 31 { 32 return GC.malloc(n); 33 } 34 35 static void* xcalloc(size_t size, size_t n) nothrow 36 { 37 return GC.calloc(size * n); 38 } 39 40 static void* xrealloc(void* p, size_t size) nothrow 41 { 42 return GC.realloc(p, size); 43 } 44 } 45 46 extern (C++) const __gshared Mem mem; 47 } 48 else 49 { 50 import core.stdc.stdlib; 51 import core.stdc.stdio; 52 53 extern (C++) struct Mem 54 { 55 static char* xstrdup(const(char)* s) nothrow 56 { 57 if (s) 58 { 59 auto p = .strdup(s); 60 if (p) 61 return p; 62 error(); 63 } 64 return null; 65 } 66 67 static void xfree(void* p) nothrow 68 { 69 if (p) 70 .free(p); 71 } 72 73 static void* xmalloc(size_t size) nothrow 74 { 75 if (!size) 76 return null; 77 78 auto p = .malloc(size); 79 if (!p) 80 error(); 81 return p; 82 } 83 84 static void* xcalloc(size_t size, size_t n) nothrow 85 { 86 if (!size || !n) 87 return null; 88 89 auto p = .calloc(size, n); 90 if (!p) 91 error(); 92 return p; 93 } 94 95 static void* xrealloc(void* p, size_t size) nothrow 96 { 97 if (!size) 98 { 99 if (p) 100 .free(p); 101 return null; 102 } 103 104 if (!p) 105 { 106 p = .malloc(size); 107 if (!p) 108 error(); 109 return p; 110 } 111 112 p = .realloc(p, size); 113 if (!p) 114 error(); 115 return p; 116 } 117 118 static void error() nothrow 119 { 120 printf("Error: out of memory\n"); 121 exit(EXIT_FAILURE); 122 } 123 } 124 125 extern (C++) const __gshared Mem mem; 126 127 enum CHUNK_SIZE = (256 * 4096 - 64); 128 129 __gshared size_t heapleft = 0; 130 __gshared void* heapp; 131 132 extern (C) void* allocmemory(size_t m_size) nothrow 133 { 134 // 16 byte alignment is better (and sometimes needed) for doubles 135 m_size = (m_size + 15) & ~15; 136 137 // The layout of the code is selected so the most common case is straight through 138 if (m_size <= heapleft) 139 { 140 L1: 141 heapleft -= m_size; 142 auto p = heapp; 143 heapp = cast(void*)(cast(char*)heapp + m_size); 144 return p; 145 } 146 147 if (m_size > CHUNK_SIZE) 148 { 149 auto p = malloc(m_size); 150 if (p) 151 { 152 return p; 153 } 154 printf("Error: out of memory\n"); 155 exit(EXIT_FAILURE); 156 } 157 158 heapleft = CHUNK_SIZE; 159 heapp = malloc(CHUNK_SIZE); 160 if (!heapp) 161 { 162 printf("Error: out of memory\n"); 163 exit(EXIT_FAILURE); 164 } 165 goto L1; 166 } 167 168 version (DigitalMars) 169 { 170 enum OVERRIDE_MEMALLOC = true; 171 } 172 else version (LDC) 173 { 174 // Memory allocation functions gained weak linkage when the @weak attribute was introduced. 175 import ldc.attributes; 176 enum OVERRIDE_MEMALLOC = is(typeof(ldc.attributes.weak)); 177 } 178 else 179 { 180 enum OVERRIDE_MEMALLOC = false; 181 } 182 183 static if (OVERRIDE_MEMALLOC) 184 { 185 extern (C) void* _d_allocmemory(size_t m_size) nothrow 186 { 187 return allocmemory(m_size); 188 } 189 190 extern (C) Object _d_newclass(const ClassInfo ci) nothrow 191 { 192 auto p = allocmemory(ci.init.length); 193 p[0 .. ci.init.length] = cast(void[])ci.init[]; 194 return cast(Object)p; 195 } 196 197 version (LDC) 198 { 199 extern (C) Object _d_allocclass(const ClassInfo ci) nothrow 200 { 201 return cast(Object)allocmemory(ci.init.length); 202 } 203 } 204 205 extern (C) void* _d_newitemT(TypeInfo ti) nothrow 206 { 207 auto p = allocmemory(ti.tsize); 208 (cast(ubyte*)p)[0 .. ti.init.length] = 0; 209 return p; 210 } 211 212 extern (C) void* _d_newitemiT(TypeInfo ti) nothrow 213 { 214 auto p = allocmemory(ti.tsize); 215 p[0 .. ti.init.length] = ti.init[]; 216 return p; 217 } 218 } 219 } 220 221 extern (D) static char[] xarraydup(const(char)[] s) nothrow 222 { 223 if (s) 224 { 225 auto p = cast(char*)mem.xmalloc(s.length + 1); 226 char[] a = p[0 .. s.length]; 227 a[] = s[0 .. s.length]; 228 p[s.length] = 0; // preserve 0 terminator semantics 229 return a; 230 } 231 return null; 232 } 233 234