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