[Mono-dev] CIL to CIL optimizer

Bjarke Hammersholt Roune bjarke.roune at gmail.com
Thu Aug 10 08:40:36 EDT 2006


Zoltan Varga skrev:
 >                                      Hi,
 >
 >   What is the problem with try-finally ? There are two cases:
 > - if there is an exception, the runtime will call it, just with the 
catch clause
 > - if there is no exception, control flow just falls from the end of
 > the try block to
 > the beginning of the finally block. This is just a normal control 
flow edge.
 >
The problem is that what happens after the finally block is done depends 
on the context that caused it to run. Here is a simple example in pseudo 
code:

	try {
		if (a) {
A:			x = 2;
			goto E;
		}
B:		x = 1;
	} finally {
C:		print "hello world!";
	}
D:	print x;
E:	return

Imagine a control flow graph of this code with the labels naming the 
nodes. Then there will be edges A->C, B->C, C->D, C->E and D->E. The 
definition of x that reaches D will thus have to go through C, and then 
C will need a phi-function to get the correct definition of x. This will 
make it look like the definition of x from A is needed at C, even though 
obviously it is not. The basic problem is that the control flow graph 
makes it look like the path A->C->D is possible. In this example this 
means that we cannot discover that x=2 is dead code.

Suppose that the x=2 at A was something throwing an exception instead 
and we had a catch handler on the innermost try. Then C would need an 
outgoing edge to this handler, making it look like falling through at B 
could cause an exception!

So if we don't do something special for finally, we can get preposterous 
  information. I should perhaps say that I am interested in precise 
analysis to do good optimization, but also because I would like the 
program to have capabilities similar to the Java findbugs program, 
though that would not be a priority at first.

I am sure this CAN be fixed for each analysis by doing the equivalent of 
path sensitive analysis but restricting it to finally. Basically this 
will be the same thing as making the analysis act as if the finally 
block was inlined everywhere it could be called, but without actually 
inlining it. I am not sure how that should interact with SSA-form.

Even if we use the naive approach the control flow graph will need to 
know that removing an edge TO a finally block might or might not 
necessitate removing an edge FROM it, depending on whether or not a 
different branch from inside the corresponding try block has another 
branch that needs to go the same outer destination. If that does not 
make sense consider removing the last branch to a label outside a 
finally-protected try block as compared to removing one of several 
branches that all go to the same label outside the try block.

I expect to discover more of these kinds of differences from normal 
control flow graph behavior as implementation proceeds, since finally 
directs control flow in a different way from anything else.

I hope I have convincingly argued that finally needs special treatment 
and that that treatment is non-trivial if we need reasonably precise 
analysis of program behavior.

/Bjarke



More information about the Mono-devel-list mailing list