Escape analysis

Steven Schveighoffer schveiguy at yahoo.com
Tue Oct 28 06:44:28 PDT 2008


"Robert Jacques" wrote
> On Tue, 28 Oct 2008 08:58:18 -0400, Steven Schveighoffer 
> <schveiguy at yahoo.com> wrote:
>> "Walter Bright" wrote
>>> 4. notifies the user if a library function parameter scope-ness changes
>>> (you'll get a compile time error)
>>
>> Oh really?  I imagined that if the scope-ness changed it just results in 
>> a
>> new heap allocation when I call the function.
>>
>> i.e.  Joe library developer has this function foo:
>>
>> int foo(scope int *x) {return *x;}
>>
>> And he now decides he wants to change it somehow:
>>
>> int *lastFooCalledWith;
>> int foo(int *x) {lastFooCalledWith = x; return *x;}
>>
>> I used foo like this:
>>
>> int i;
>> auto j = foo(&i);
>>
>> So does this now fail to compile?  Or does it silently kill the 
>> performance
>> of my code?
>>
>> If the latter, we are left with the same problem we have now.
>>
>> If the former, how does one call a function with a noscope parameter?
>>
>> The more I think about this, the more I'd rather have D1 behavior and 
>> some
>> sort of way to indicate my function should allocate a heap frame (except 
>> on
>> easily provable scope escapes).
>>
>> The most common case I think which will cause unnecessary allocations, 
>> is a
>> very common case.  A class setter:
>>
>> class X
>> {
>>    private int *v_;
>>    int *v(int *newV) {return v_ = newV;}
>>    int *v() { return v_;}
>> }
>>
>> Clearly, newV escapes into the class instance, but how do we know what 
>> the
>> scope of the class instance is to know if newV truly escapes its own 
>> scope?
>
> Escape analysis also applies to shared/local/scope storage types and not 
> just delegates. Consider having to write a function for every combination 
> of shared/local/scope for every object or pointer in the function 
> signature.

shared/unshared is not a storage class, it is a type modifier (like const). 
But in any case, shared is much easier to define.  Only one line needs to be 
checked -- is this accessible by another thread or not.  Since it is a type 
modifier, it's carried around for every reference to shared data, and you 
can easily do escape analysis there.

Scope is much more difficult because there are many scopes to consider. 
It's not just global or not global, you have a scope for each function, a 
scope for each set of braces within a function, and there is no easy way to 
say which scope you are referring to when you say a variable is scope.  If 
you can only refer to the current scope, then you have not solved the 
closure problem, and useful escape analysis is impossible beyond simply 'a 
pointer to a variable I declared in this scope is being returned.'

In order for escape analysis to be useful, I need to be able to specify in a 
function such as:

void foo(int *x, int **y, int **z)

That x might escape to y's or z's scope.  How do you do allow that 
specification without making function signatures dreadfully complicated?

-Steve 





More information about the Digitalmars-d mailing list