Skip to content

Commit eaf2769

Browse files
authored
Update _d_arrayctor branches to improve performance (#21675)
1 parent f9da382 commit eaf2769

2 files changed

Lines changed: 45 additions & 8 deletions

File tree

druntime/src/core/internal/array/construction.d

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* ma
6565

6666
enforceRawArraysConformable("initialization", T.sizeof, vFrom, vTo);
6767

68-
static if (hasElaborateCopyConstructor!T)
68+
static if (__traits(hasCopyConstructor, T))
6969
{
7070
size_t i;
7171
try
@@ -88,8 +88,30 @@ Tarr _d_arrayctor(Tarr : T[], T)(return scope Tarr to, scope Tarr from, char* ma
8888
}
8989
else
9090
{
91-
// blit all elements at once
92-
memcpy(cast(void*) to.ptr, from.ptr, to.length * T.sizeof);
91+
if (to.length)
92+
{
93+
// blit all elements at once
94+
memcpy(cast(void*) to.ptr, from.ptr, to.length * T.sizeof);
95+
96+
// call postblits if they exist
97+
static if (__traits(hasPostblit, T))
98+
{
99+
import core.internal.lifetime : __doPostblit;
100+
size_t i = 0;
101+
try __doPostblit(to, i);
102+
catch (Exception o)
103+
{
104+
// Destroy, in reverse order, what we've constructed so far
105+
while (i--)
106+
{
107+
auto elem = cast(Unqual!T*) &to[i];
108+
destroy(*elem);
109+
}
110+
111+
throw o;
112+
}
113+
}
114+
}
93115
}
94116

95117
return to;

druntime/src/core/internal/lifetime.d

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,14 +210,29 @@ void __doPostblit(T)(T[] arr)
210210
{
211211
static if (__traits(isStaticArray, T) && is(T : E[], E))
212212
__doPostblit(cast(E[]) arr);
213-
else static if (!__traits(compiles, arr[0].__xpostblit))
213+
else
214214
{
215-
alias Unqual_T = Unqual!T;
216-
foreach (ref elem; (() @trusted => cast(Unqual_T[]) arr)())
215+
import core.internal.traits : Unqual;
216+
foreach (ref elem; (() @trusted => cast(Unqual!T[]) arr)())
217217
elem.__xpostblit();
218218
}
219+
}
220+
}
221+
222+
// ditto, but with an index to keep track of how many elements have been postblitted
223+
void __doPostblit(T)(T[] arr, ref size_t i)
224+
{
225+
// infer static postblit type, run postblit if any
226+
static if (__traits(hasPostblit, T))
227+
{
228+
static if (__traits(isStaticArray, T) && is(T : E[], E))
229+
__doPostblit(cast(E[]) arr, i);
219230
else
220-
foreach (ref elem; arr)
221-
elem.__xpostblit();
231+
{
232+
i = 0;
233+
import core.internal.traits : Unqual;
234+
for(auto eptr = cast(Unqual!T*)&arr[0]; i < arr.length; ++i, ++eptr)
235+
eptr.__xpostblit();
236+
}
222237
}
223238
}

0 commit comments

Comments
 (0)