1
2 /* Copyright (C) 2000-2021 by The D Language Foundation, All Rights Reserved
3 * http://www.digitalmars.com
4 * Distributed under the Boost Software License, Version 1.0.
5 * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
6 * https://github.com/D-Programming-Language/dmd/blob/master/src/root/rmem.c
7 */
8
9 #include "dsystem.h"
10 #include "rmem.h"
11
12 /* This implementation of the storage allocator uses the standard C allocation package.
13 */
14
15 Mem mem;
16
xstrdup(const char * s)17 char *Mem::xstrdup(const char *s)
18 {
19 char *p;
20
21 if (s)
22 {
23 #ifdef IN_GCC
24 p = ::xstrdup(s);
25 #else
26 p = strdup(s);
27 #endif
28 if (p)
29 return p;
30 error();
31 }
32 return NULL;
33 }
34
xmalloc(size_t size)35 void *Mem::xmalloc(size_t size)
36 { void *p;
37
38 if (!size)
39 p = NULL;
40 else
41 {
42 #ifdef IN_GCC
43 p = ::xmalloc(size);
44 #else
45 p = malloc(size);
46 #endif
47 if (!p)
48 error();
49 }
50 return p;
51 }
52
xcalloc(size_t size,size_t n)53 void *Mem::xcalloc(size_t size, size_t n)
54 { void *p;
55
56 if (!size || !n)
57 p = NULL;
58 else
59 {
60 #ifdef IN_GCC
61 p = ::xcalloc(size, n);
62 #else
63 p = calloc(size, n);
64 #endif
65 if (!p)
66 error();
67 }
68 return p;
69 }
70
xrealloc(void * p,size_t size)71 void *Mem::xrealloc(void *p, size_t size)
72 {
73 if (!size)
74 { if (p)
75 {
76 free(p);
77 p = NULL;
78 }
79 }
80 else if (!p)
81 {
82 #ifdef IN_GCC
83 p = ::xmalloc(size);
84 #else
85 p = malloc(size);
86 #endif
87 if (!p)
88 error();
89 }
90 else
91 {
92 void *psave = p;
93 #ifdef IN_GCC
94 p = ::xrealloc(psave, size);
95 #else
96 p = realloc(psave, size);
97 #endif
98 if (!p)
99 { xfree(psave);
100 error();
101 }
102 }
103 return p;
104 }
105
xfree(void * p)106 void Mem::xfree(void *p)
107 {
108 if (p)
109 free(p);
110 }
111
xmallocdup(void * o,size_t size)112 void *Mem::xmallocdup(void *o, size_t size)
113 { void *p;
114
115 if (!size)
116 p = NULL;
117 else
118 {
119 #ifdef IN_GCC
120 p = ::xmalloc(size);
121 #else
122 p = malloc(size);
123 #endif
124 if (!p)
125 error();
126 else
127 memcpy(p,o,size);
128 }
129 return p;
130 }
131
error()132 void Mem::error()
133 {
134 printf("Error: out of memory\n");
135 exit(EXIT_FAILURE);
136 }
137
138 /* =================================================== */
139
140 /* Allocate, but never release
141 */
142
143 // Allocate a little less than 1Mb because the C runtime adds some overhead that
144 // causes the actual memory block to be larger than 1Mb otherwise.
145 #define CHUNK_SIZE (256 * 4096 - 64)
146
147 static size_t heapleft = 0;
148 static void *heapp;
149
allocmemory(size_t m_size)150 extern "C" void *allocmemory(size_t m_size)
151 {
152 // 16 byte alignment is better (and sometimes needed) for doubles
153 m_size = (m_size + 15) & ~15;
154
155 // The layout of the code is selected so the most common case is straight through
156 if (m_size <= heapleft)
157 {
158 L1:
159 heapleft -= m_size;
160 void *p = heapp;
161 heapp = (void *)((char *)heapp + m_size);
162 return p;
163 }
164
165 if (m_size > CHUNK_SIZE)
166 {
167 #ifdef IN_GCC
168 void *p = xmalloc(m_size);
169 #else
170 void *p = malloc(m_size);
171 #endif
172 if (p)
173 return p;
174 printf("Error: out of memory\n");
175 exit(EXIT_FAILURE);
176 return p;
177 }
178
179 heapleft = CHUNK_SIZE;
180 #ifdef IN_GCC
181 heapp = xmalloc(CHUNK_SIZE);
182 #else
183 heapp = malloc(CHUNK_SIZE);
184 #endif
185 if (!heapp)
186 {
187 printf("Error: out of memory\n");
188 exit(EXIT_FAILURE);
189 }
190 goto L1;
191 }
192