ldc/ddmd/root/rmem.d
Martin a5e5bd1716 Keep _d_newclass() semantics, re-introduce _d_allocclass() instead
And use that one in DtoNewClass(), keeping 3rd party code from breaking.
2016-08-15 13:19:11 +02:00

217 lines
4.9 KiB
D

// Compiler implementation of the D programming language
// Copyright (c) 1999-2015 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
module ddmd.root.rmem;
import core.stdc.string;
version (GC)
{
import core.memory : GC;
extern (C++) struct Mem
{
static char* xstrdup(const(char)* p) nothrow
{
return p[0 .. strlen(p) + 1].dup.ptr;
}
static void xfree(void* p) nothrow
{
}
static void* xmalloc(size_t n) nothrow
{
return GC.malloc(n);
}
static void* xcalloc(size_t size, size_t n) nothrow
{
return GC.calloc(size * n);
}
static void* xrealloc(void* p, size_t size) nothrow
{
return GC.realloc(p, size);
}
}
extern (C++) __gshared Mem mem;
}
else
{
import core.stdc.stdlib;
import core.stdc.stdio;
extern (C++) struct Mem
{
static char* xstrdup(const(char)* s) nothrow
{
if (s)
{
auto p = .strdup(s);
if (p)
return p;
error();
}
return null;
}
static void xfree(void* p) nothrow
{
if (p)
.free(p);
}
static void* xmalloc(size_t size) nothrow
{
if (!size)
return null;
auto p = .malloc(size);
if (!p)
error();
return p;
}
static void* xcalloc(size_t size, size_t n) nothrow
{
if (!size || !n)
return null;
auto p = .calloc(size, n);
if (!p)
error();
return p;
}
static void* xrealloc(void* p, size_t size) nothrow
{
if (!size)
{
if (p)
.free(p);
return null;
}
if (!p)
{
p = .malloc(size);
if (!p)
error();
return p;
}
p = .realloc(p, size);
if (!p)
error();
return p;
}
static void error() nothrow
{
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
}
}
extern (C++) __gshared Mem mem;
enum CHUNK_SIZE = (256 * 4096 - 64);
__gshared size_t heapleft = 0;
__gshared void* heapp;
extern (C) void* allocmemory(size_t m_size) nothrow
{
// 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;
auto p = heapp;
heapp = cast(void*)(cast(char*)heapp + m_size);
return p;
}
if (m_size > CHUNK_SIZE)
{
auto p = malloc(m_size);
if (p)
{
return p;
}
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
}
heapleft = CHUNK_SIZE;
heapp = malloc(CHUNK_SIZE);
if (!heapp)
{
printf("Error: out of memory\n");
exit(EXIT_FAILURE);
}
goto L1;
}
version (DigitalMars)
{
enum OVERRIDE_MEMALLOC = true;
}
else version (LDC)
{
// Memory allocation functions gained weak linkage when the @weak attribute was introduced.
import ldc.attributes;
enum OVERRIDE_MEMALLOC = is(typeof(ldc.attributes.weak));
}
else
{
enum OVERRIDE_MEMALLOC = false;
}
static if (OVERRIDE_MEMALLOC)
{
extern (C) void* _d_allocmemory(size_t m_size) nothrow
{
return allocmemory(m_size);
}
extern (C) Object _d_newclass(const ClassInfo ci) nothrow
{
auto p = allocmemory(ci.init.length);
p[0 .. ci.init.length] = cast(void[])ci.init[];
return cast(Object)p;
}
version (LDC)
{
extern (C) Object _d_allocclass(const ClassInfo ci) nothrow
{
return cast(Object)allocmemory(ci.init.length);
}
}
extern (C) void* _d_newitemT(TypeInfo ti) nothrow
{
auto p = allocmemory(ti.tsize);
(cast(ubyte*)p)[0 .. ti.init.length] = 0;
return p;
}
extern (C) void* _d_newitemiT(TypeInfo ti) nothrow
{
auto p = allocmemory(ti.tsize);
p[0 .. ti.init.length] = ti.init[];
return p;
}
}
}