On Monday, 11 February 2013 at 06:52:33 UTC, deadalnix wrote:
Ok, We have 2 usages of ref : when you actually need to modify
informations, and for performance reasons. Let's talk about the
second one.
Passing by ref to improve performance is not ideal. First this
is quite hard to know when it is actually faster to pass by ref
and to pass by value, especially in generic code. Secondly it
is easy to forget to use ref at some location, and a lot of
small performance improvement are lost in the process. Finally,
this may be error prone.
I'm thinking about it for a while now and I'm now convinced
that we should allow the compiler to do that job for us. Let me
explain.
When a function accept a struct, the compiler is free to use
that function, or an altered one taking a reference as
parameter. Here are some rules the compiler can use to know
which one to call from callee side :
The caller is free to call the ref version of the function
unless (rules evaluate in order) :
- The argument is an rvalue (in such case, no postblit is
executed as well).
- The argument is shared.
- The argument's postblit in not pure (weakly).
The callee isn't modified for the vanilla function, but must
create a local copy of the argument in the following reasons in
the ref version :
- The argument is binded to a mutable ref.(even as hidden
argument as for member method).
- The argument is actually modified.
- address of anything coming from the struct is taken.
The compiler is free to apply such treatment only in a branch
of the callee, ie :
// Compiler choose to create an alternative ref version for
performance.
void foo(MyStruct s) {
if(condition) {
// Operation require a copy to not alter what the
caller see.
// A s is copied on stack and postblit is called.
s.field = 5;
} else {
// No operation requiring local copy is performed.
// No local copy is created.
}
}
The compiler is however disallowed to create multiple copies in
the callee. If several branches requires it, then the copy have
to be made in a common branch.
Note that the compiler don't HAVE to do this, but is allowed
to. Modifying the spec in such way allow the compiler to avoid
many copies of struct let us get rid of most ref parameters,
keeping them for what they really are for.
EDIT: I forgot one condition for the callee, it is disallowed to
copy the struct or any part of it that contain reference/pointer
is the postblit isn't strongly pure.