www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Postblit isn't called on rvalue return

reply "Sebastian Graf" <SebastianGraf t-online.de> writes:
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?
Apr 24 2013
parent reply "Ali =?UTF-8?B?w4dlaHJlbGki?= <acehreli yahoo.com> writes:
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
Apr 24 2013
parent reply "Sebastian Graf" <SebastianGraf t-online.de> writes:
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.
Apr 24 2013
parent reply "Ali =?UTF-8?B?w4dlaHJlbGki?= <acehreli yahoo.com> writes:
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
Apr 24 2013
parent "Sebastian Graf" <SebastianGraf t-online.de> writes:
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 :)
Apr 25 2013