[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: remove-unreachable-traps
After running Ondrej's example through "soot -O --dump-body ALL",
and comparing jop.uce2.in to jop.uce2.out, I think I understand
what is going on, and it is a result of a mistake I made when
adding --remove-unreachable-traps. I've checked in a provisional
fix.
My intention was that "--remove-unreachable-traps false"
would still allow the removal of traps that became unreachable
because all the trapped units were optimized away, but not those
that became unreachable because ExceptionalUnitGraph said none of
the trapped Units could throw the exeption being trapped.
Before ExceptionalUnitGraph, UnreachableCodeEliminator amounted to:
Perform a depth-first search to find all the units reachable
from the first unit in the method.
Remove all units that left unvisited by the depth-first
search.
Remove all traps that now trap no units.
Essentially my change --- in the case where
remove-unreachable-traps is false --- consisted of adding to the
set of DFS starting points the getHandlerUnit() of each Trap that
was not trapping zero units. My intention was that by not adding
the Traps with zero trapped units, I would continue to allow them
to be removed as they had always been.
What I somehow neglected to think of is that is only _after_ the
DFS that you eliminate the trapped units. Doh!
So in the test case from abc, all the handlers get added to the
list of DFS starting points, guaranteeing that all the handler
units will be retained. Then the DFS discovers that the trapped
units for one of the traps are unreachable, and eliminates them.
_Now_ the corresponding trap covers zero trapped units, so the
last step removes the Trap, even though the units comprising the
Trap's handler are still in the Body.
At first glance, it would seem that the fix (if you want to
continue to allow the retention of Traps that are unreachable
because ExceptionalUnitGraph says that the units they trap can't
throw the caught exception), would involve iterating the steps:
DFS starting from the method entry point and all handlers which
trap more than 0 units.
Eliminate unvisited units.
Eliminate Traps trapping 0 units.
so long as the last step has eliminated some traps. Ondrej was
essentially doing this when he ran UnreachableCodeEliminator a
third time:
olhotak> Also interesting is that jop runs the
olhotak> UnreachableCodeEliminator twice. If you change it
olhotak> to run it a third time, it gets rid of the
olhotak> unreachable handler, and everything works.
But I've checked in a simpler option: essentially I've returned
the code to its original form, except that if
remove-unreachable-traps is false, I use the pessimistic
ExceptionalUnitGraph(body, PedanticThrowAnalysis.v(), false)
for a CFG, regardless of the default values for ThrowAnalysis and
omit-excepting-unit-edges. That should guarantee that the
handlers are reachable unless they trap 0 units.
Incidentally, the post-fix jimple output of "soot -O" on the abc
example reveal a minor intraprocedural optimization which soot is
missing, at least in this example: it's failing to eliminate a
tableswitch with a constant argument. Are such degenerate
switches likely to be common in abc-generated code?:
protected void <init>()
{
NewSwitch2 r0;
java.lang.Throwable r3, r4;
FFDC2 r6, r7;
r0 := @this;
specialinvoke r0.<init>();
label0:
tableswitch(3)
{
case 3: goto label1;
default: goto label1;
};
label1:
goto label4;
label2:
r3 := @caughtexception;
r6 = FFDC2.aspectOf();
r6.afterThrowing$0(r3);
throw r3;
label3:
r4 := @caughtexception;
r7 = FFDC2.aspectOf();
r7.afterThrowing$0(r4);
throw r4;
label4:
return;
catch java.lang.Throwable from label0 to label2 with
label2;
catch java.lang.Throwable from label0 to label3 with
label3;
}