Escape analysis (full scope analysis proposal)
Michel Fortin
michel.fortin at michelf.com
Thu Oct 30 05:14:53 PDT 2008
On 2008-10-29 11:01:35 -0400, "Steven Schveighoffer"
<schveiguy at yahoo.com> said:
> This is exactly the kind of thing I DON'T want to have. Here, you have to
> specify everything, even though the compiler is also doing the work, and
> making sure it matches. Tack on const modifiers, shared modifiers, and pure
> functions and there's going to be more decorations on function signatures
> than there are parameters.
I agree that this is becomming a problem, even without scope. What we
need is good defaults so that you don't have to decorate most of the
time, and especially when you want to bypass it.
I'd also like to point out that beside the possibility of better
optimization and error catching by the compiler, specifying more
properties function interfaces can free us of handling other releated
things. With "immutable" values you don't need to worry about
duplicating them everywhere to avoid other references from changing it;
with "shared", you'll have less to worry about thread synchronization;
and with "scope" as I proposed, you no longer have to worry about
providing variables with the correct scope as the compiler can
dynamically allocate when it sees the variable is needed outside of the
current scope.
Basically, by documenting better the interfaces in a machine-readable
way, we are freed of other burdens the compiler can now take care of.
In addition, we have better defined interfaces and the compiler has a
lot more room to optimize things.
> Note that especially this scope stuff will be required more often than the
> others.
Indeed.
> I'd much rather have either no checks, or have the compiler (or a lint tool)
> do all the work to tell me if anything escapes.
The problem is that as soon as you have a function declaration without
the body, the lint tool won't be able to tell you if it escapes or not.
So, without a way to specify the requested scope of the parameters,
you'll very often have holes in your escape analysis that will
propagate down the caller chain, preventing any useful conclusion.
For instance:
void foo()
{
char[5] x = ['1', '2', '3', '4', '\0'];
bar(x);
}
void bar(char* x)
{
printf(x);
}
void printf(char* x);
Here you have no specification telling you that printf won't keep a
reference to x beyond its scope, so we have to expect that it may do
so. Turns out that because of that, a compiler or lit tool can't deduce
if bar may or not leak the reference beyond its scope, which basically
mean that calling bar(x) in foo may or may not be safe. With my
proposal, it'd become this:
void foo()
{
char[5] x = ['1', '2', '3', '4', '\0'];
bar(x.ptr);
}
void bar(scope char* x)
{
printf(x);
}
void printf(scope char* x);
And here the compiler, or the lint tool, can see that x doesn't need to
live outside of foo's scope and that all is fine. If bar decided to
keep the pointer in a global variable for further use, then the
function signature would have a noscope x or the assignment to a global
wouldn't work, and once bar has a noscope argument then foo won't
compile unless x is allocated on the heap.
I don't think it's bad to force interfaces to be well documented, and
documented in a format that the compiler can understand to find errors
like this.
--
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/
More information about the Digitalmars-d
mailing list