Escape analysis

Walter Bright newshound1 at digitalmars.com
Tue Oct 28 12:38:38 PDT 2008


Steven Schveighoffer wrote:
> "Walter Bright" wrote
>> The reason the scope/noscope needs to be part of the function signature is 
>> because:
>>
>> 1. that makes it self-documenting
> 
> But the documentation is not enough.  You cannot express the intricacies of 
> what variables are scope escapes so that the compiler can make intelligent 
> enough decisions.  What this will result in is slightly less unnecessary 
> closures, but not enough to make a difference.  Or else you won't be able to 
> declare things the way you want, so you will be forced to declare something 
> that *could* result in an escape, but usually doesn't.

I think it is conceptually straightforward whether a reference escapes 
or not, though it is difficult for the compiler to detect it reliably.

>> 2. function bodies may be external, i.e. not present
>> 3. virtual functions
> 
> Yes, so you are now implying a scope escape contract on all derived classes. 
> But not a very expressive one.
> 
>> 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.

First off, the mangled names will be different, so it won't link until 
you recompile. This is critical because the caller's code depends on the 
scope/noscope characteristic.

Secondly, passing a scoped reference to a noscope parameter should be a 
compile time error.

> 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).

Having the caller specify it is not tenable, because the caller has no 
control over (and likely no knowledge of) what the callee does. 
Functions should be regarded as black boxes, where all you can know 
about them is in the function signature.

> 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,

Then it's noscope.

> but how do we know what the 
> scope of the class instance is to know if newV truly escapes its own scope?

We take the conservative approach, and regard "might escape" and "don't 
know if it escapes" as "treat as if it does escape".



More information about the Digitalmars-d mailing list