Skip to content
This repository was archived by the owner on Feb 8, 2024. It is now read-only.

Prefer __traits(initSymbol) over TypeInfo.initializer() #201

Merged
merged 2 commits into from
Jun 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/core/demangle.d
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ private struct NoHooks
// static char[] parseType(ref Demangle, char[])
}

version (LDC) private enum isLDC = true;
else private enum isLDC = false;

private struct Demangle(Hooks = NoHooks)
{
// NOTE: This implementation currently only works with mangled function
Expand Down Expand Up @@ -104,7 +107,8 @@ pure @safe:

//throw new ParseException( msg );
debug(info) printf( "error: %.*s\n", cast(int) msg.length, msg.ptr );
throw __ctfe ? new ParseException(msg)
throw __ctfe ? new ParseException(msg) :
isLDC ? cast(ParseException) __traits(initSymbol, ParseException).ptr
: cast(ParseException) cast(void*) typeid(ParseException).initializer;

}
Expand All @@ -116,7 +120,8 @@ pure @safe:

//throw new OverflowException( msg );
debug(info) printf( "overflow: %.*s\n", cast(int) msg.length, msg.ptr );
throw cast(OverflowException) cast(void*) typeid(OverflowException).initializer;
throw isLDC ? cast(OverflowException) __traits(initSymbol, OverflowException).ptr
: cast(OverflowException) cast(void*) typeid(OverflowException).initializer;
}


Expand Down
4 changes: 2 additions & 2 deletions src/core/exception.d
Original file line number Diff line number Diff line change
Expand Up @@ -655,11 +655,11 @@ private T staticError(T, Args...)(auto ref Args args)
else
auto store = &_store;

(*store)[0 .. __traits(classInstanceSize, T)] = typeid(T).initializer[];
return cast(T) store.ptr;
}
auto res = (cast(T function() @trusted pure nothrow @nogc) &get)();
res.__ctor(args);
import core.lifetime : emplace;
emplace(res, args);
return res;
}

Expand Down
9 changes: 2 additions & 7 deletions src/core/internal/container/common.d
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,8 @@ void destroy(T)(ref T t) if (!is(T == struct))

void initialize(T)(ref T t) if (is(T == struct))
{
import core.stdc.string;
static if (__traits(isPOD, T)) // implies !hasElaborateAssign!T && !hasElaborateDestructor!T
t = T.init;
else static if (__traits(isZeroInit, T))
memset(&t, 0, T.sizeof);
else
memcpy(&t, typeid(T).initializer().ptr, T.sizeof);
import core.internal.lifetime : emplaceInitializer;
emplaceInitializer(t);
}

void initialize(T)(ref T t) if (!is(T == struct))
Expand Down
14 changes: 4 additions & 10 deletions src/core/internal/gc/impl/conservative/gc.d
Original file line number Diff line number Diff line change
Expand Up @@ -115,19 +115,13 @@ extern(C) pragma(crt_constructor) void _d_register_precise_gc()

private GC initialize()
{
import core.stdc.string: memcpy;
import core.lifetime : emplace;

auto p = cstdlib.malloc(__traits(classInstanceSize, ConservativeGC));

if (!p)
auto gc = cast(ConservativeGC) cstdlib.malloc(__traits(classInstanceSize, ConservativeGC));
if (!gc)
onOutOfMemoryErrorNoGC();

auto init = typeid(ConservativeGC).initializer();
assert(init.length == __traits(classInstanceSize, ConservativeGC));
auto instance = cast(ConservativeGC) memcpy(p, init.ptr, init.length);
instance.__ctor();

return instance;
return emplace(gc);
}

private GC initialize_precise()
Expand Down
13 changes: 4 additions & 9 deletions src/core/internal/gc/impl/manual/gc.d
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,13 @@ extern(C) pragma(crt_constructor) void _d_register_manual_gc()

private GC initialize()
{
import core.stdc.string: memcpy;
import core.lifetime : emplace;

auto p = cstdlib.malloc(__traits(classInstanceSize, ManualGC));
if (!p)
auto gc = cast(ManualGC) cstdlib.malloc(__traits(classInstanceSize, ManualGC));
if (!gc)
onOutOfMemoryError();

auto init = typeid(ManualGC).initializer();
assert(init.length == __traits(classInstanceSize, ManualGC));
auto instance = cast(ManualGC) memcpy(p, init.ptr, init.length);
instance.__ctor();

return instance;
return emplace(gc);
}

