On 8/2/18 12:21 PM, Jonathan Marler wrote:
On Monday, 30 July 2018 at 21:02:56 UTC, Steven Schveighoffer wrote:
Would it be a valid optimization to have D remove the requirement for
allocation when it can determine that the entire data structure of the
item in question is an rvalue, and would fit into the data pointer
part of the delegate?
Here's what I'm looking at:
auto foo(int x)
{
return { return x + 10; };
}
In this case, D allocates a pointer on the heap to hold "x", and then
return a delegate which uses the pointer to read x, and then return
that plus 10.
However, we could store x itself in the storage of the pointer of the
delegate. This removes an indirection, and also saves the heap
allocation.
Think of it like "automatic functors".
Does it make sense? Would it be feasible for the language to do this?
The type system already casts the delegate pointer to a void *, so it
can't make any assumptions, but this is a slight break of the type
system.
The two requirements I can think of are:
1. The data in question must fit into a word
2. It must be guaranteed that the data is not going to be mutated
(either via the function or any other function). Maybe it's best to
require the state to be const/immutable.
I've had several cases where I was tempted to not use delegates
because of the allocation cost, and simply return a specialized
struct, but it's so annoying to do this compared to making a delegate.
Plus something like this would be seamless with normal delegates as
well (in case you do need a real delegate).
I think the number of cases where you could optimize this is very
small. And the complexity of getting the compiler to analyze cases to
determine when this is possible would be very large.
It's not that complicated, you just have to analyze how much data is
needed from the context inside the delegate. First iteration, all of the
data has to be immutable, so it should be relatively straightforward.
In addition, a developer can already do this explicitly if they want, i.e.
auto foo(int x)
{
static struct DummyStructToMakeFunctionWithDelegateAbi
{
int passthru() const { return cast(int)&this; }
}
DummyStructToMakeFunctionWithDelegateAbi dummyStruct;
auto dg = &dummyStruct.passthru;
dg.ptr = cast(void*)(x + 10); // treat the void* pointer as an int
value
return dg;
}
Yep, just make that dummyStruct static or else it will allocate, and it
should work. The concern I have with doing it this way is all the
breakage of the type system.
-Steve