Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
April 24, 2013 Postblit isn't called on rvalue return | ||||
---|---|---|---|---|
| ||||
For this program: import std.stdio; struct S { ubyte* b; ubyte buf[128]; this(this) { writeln("postblit"); } } auto ref makeS() { S s; s.b = s.buf; writeln("made S at ", cast(void*)&s, ", s.b == ", s.b); return s; } void main() { S s = makeS(); writeln("got back S at ", cast(void*)&s, ", s.b == ", s.b); } I get made S at 18FC64, s.b == 18FC68 got back S at 18FCF4, s.b == 18FC68 as output for dmd 2.062. Patching s.b to point into the newly allocated struct in postblit is crucial here, but it seems like the postblit constructor isn't called, nor is there any attempt to optimize away the temporary in `makeS()` even with -O. Is this is a bug or am I doing something wrong? |
April 24, 2013 Re: Postblit isn't called on rvalue return | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sebastian Graf | On Wednesday, 24 April 2013 at 11:42:01 UTC, Sebastian Graf wrote:
> For this program:
>
> import std.stdio;
>
> struct S
> {
> ubyte* b;
> ubyte buf[128];
>
> this(this)
> {
> writeln("postblit");
> }
> }
>
> auto ref makeS()
> {
> S s;
> s.b = s.buf;
> writeln("made S at ", cast(void*)&s, ", s.b == ", s.b);
> return s;
> }
>
> void main()
> {
> S s = makeS();
> writeln("got back S at ", cast(void*)&s, ", s.b == ", s.b);
> }
>
> I get
>
> made S at 18FC64, s.b == 18FC68
> got back S at 18FCF4, s.b == 18FC68
>
> as output for dmd 2.062. Patching s.b to point into the newly allocated struct in postblit is crucial here, but it seems like the postblit constructor isn't called, nor is there any attempt to optimize away the temporary in `makeS()` even with -O.
> Is this is a bug or am I doing something wrong?
First, as the local 's' in makeS() is local, it cannot be returned by ref. So, the 'auto ref' return type of makeS() becomes by-value.
However, rvalues are never copied in D. The compiler automatically moves the bits of the rvalue to the left-hand side object, and to be correct, it also elides the destructor execution on the rvalue. (Note that this is not the RVO and NRVO optimization that C++ "allows". This is a language feature in D.)
For that feature to be available at all, struct objects must not have references to themselves; D explicitly makes it illegal.
So, unfortunately your S is not a valid type in D because of the following line (.ptr is added by me):
s.b = s.buf.ptr;
Ali
|
April 24, 2013 Re: Postblit isn't called on rvalue return | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Wednesday, 24 April 2013 at 20:53:11 UTC, Ali Çehreli wrote: > > First, as the local 's' in makeS() is local, it cannot be returned by ref. So, the 'auto ref' return type of makeS() becomes by-value. > > However, rvalues are never copied in D. The compiler automatically moves the bits of the rvalue to the left-hand side object, and to be correct, it also elides the destructor execution on the rvalue. (Note that this is not the RVO and NRVO optimization that C++ "allows". This is a language feature in D.) > > For that feature to be available at all, struct objects must not have references to themselves; D explicitly makes it illegal. > > So, unfortunately your S is not a valid type in D because of the following line (.ptr is added by me): > > s.b = s.buf.ptr; > > Ali Thanks, this explains a lot. I was interfacing with a C library when tracing back an error to this. I eagerly submitted a Bug report http://d.puremagic.com/issues/show_bug.cgi?id=9985. Seems to me that dmd doesn't do NRVO (?), see the issue. |
April 24, 2013 Re: Postblit isn't called on rvalue return | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sebastian Graf | On Wednesday, 24 April 2013 at 21:36:48 UTC, Sebastian Graf wrote: > Seems to me that dmd doesn't do NRVO (?), see the issue. I can see that NRVO would be faster than the extra bit-copy. Especially the last one of the following set of blog posts is relevant. The posts explain the rationale for this design decision (I don't remember whether they provide an exact answer to your question): http://bartoszmilewski.com/2008/10/18/who-ordered-rvalue-references-part-1/ http://bartoszmilewski.com/2008/10/26/who-ordered-rvalue-references-part-2/ http://bartoszmilewski.com/2008/11/03/who-ordered-rvalue-references-part-3/ Ali |
April 25, 2013 Re: Postblit isn't called on rvalue return | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Wednesday, 24 April 2013 at 22:29:55 UTC, Ali Çehreli wrote:
> On Wednesday, 24 April 2013 at 21:36:48 UTC, Sebastian Graf wrote:
>
>> Seems to me that dmd doesn't do NRVO (?), see the issue.
>
> I can see that NRVO would be faster than the extra bit-copy.
>
> Especially the last one of the following set of blog posts is relevant. The posts explain the rationale for this design decision (I don't remember whether they provide an exact answer to your question):
>
> http://bartoszmilewski.com/2008/10/18/who-ordered-rvalue-references-part-1/
>
> http://bartoszmilewski.com/2008/10/26/who-ordered-rvalue-references-part-2/
>
> http://bartoszmilewski.com/2008/11/03/who-ordered-rvalue-references-part-3/
>
> Ali
They did. Thanks for this awesome read :)
|
Copyright © 1999-2021 by the D Language Foundation