Bug 11394 – NRVO should work for object field initialization in constructor
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-10-30T19:18:00Z
Last change time
2013-11-08T00:57:24Z
Keywords
pull, wrong-code
Assigned to
nobody
Creator
k.hara.pg
Comments
Comment #0 by k.hara.pg — 2013-10-30T19:18:09Z
Spin-off issue from http://d.puremagic.com/issues/show_bug.cgi?id=11343#c15
At the line 18, NRVO should work, then p1, p2, p3 should print same address.
extern(C) int printf(const char*, ...);
static int[3] make(in int x, out const(int)* p) pure
{
typeof(return) a;
a[0] = x;
a[1] = x + 1;
a[2] = x + 2;
p = a.ptr;
return a;
}
struct Bar
{
immutable int[3] arr;
this(int x, out const(int)* p2)
{
const(int)* p1;
this.arr = make(x, p1); // Line 18: NRVO should work
p2 = this.arr.ptr;
printf("p1 = %p\np2 = %p\n", p1, p2);
//assert(p1 == p2);
}
}
void main()
{
const(int)* p2;
auto b = Bar(5, p2);
const(int)* p3 = b.arr.ptr;
printf("p3 = %p\n", p3);
//assert(p2 == p3);
}
Comment #1 by k.hara.pg — 2013-11-01T09:05:53Z
Sorry the OP code is incorrect, because the make function cannot have strong purity.
Correct test case is:
debug = NRVO;
debug(NRVO) static void* pa, pb, pc;
static int[3] make(in int x) pure
{
typeof(return) a;
a[0] = x;
a[1] = x + 1;
a[2] = x + 2;
debug(NRVO) pa = cast(void*)a.ptr;
return a;
}
struct Bar
{
immutable int[3] arr;
this(int x)
{
this.arr = make(x); // NRVO should work
debug(NRVO) pb = cast(void*)this.arr.ptr;
}
}
void main()
{
auto b = Bar(5);
debug(NRVO) pc = cast(void*)b.arr.ptr;
debug(NRVO) assert(pa == pb);
debug(NRVO) assert(pb == pc);
}
Comment #4 by bearophile_hugs — 2013-11-08T00:57:24Z
(In reply to comment #3)
> Commit pushed to master at https://github.com/D-Programming-Language/dmd
>
> https://github.com/D-Programming-Language/dmd/commit/6f80983044a55580e81e7f723e5b71f05650caa4
> fix Issue 11394 - NRVO should work for object field initialization in
> constructor
The asm of two constructors isn't equal, but the situation has improved and now there is no call to the array copy:
import std.traits: Unqual;
struct Foo {
int[3] arr;
this(int x) pure nothrow {
arr[0] = x;
arr[1] = x + 1;
arr[2] = x + 2;
}
}
struct Bar {
immutable int[3] arr;
this(int x) pure nothrow {
static Unqual!(typeof(arr)) make(in int x)
pure nothrow {
typeof(return) a;
a[0] = x;
a[1] = x + 1;
a[2] = x + 2;
return a;
}
this.arr = make(x); // NRVO works?
}
}
void main() {
auto f = Foo(5);
auto b = Bar(5);
}
Foo.__ctor:
push EBX
mov EDX, EAX
mov EBX, 8[ESP]
push ESI
lea ECX, 1[EBX]
lea ESI, 2[EBX]
mov [EDX], EBX
mov 4[EDX], ECX
mov 8[EDX], ESI
pop ESI
pop EBX
ret 4
Bar.__ctor:
push EBX
mov EBX, 8[ESP]
xor ECX, ECX
push ESI
mov EDX, EAX
lea ESI, 1[EBX]
push EDI
lea EDI, 2[EBX]
mov [EAX], ECX
mov 4[EAX], ECX
mov 8[EAX], ECX
mov [EDX], EBX
mov 4[EDX], ESI
mov 8[EDX], EDI
pop EDI
pop ESI
pop EBX
ret 4