blob: 768b75d27154c1e14c321597d5bd7583b73c09ca [file] [log] [blame]
/* 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;
}