class ManualGC : GC
Expand Down
50 changes: 21 additions & 29 deletions src/core/internal/lifetime.d
Original file line number Diff line number Diff line change
Expand Up @@ -89,44 +89,36 @@ Emplaces T.init.
In contrast to `emplaceRef(chunk)`, there are no checks for disabled default
constructors etc.
+/
template emplaceInitializer(T)
// LDC: simplified via __traits(initSymbol)
void emplaceInitializer(T)(scope ref T chunk) nothrow pure @trusted
if (!is(T == const) && !is(T == immutable) && !is(T == inout))
{
import core.internal.traits : hasElaborateAssign, Unqual;
import core.internal.traits : hasElaborateAssign;

// Avoid stack allocation by hacking to get to the struct/union init symbol.
static if (is(T == struct) || is(T == union))
static if (__traits(isZeroInit, T))
{
pragma(mangle, "_D" ~ Unqual!T.mangleof[1..$] ~ "6__initZ")
__gshared extern immutable T initializer;
import core.stdc.string : memset;
memset(cast(void*) &chunk, 0, T.sizeof);
}

void emplaceInitializer(scope ref T chunk) nothrow pure @trusted
else static if (__traits(isScalar, T) ||
T.sizeof <= 16 && !hasElaborateAssign!T && __traits(compiles, (){ T chunk; chunk = T.init; }))
{
static if (__traits(isZeroInit, T))
{
import core.stdc.string : memset;
memset(cast(void*) &chunk, 0, T.sizeof);
}
else static if (__traits(isScalar, T) ||
T.sizeof <= 16 && !hasElaborateAssign!T && __traits(compiles, (){ T chunk; chunk = T.init; }))
{
chunk = T.init;
}
else static if (__traits(isStaticArray, T))
{
// For static arrays there is no initializer symbol created. Instead, we emplace elements one-by-one.
foreach (i; 0 .. T.length)
{
emplaceInitializer(chunk[i]);
}
}
else
chunk = T.init;
}
else static if (__traits(isStaticArray, T))
{
// For static arrays there is no initializer symbol created. Instead, we emplace elements one-by-one.
foreach (i; 0 .. T.length)
{
import core.stdc.string : memcpy;
memcpy(cast(void*)&chunk, &initializer, T.sizeof);
emplaceInitializer(chunk[i]);
}
}
else
{
import core.stdc.string : memcpy;
const initializer = __traits(initSymbol, T);
memcpy(cast(void*)&chunk, initializer.ptr, initializer.length);
}
}

@safe unittest
Expand Down
17 changes: 15 additions & 2 deletions src/core/lifetime.d
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,19 @@ T emplace(T, Args...)(T chunk, auto ref Args args)
" is abstract and it can't be emplaced");

// Initialize the object in its pre-ctor state
enum classSize = __traits(classInstanceSize, T);
(() @trusted => (cast(void*) chunk)[0 .. classSize] = typeid(T).initializer[])();
version (LDC)
{
() @trusted
{
const initializer = __traits(initSymbol, T);
(cast(void*) chunk)[0 .. initializer.length] = initializer[];
}();
}
else
{
enum classSize = __traits(classInstanceSize, T);
(() @trusted => (cast(void*) chunk)[0 .. classSize] = typeid(T).initializer[])();
}

