Escape analysis (full scope analysis proposal)

Robert Jacques sandford at jhu.edu
Wed Oct 29 12:10:00 PDT 2008


On Wed, 29 Oct 2008 07:28:55 -0400, Michel Fortin  
<michel.fortin at michelf.com> wrote:

> On 2008-10-28 23:52:04 -0400, "Robert Jacques" <sandford at jhu.edu> said:
>
>> I've run across some academic work on ownership types which seems  
>> relevant  to this discussion on share/local/scope/noscope.
>
> I haven't read the paper yet, but the overview seems to go in the same  
> direction as I was thinking.
>
> Basically, all the scope variables you can get are guarentied to be in  
> the current or in some ansestry scope. To allow a reference to a scope  
> variable, or a scope function, to be put inside a member of a struct or  
> class, you only need to prove that the struct or class lifetime is  
> smaller or equal to the one of the reference to your scope variable. If  
> you could tell to the compiler the scope relationship of the various  
> arguments, then you'd have pretty good scope analysis.
>
> For instance, with this syntax, we could define i to be available during  
> the whole lifetime of o:
>
> 	void foo(scope MyObject o, scope(o) int* i)
> 	{
> 		o.i = i;
> 	}

What does the scope part of 'scope MyObject o' mean? (i.e. is this D's  
current scope or something else?)
What does 'scope(o)' explicitly mean? I'm going to assume scope(o) means  
the scope of o.

> So you could do:
>
> 	void bar()
> 	{
> 		scope int i;
> 		scope MyObject o = new MyObject;
> 		foo(o, &i);
> 	}
>
> And the compiler would let it pass because foo guarenties not to keep  
> references to i outside of o's scope, and o's scope is the same as i.
>
> Or you could do:
>
> 	void test1()
> 	{
> 		int i;
> 		test2(&i);
> 	}
>
> 	void test2(scope int* i)
> 	{
> 		scope o = new MyObject;
> 		foo(o, &i);
Error: &i is of type int** while foo takes a int*. Did you mean foo(o, i)?

> 	}
>
> Again, the compiler can statically check that test2 won't keep a  
> reference to i outside of the caller's scope (test1) because o scope is  
> limited to test2.

The way I read your example, no useful escape analysis can be done by the  
complier, and it works mainly because i is a pointer to a value type.

> And if you try the reverse:
>
> 	void test1()
> 	{
> 		scope o = new MyObject;
> 		test2(o);
> 	}
>
> 	void test2(scope MyObject o)
> 	{
> 		int i;
> 		foo(o, &i);
> 	}
>
> Then the compiler could determine automatically that i needs to escape  
> test2's scope and allocate the variable on the heap to make its lifetime  
> as long as the object's scope (as it does currently with nested  
> functions) [see my reserves to this in post scriptum]. This could be  
> avoided by explictly binding i to the current scope, in which case the  
> compiler could issue a scope error:

The way I read this is o is of type scope MyObject, i is of type scope int  
and therefore foo(o,&i) is valid and an escape happens.





More information about the Digitalmars-d mailing list