1
2/* Copyright (C) 2000-2019 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
15Mem mem;
16
17char *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
35void *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
53void *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
71void *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
106void Mem::xfree(void *p)
107{
108    if (p)
109        free(p);
110}
111
112void *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
132void 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
147static size_t heapleft = 0;
148static void *heapp;
149
150extern "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