On Monday, 15 May 2017 at 23:10:00 UTC, ag0aep6g wrote:
On 05/15/2017 11:56 PM, Jonathan Marler wrote:
your proposal would require every function to use the same ABI
as it's
delegate counterpart, which includes the code to unwind the
stack if the
context pointer was passed in there or any extra setup code in
the caller.
I don't see how that's true. Stack cleanup of the context
pointer would be done in the caller, not the callee. And no
extra setup (or cleanup) is needed in the caller when the
callee is a non-delegate function.
And that's the point. The goal is to keep normal, non-delegate
function calls exactly as they are. That's why the context
pointer is passed in a spot where it doesn't affect the rest of
the call (i.e. in a free register or before the other args on
the stack).
If this proposal was integrated I could also imagine
applications
wanting to create functions that are not delegate compatible
so they
don't have to incur the delegate ABI overhead, i.e.
There should be zero overhead.
[...]
In short, this proposal modifies existing the function ABI to
use the
delegate ABI which will have a runtime cost in the general
case (even
though some cases may have zero cost).
No. At least, that's not how it's supposed to work. The idea is
to modify the delegate ABI to be compatible with the function
ABI. I wouldn't touch the function ABI.
Every call to a delegate would contain code that's exactly the
same as a call to a non-delegate function with the same visible
parameters. That piece of code would look the same as it does
today.
For example, if `f(1, 2);` results in machine code `foo` today,
then `void delegate(int, int) dg = &f; dg(1, 2);` would be made
to result in
mov parameter_register_not_used_in_foo, context_pointer;
foo;
or if `foo` already uses all registers
push context_pointer;
foo;
pop;
If this doesn't work for some specific `foo`, I'd appreciate an
example where it falls apart.
It doesn't work with `extern(C++)` methods, because we have to
follow established calling conventions and put the `this`
pointer somewhere else. So, implicit conversion wouldn't work
here. That's ok.
I suspect that variadic functions might also be problematic.
But I haven't checked, because I don't care much about them.
Worst case, you can't implicitly convert a variadic function to
a variadic delegate. Not a big issue.
Ok I got your proposal backwards. Now that I understand I think
it's worth looking into. The obvious questions would be the
practical performance implications of changing how the context
pointer is passed in, and also how close the current delegate ABI
is to working with this. I'm not alot of help here so I hope
others respond.
It adds some restriction to the delegate ABI that didn't exist
before so the next question would be is the decrease in ABI
flexibility going to be an issue? Some platforms may have very
fast ways of passing the context pointer that aren't compatible
with these restrictions in which case D
delegates/member-functions would have to use an inferior ABI by
default. That could be addressed by adding something like
"extern(optimized)" that allows the ABI to be flexible at the
cost of being incompatible with a function pointer.
An interesting idea, it's sort of the reverse of my proposal
hence why I was making the bad assumptions. Will wait to hear
others thoughts.