Make _d_arrayctor and _d_arraysetctor aware of copy constructor#3177
Make _d_arrayctor and _d_arraysetctor aware of copy constructor#3177edi33416 wants to merge 3 commits intodlang:masterfrom
Conversation
|
Thanks for your pull request and interest in making D better, @edi33416! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub run digger -- build "master + druntime#3177" |
55a4f91 to
d3509fa
Compare
72a0b46 to
1b129ea
Compare
| { | ||
| auto elem = cast(Unqual!T*)&to[i]; | ||
| // Copy construction is defined as bit copy followed by postblit. | ||
| memcpy(elem, &from[i], element_size); |
There was a problem hiding this comment.
Not related to this PR, but memcpying each element separately is not optimal, and doesn't exploit the postblit advantage over copy ctors. The loop can additionally be completely elided if the type has no postblit.
There was a problem hiding this comment.
Btw, is this stuff actually used at all? The compiler still lowers to the non-templated extern(C) hook...
Edit: Seems totally unused in 2.093, incl. no usages in druntime/Phobos.
There was a problem hiding this comment.
You are right. This doesn't get lowered to by the compiler.
As you've pointed out, the compiler lowers to the array function from rt.arrayassign.
The course of action going forward is to hook the call to _d_arrayctor in dmd, as @RazvanN7 pointed out.
Before doing so, we'll have to convert _d_arrayassign, _d_arrayassign_l and _d_arrayassign_r to into templates and then change dmd to call the templated versions of _d_arrayassign and the current templated version of _d_arrayctor and their set cousins _d_arraysetctor and _d_arraysetassign
There was a problem hiding this comment.
Not related to this PR, but memcpying each element separately is not optimal, and doesn't exploit the postblit advantage over copy ctors.
I believe the memcpying is done separately so it will be able to correctly destroy previously constructed elements in case a of a throw from the postblit of the current ith element
The loop can additionally be completely elided if the type has no postblit.
I think the memcopying should still be performed.
There was a problem hiding this comment.
When performing a single memcpy, the 'unconstructed' elements >= i will have to be reset (edit: blitted) to T.init in the exception case, yes.
There was a problem hiding this comment.
So you're suggesting that the code should be changed to
try
{
static if (__traits(hasPostblit, T))
{
memcpy(to, from, element_size * to.length);
for (i = 0; i < to.length; i++)
{
auto elem = cast(Unqual!T*)&to[i];
postblitRecurse(*elem);
}
}
else static if (__traits(hasCopyConstructor, T))
{
for (i = 0; i < to.length; i++)
{
to[i].__ctor(from[i]);
}
}
else
{
memcpy(to, from, element_size * to.length);
}
catch (Exception o)
{
/* Destroy, in reverse order, what we've constructed so far
*/
static if (__traits(hasPostblit, T) || !__traits(hasCopyConstructor, T))
{
for (int j = i; j < to.length; j++)
{
auto elem = cast(Unqual!T*)&to[i];
memcpy(elem, &T.init, element_size);
}
}
while (i--)
{
auto elem = cast(Unqual!T*)&to[i];
destroy(*elem);
}
throw o;
}
There was a problem hiding this comment.
Something similar to this, yes. Elements without postblit/cpctor don't need a try/catch, that's a plain memcpy. T.init is an rvalue and cannot be used for memcpy; there's some emplace version blitting the default initializer which can be used - in case the T.init reset is really necessary (the array wasn't successfully constructed, so is it going to be destructed at some point later? have the elements already been initialized with T.init in the first place?).
There was a problem hiding this comment.
I'd keep this as a separate PR in an attempt to keep the changes small
0a67405 to
6ce8fc0
Compare
|
@edi33416 Fix the conflicts and let's merge this! |
6ce8fc0 to
e8e4be6
Compare
|
Looks like this has been implemented in #3239 |
This PR makes the copy construction of arrays aware of the copy constructor.
IMHO, in the long run, this should be used in #3139 and other similar fixes.