[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Options for replacing use of UnitGraph() constructor (continued)



(This is the question where I solicit input from people who 
know how VMs should interpret the Java specification.)

    vranganath> So, what is the meaning of unit graph in the
    vranganath> situation when a unchecked exception is thrown
    vranganath> after the execution of the following statement
    vranganath> and omitExceptionalEdges is true.

    vranganath>      try {
    vranganath> 	b = 5;  //1
    vranganath> 	a = b + c; //2
    vranganath>          //3
    vranganath>      } catch (Throwable e) {
    vranganath> 	print a; //4
    vranganath>      }

    vranganath> Clearly the 2 has no side-effect. It has the
    vranganath> effect of setting a. (Or do you consider the
    vranganath> latter as side-effect?)  Similarly 1.  Now
    vranganath> clearly, a can be set at when control reaches 4
    vranganath> if the async exception happens after a is
    vranganath> assinged b+c but before 2 completes.  This is
    vranganath> possible according to JVM spec quoted below (JVM
    vranganath> 1ed 2.15.2)

    vranganath> "Java permits a small but bounded amount of
    vranganath> execution to occur before an asynchronous
    vranganath> exception is thrown.  This dealy is permitted to
    vranganath> allow optimized code to detect and throw these
    vranganath> exceptions at points where it is practical to
    vranganath> handle them while obeying the semantics of Java
    vranganath> language."

You're correct, ExceptionalUnitGraph's constructor does not
consider 2 to have a side effect.  I do not think it is clear
that 'a' may be set when control reaches 4 (unless there is some
code elided on line 3), though I agree with you that the
specification might allow that interpretation. Hence my appeal
for specification lawyers. More later.

    vranganath> So, 2 "excepted" but no edges are added in the
    vranganath> graph according to the javadocs of
    vranganath> ExceptionalUnitGraph when
    vranganath> omitExceptionalUnitEdges is true.

    vranganath> "omitExceptingUnitEdges - indicates whether the
    vranganath> CFG should omit edges to a handler from trapped
    vranganath> Units which may throw an exception which the
    vranganath> handler catches but which have no potential side
    vranganath> effects."

Again, your description of how ExceptionalUnitGraph would treat
this example is accurate.

    vranganath> and so the data flow analyses gives incorrect
    vranganath> result by claiming the assignment to a at 2 is
    vranganath> invisible at 4.

    vranganath> If the above analysis is correct, then all units
    vranganath> protected by an async exception catch block
    vranganath> should have an outgoing exceptional edge to the
    vranganath> corresponding handler.  This is not true for sync
    vranganath> exceptions.  So, shouldn't the logic distinguish
    vranganath> between exception sorts while pruning the edges
    vranganath> in the CFG?

That's a good point and I'm glad you raised it, since I didn't
think of the special case of asynchronous exceptions myself.
Nevertheless, the current behaviour of ExceptionalUnitGraph can
be considered correct even in the light of section 2.15.2 of the
specification. It depends on how you split the hairs.

First, note that because the issue only arises in the case of
asynchronous exceptions, the only units affected are those which
are

  a) protected by a handler which catches some asynchronous
     exception type, and

  b) have no successors which are themselves in the scope of
     the same handler.

If the unit (let's call it x) does have a successor in the scope
of the same handler (call the successor y and the handler h),
then y can also throw exceptions to h (since any unit
can throw any asynchronous exception). Then ExceptionalUnitGraph
will add a CFG edge from x to h because x is a predecessor of y.

So, under what circumstances might x throw an asynchronous
exception to h without having any successors that do as well?  In
the case where x is an unconditional branch whose target is
outside of the protected area, or if x is the last unit in the
protected area. Let's modify the example to have one example of
each possibility.

    try {
        if (moon == FULL) {		//0
	  e = 0;		        //1
	  goto unprotected_target	//2
        }
     	b = 5;				//3
     	a = b + c;			//4
	d = a / 2;			//5
      } catch (Throwable e) {
     	print e,b,a,d;			//6
    }

As you point out, a condition corresponding to an asynchronous
exception can occur at any point during the execution of this
code, and the VM can opt to delay delivering the exception until
it reaches a program point after that which was executing when
the exceptional condition arose.  

ExceptionalUnitGraph will create CFG edges from lines 0, 1, 3,
and 4 to line 6 because each of those instructions have
successors which may throw a asynchronous exception that 6
catches.  So the graph will indicate that at line 6, each of
variables e, b, and a may or may not have been assigned a new
value.  

You're suggesting that there should also be an edge from 5 to 6
to indicate that d may have been assigned a new value when
control reaches line 6. To indicate why I think that
interpretation of the specification is incorrect, let's look at
the case of line 2 first.

Let's say an asynchronous error condition arises before line 2 is
executed, but the VM does not deliver it until after line 2 is
executed. In that case, control will have passed to the target of
the branch (what else can executing a goto mean?). That target is
outside the protected area, so when the VM delivers the exception
object, it will not be caught by the handler. So line 6 cannot be
executed as a result of an exception being delayed until after
line 2 executes.

Similarly I argue that if the exception is delayed until after
line 5 has assigned a new value to the variable d, then it is
being delivered after line 5 has completed execution. But when
line 5 has completed execution, the flow of control has exited
the protected area, so the exception will not be caught by line
6.

As I admitted at the outset, this is splitting hairs. I honestly
do believe that this is the sensible way to interpret the
specification, but I also concede that in practice there may be some
VM implementations that would deliver the asynchronous exception
to line 6 after performing line 5's assignment to d.  Perhaps to
be safe ExceptionalUnitGraph should add edges to asynchronous
exception handlers from all protected units, regardless of
whether the units have side effects---on that issue I await input from people
with more experience interpreting the Java specs than I have. 

In the meantime, feel free to leave omitExceptingUnits
set to false).