| |
| /* Copyright (C) 2000-2021 by The D Language Foundation, All Rights Reserved |
| * http://www.digitalmars.com |
| * Distributed under the Boost Software License, Version 1.0. |
| * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) |
| * https://github.com/D-Programming-Language/dmd/blob/master/src/root/rmem.c |
| */ |
| |
| #include "dsystem.h" |
| #include "rmem.h" |
| |
| /* This implementation of the storage allocator uses the standard C allocation package. |
| */ |
| |
| Mem mem; |
| |
| char *Mem::xstrdup(const char *s) |
| { |
| char *p; |
| |
| if (s) |
| { |
| #ifdef IN_GCC |
| p = ::xstrdup(s); |
| #else |
| p = strdup(s); |
| #endif |
| if (p) |
| return p; |
| error(); |
| } |
| return NULL; |
| } |
| |
| void *Mem::xmalloc(size_t size) |
| { void *p; |
| |
| if (!size) |
| p = NULL; |
| else |
| { |
| #ifdef IN_GCC |
| p = ::xmalloc(size); |
| #else |
| p = malloc(size); |
| #endif |
| if (!p) |
| error(); |
| } |
| return p; |
| } |
| |
| void *Mem::xcalloc(size_t size, size_t n) |
| { void *p; |
| |
| if (!size || !n) |
| p = NULL; |
| else |
| { |
| #ifdef IN_GCC |
| p = ::xcalloc(size, n); |
| #else |
| p = calloc(size, n); |
| #endif |
| if (!p) |
| error(); |
| } |
| return p; |
| } |
| |
| void *Mem::xrealloc(void *p, size_t size) |
| { |
| if (!size) |
| { if (p) |
| { |
| free(p); |
| p = NULL; |
| } |
| } |
| else if (!p) |
| { |
| #ifdef IN_GCC |
| p = ::xmalloc(size); |
| #else |
| p = malloc(size); |
| #endif |
| if (!p) |
| error(); |
| } |
| else |
| { |
| void *psave = p; |
| #ifdef IN_GCC |
| p = ::xrealloc(psave, size); |
| #else |
| p = realloc(psave, size); |
| #endif |
| if (!p) |
| { xfree(psave); |
| error(); |
| } |
| } |
| return p; |
| } |
| |
| void Mem::xfree(void *p) |
| { |
| if (p) |
| free(p); |
| } |
| |
| void *Mem::xmallocdup(void *o, size_t size) |
| { void *p; |
| |
| if (!size) |
| p = NULL; |
| else |
| { |
| #ifdef IN_GCC |
| p = ::xmalloc(size); |
| #else |
| p = malloc(size); |
| #endif |
| if (!p) |
| error(); |
| else |
| memcpy(p,o,size); |
| } |
| return p; |
| } |
| |
| void Mem::error() |
| { |
| printf("Error: out of memory\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| /* =================================================== */ |
| |
| /* Allocate, but never release |
| */ |
| |
| // Allocate a little less than 1Mb because the C runtime adds some overhead that |
| // causes the actual memory block to be larger than 1Mb otherwise. |
| #define CHUNK_SIZE (256 * 4096 - 64) |
| |
| static size_t heapleft = 0; |
| static void *heapp; |
| |
| extern "C" void *allocmemory(size_t m_size) |
| { |
| // 16 byte alignment is better (and sometimes needed) for doubles |
| m_size = (m_size + 15) & ~15; |
| |
| // The layout of the code is selected so the most common case is straight through |
| if (m_size <= heapleft) |
| { |
| L1: |
| heapleft -= m_size; |
| void *p = heapp; |
| heapp = (void *)((char *)heapp + m_size); |
| return p; |
| } |
| |
| if (m_size > CHUNK_SIZE) |
| { |
| #ifdef IN_GCC |
| void *p = xmalloc(m_size); |
| #else |
| void *p = malloc(m_size); |
| #endif |
| if (p) |
| return p; |
| printf("Error: out of memory\n"); |
| exit(EXIT_FAILURE); |
| return p; |
| } |
| |
| heapleft = CHUNK_SIZE; |
| #ifdef IN_GCC |
| heapp = xmalloc(CHUNK_SIZE); |
| #else |
| heapp = malloc(CHUNK_SIZE); |
| #endif |
| if (!heapp) |
| { |
| printf("Error: out of memory\n"); |
| exit(EXIT_FAILURE); |
| } |
| goto L1; |
| } |