About ref used for performance reasons with struct

kinke noone at hotmail.com
Mon Feb 11 06:54:47 PST 2013


+1, I've been thinking about similar concepts as well.

This would be particularly useful for Win64. The Win64 ABI 
requires all structs > 64 bits (or of a size which is not a power 
of 2) to be passed by reference. So if a function foo(BigStruct 
s) is invoked, the caller first allocates a copy of s for the 
callee on its own stack (16-bytes aligned) and then passes the 
callee a pointer to the copy (in a register or on the parameters 
stack), instead of passing a copy of s directly on the parameters 
stack. It seems to me that the whole idea of this is to encourage 
byref passing and copying arguments only if required, otherwise 
it doesn't make much sense performance-wise (higher stack memory 
usage due to the additional pointer and need for dereferencing 
the pointer parameter).

I'd propose a small change so that suited structs are passed 
transparently byref only if the parameter is not mutable, e.g., 
for a function foo(const BigStruct s). The compiler would 
therefore not need to analyze the code flow in the callee to 
determine if the parameter is modified and hence a copy is needed.

The compiler would nevertheless need to be quite smart though:

---
struct MyBigStruct { double a, b, c; }
double foo(const MyBigStruct s, double* x)
{
     *x = s.a;
     return s.b;
}
// naive optimization by byref passing
double foo_ref(const ref MyBigStruct s, double* x)
{
     *x = s.a;
     return s.b;
}

MyBigStruct s = { 1, 2, 3 };
double* x = &s.b;
auto bla = foo(s, x); // returns 2; now s.b = 1
s.b = 2;              // reset s.b to 2
bla = foo_ref(s, x);  // returns 1! (the new s.b = 1)
---

So the compiler would need to prove there is no way the argument 
can be modified and handle tricky aliasing issues accordingly.


More information about the Digitalmars-d mailing list