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