static if (isInnerClass!T)
{
Expand Down Expand Up @@ -2121,6 +2132,8 @@ private void moveEmplaceImpl(T)(ref T source, ref T target)

static if (__traits(isZeroInit, T))
() @trusted { memset(&source, 0, sz); }();
else version (LDC)
() @trusted { memcpy(&source, __traits(initSymbol, T).ptr, sz); }();
else
{
auto init = typeid(T).initializer();
Expand Down
20 changes: 11 additions & 9 deletions src/core/sync/mutex.d
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,10 @@ class Mutex :
if (pthread_mutex_lock(&m_hndl) == 0)
return;

SyncError syncErr = cast(SyncError) cast(void*) typeid(SyncError).initializer;
version (LDC)
SyncError syncErr = cast(SyncError) __traits(initSymbol, SyncError).ptr;
else
SyncError syncErr = cast(SyncError) cast(void*) typeid(SyncError).initializer;
syncErr.msg = "Unable to lock mutex.";
throw syncErr;
}
Expand Down Expand Up @@ -227,7 +230,10 @@ class Mutex :
if (pthread_mutex_unlock(&m_hndl) == 0)
return;

SyncError syncErr = cast(SyncError) cast(void*) typeid(SyncError).initializer;
version (LDC)
SyncError syncErr = cast(SyncError) __traits(initSymbol, SyncError).ptr;
else
SyncError syncErr = cast(SyncError) cast(void*) typeid(SyncError).initializer;
syncErr.msg = "Unable to unlock mutex.";
throw syncErr;
}
Expand Down Expand Up @@ -345,14 +351,10 @@ unittest
@system @nogc nothrow unittest
{
import core.stdc.stdlib : malloc, free;
import core.lifetime : emplace;

void* p = malloc(__traits(classInstanceSize, Mutex));

auto ti = typeid(Mutex);
p[0 .. ti.initializer.length] = ti.initializer[];

shared Mutex mtx = cast(shared(Mutex)) p;
mtx.__ctor();
auto mtx = cast(shared Mutex) malloc(__traits(classInstanceSize, Mutex));
emplace(mtx);

mtx.lock_nothrow();

Expand Down
7 changes: 3 additions & 4 deletions src/core/thread/fiber.d
Original file line number Diff line number Diff line change
Expand Up @@ -1916,11 +1916,10 @@ private:
import core.stdc.stdlib : malloc;
import core.thread.threadbase : ThreadException;
enum threadExceptionSize = __traits(classInstanceSize, ThreadException);
if (void* p = malloc(threadExceptionSize))
if (auto e = cast(ThreadException) malloc(threadExceptionSize))
{
p[0 .. threadExceptionSize] = typeid(ThreadException).initializer[];
auto e = cast(ThreadException) p;
e.__ctor(
import core.lifetime : emplace;
emplace(e,
"Migrating Fibers between Threads on this platform may lead " ~
"to incorrect thread local variable access. To allow " ~
"migration anyway, call Fiber.allowMigration()");
Expand Down
4 changes: 3 additions & 1 deletion src/core/thread/osthread.d
Original file line number Diff line number Diff line change
Expand Up @@ -2205,7 +2205,9 @@ extern (C) void thread_init() @nogc
status = sem_init( &suspendCount, 0, 0 );
assert( status == 0 );
}
if (typeid(Thread).initializer.ptr)
version (LDC)
_mainThreadStore[] = __traits(initSymbol, Thread)[];
else if (typeid(Thread).initializer.ptr)
_mainThreadStore[] = typeid(Thread).initializer[];
Thread.sm_main = attachThread((cast(Thread)_mainThreadStore.ptr).__ctor());
}
Expand Down
16 changes: 8 additions & 8 deletions src/core/thread/threadbase.d
Original file line number Diff line number Diff line change
Expand Up @@ -569,11 +569,9 @@ package(core.thread):

static void initLocks() @nogc
{
_slock[] = typeid(Mutex).initializer[];
(cast(Mutex)_slock.ptr).__ctor();

_criticalRegionLock[] = typeid(Mutex).initializer[];
(cast(Mutex)_criticalRegionLock.ptr).__ctor();
import core.lifetime : emplace;
emplace!Mutex(_slock[]);
emplace!Mutex(_criticalRegionLock[]);
}

static void termLocks() @nogc
Expand Down Expand Up @@ -769,7 +767,9 @@ package void thread_term_tpl(ThreadT, MainThreadStore)(ref MainThreadStore _main
// destruct manually as object.destroy is not @nogc
(cast(ThreadT) cast(void*) ThreadBase.sm_main).__dtor();
_d_monitordelete_nogc(ThreadBase.sm_main);
if (typeid(ThreadT).initializer.ptr)
version (LDC)
_mainThreadStore[] = __traits(initSymbol, ThreadT)[];
else if (typeid(ThreadT).initializer.ptr)
_mainThreadStore[] = typeid(ThreadT).initializer[];
else
(cast(ubyte[])_mainThreadStore)[] = 0;
Expand Down Expand Up @@ -1334,8 +1334,8 @@ package

void initLowlevelThreads() @nogc
{
ll_lock[] = typeid(Mutex).initializer[];
lowlevelLock.__ctor();
import core.lifetime : emplace;
emplace(lowlevelLock());
}

void termLowlevelThreads() @nogc
Expand Down
12 changes: 10 additions & 2 deletions src/object.d
Original file line number Diff line number Diff line change
Expand Up @@ -4021,8 +4021,16 @@ void destroy(bool initialize = true, T)(T obj) if (is(T == class))

static if (initialize)
{
enum classSize = __traits(classInstanceSize, T);
(cast(void*)obj)[0 .. classSize] = typeid(T).initializer[];
version (LDC)
{
const initializer = __traits(initSymbol, T);
(cast(void*)obj)[0 .. initializer.length] = initializer[];
}
else
{
enum classSize = __traits(classInstanceSize, T);
(cast(void*)obj)[0 .. classSize] = typeid(T).initializer[];
}
}
}
else
Expand Down
5 changes: 4 additions & 1 deletion src/rt/aaA.d
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,10 @@ TypeInfo_Struct fakeEntryTI(ref Impl aa, const TypeInfo keyti, const TypeInfo va
void* p = GC.malloc(sizeti + (2 + rtisize) * (void*).sizeof);
import core.stdc.string : memcpy;

memcpy(p, typeid(TypeInfo_Struct).initializer().ptr, sizeti);
version (LDC)
memcpy(p, __traits(initSymbol, TypeInfo_Struct).ptr, sizeti);
else
memcpy(p, typeid(TypeInfo_Struct).initializer().ptr, sizeti);

auto ti = cast(TypeInfo_Struct) p;
auto extra = cast(TypeInfo*)(p + sizeti);
Expand Down
2 changes: 1 addition & 1 deletion src/rt/sections_elf_shared.d
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ package extern(C) void _d_dso_registry(void* arg)
if (firstDSO) initLocks();

DSO* pdso = cast(DSO*).calloc(1, DSO.sizeof);
assert(typeid(DSO).initializer().ptr is null);
static assert(__traits(isZeroInit, DSO));
pdso._slot = data._slot;
*data._slot = pdso; // store backlink in library record

Expand Down