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