|
|
@ -246,7 +246,6 @@ public class TransformExceptionHandlers { |
|
|
|
public void checkAndRemoveJSR(FlowBlock tryFlow, FlowBlock subRoutine, |
|
|
|
public void checkAndRemoveJSR(FlowBlock tryFlow, FlowBlock subRoutine, |
|
|
|
int startOutExit, int endOutExit) { |
|
|
|
int startOutExit, int endOutExit) { |
|
|
|
boolean foundSub = false; |
|
|
|
boolean foundSub = false; |
|
|
|
FlowBlock exitBlock = null; |
|
|
|
|
|
|
|
Iterator iter = tryFlow.getSuccessors().iterator(); |
|
|
|
Iterator iter = tryFlow.getSuccessors().iterator(); |
|
|
|
dest_loop: |
|
|
|
dest_loop: |
|
|
|
while (iter.hasNext()) { |
|
|
|
while (iter.hasNext()) { |
|
|
@ -306,8 +305,7 @@ public class TransformExceptionHandlers { |
|
|
|
* directly to a correct jsr instruction, which |
|
|
|
* directly to a correct jsr instruction, which |
|
|
|
* lies outside the try/catch block. |
|
|
|
* lies outside the try/catch block. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (exitBlock == null |
|
|
|
if (jumps.destination.predecessors.size() == 1 |
|
|
|
&& jumps.destination.predecessors.size() == 1 |
|
|
|
|
|
|
|
&& jumps.destination.getAddr() >= startOutExit |
|
|
|
&& jumps.destination.getAddr() >= startOutExit |
|
|
|
&& jumps.destination.getNextAddr() <= endOutExit) { |
|
|
|
&& jumps.destination.getNextAddr() <= endOutExit) { |
|
|
|
jumps.destination.analyze(startOutExit, endOutExit); |
|
|
|
jumps.destination.analyze(startOutExit, endOutExit); |
|
|
@ -320,7 +318,6 @@ public class TransformExceptionHandlers { |
|
|
|
&& (sb.getSubBlocks()[0].jump.destination |
|
|
|
&& (sb.getSubBlocks()[0].jump.destination |
|
|
|
== subRoutine)) { |
|
|
|
== subRoutine)) { |
|
|
|
StructuredBlock jsrInner = sb.getSubBlocks()[0]; |
|
|
|
StructuredBlock jsrInner = sb.getSubBlocks()[0]; |
|
|
|
exitBlock = jumps.destination; |
|
|
|
|
|
|
|
jumps.destination.removeSuccessor(jsrInner.jump); |
|
|
|
jumps.destination.removeSuccessor(jsrInner.jump); |
|
|
|
jsrInner.removeJump(); |
|
|
|
jsrInner.removeJump(); |
|
|
|
sb.removeBlock(); |
|
|
|
sb.removeBlock(); |
|
|
@ -355,16 +352,30 @@ public class TransformExceptionHandlers { |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
boolean isMonitorExitSubRoutine(FlowBlock subRoutine, LocalInfo local) { |
|
|
|
|
|
|
|
if (transformSubRoutine(subRoutine.block)) { |
|
|
|
|
|
|
|
if (subRoutine.block instanceof InstructionBlock) { |
|
|
|
|
|
|
|
Expression instr = |
|
|
|
|
|
|
|
((InstructionBlock)subRoutine.block) |
|
|
|
|
|
|
|
.getInstruction(); |
|
|
|
|
|
|
|
if (isMonitorExit(instr, local)) { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void checkAndRemoveMonitorExit(FlowBlock tryFlow, LocalInfo local, |
|
|
|
public void checkAndRemoveMonitorExit(FlowBlock tryFlow, LocalInfo local, |
|
|
|
int startOutExit, int endOutExit, |
|
|
|
int startOutExit, int endOutExit, |
|
|
|
int startMonExit, int endMonExit) { |
|
|
|
int startMonExit, int endMonExit) { |
|
|
|
FlowBlock subRoutine = null; |
|
|
|
FlowBlock subRoutine = null; |
|
|
|
FlowBlock exitBlock = null; |
|
|
|
|
|
|
|
Iterator succs = tryFlow.getSuccessors().iterator(); |
|
|
|
Iterator succs = tryFlow.getSuccessors().iterator(); |
|
|
|
dest_loop: |
|
|
|
dest_loop: |
|
|
|
while (succs.hasNext()) { |
|
|
|
while (succs.hasNext()) { |
|
|
|
boolean isFirstJump = true; |
|
|
|
boolean isFirstJump = true; |
|
|
|
for (Jump jumps = tryFlow.getJumps((FlowBlock) succs.next()); |
|
|
|
FlowBlock successor = (FlowBlock) succs.next(); |
|
|
|
|
|
|
|
for (Jump jumps = tryFlow.getJumps(successor); |
|
|
|
jumps != null; jumps = jumps.next, isFirstJump = false) { |
|
|
|
jumps != null; jumps = jumps.next, isFirstJump = false) { |
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock prev = jumps.prev; |
|
|
|
StructuredBlock prev = jumps.prev; |
|
|
@ -435,44 +446,56 @@ public class TransformExceptionHandlers { |
|
|
|
* another jsr. This must be the monitorexit |
|
|
|
* another jsr. This must be the monitorexit |
|
|
|
* subroutine. |
|
|
|
* subroutine. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (prev instanceof JsrBlock && subRoutine == null) { |
|
|
|
if (prev instanceof JsrBlock) { |
|
|
|
|
|
|
|
if (subRoutine == null |
|
|
|
subRoutine = jumps.destination; |
|
|
|
&& successor.getAddr() >= startMonExit |
|
|
|
subRoutine.analyze(startMonExit, endMonExit); |
|
|
|
&& successor.getNextAddr() <= endMonExit) { |
|
|
|
transformSubRoutine(subRoutine.block); |
|
|
|
successor.analyze(startMonExit, endMonExit); |
|
|
|
|
|
|
|
|
|
|
|
if (subRoutine.block instanceof InstructionBlock) { |
|
|
|
if (isMonitorExitSubRoutine(successor, local)) |
|
|
|
Expression instr = |
|
|
|
subRoutine = successor; |
|
|
|
((InstructionBlock)subRoutine.block) |
|
|
|
|
|
|
|
.getInstruction(); |
|
|
|
|
|
|
|
if (isMonitorExit(instr, local)) { |
|
|
|
|
|
|
|
tryFlow.mergeAddr(subRoutine); |
|
|
|
|
|
|
|
continue dest_loop; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (subRoutine == successor) |
|
|
|
|
|
|
|
continue dest_loop; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Now we have a jump that is not preceded by a |
|
|
|
/* Now we have a jump that is not preceded by a |
|
|
|
* monitorexit. There's a last chance: the jump |
|
|
|
* monitorexit. There's a last chance: the jump |
|
|
|
* jumps directly to the correct monitorexit |
|
|
|
* jumps directly to the correct monitorexit |
|
|
|
* instruction, which lies outside the try/catch |
|
|
|
* instruction, which lies outside the try/catch |
|
|
|
* block. |
|
|
|
* block. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (exitBlock == null |
|
|
|
if (successor.predecessors.size() == 1 |
|
|
|
&& jumps.destination.predecessors.size() != 1 |
|
|
|
&& successor.getAddr() >= startOutExit |
|
|
|
&& jumps.destination.getAddr() >= startOutExit |
|
|
|
&& successor.getNextAddr() <= endOutExit) { |
|
|
|
&& jumps.destination.getNextAddr() <= endOutExit) { |
|
|
|
successor.analyze(startOutExit, endOutExit); |
|
|
|
jumps.destination.analyze(startOutExit, endOutExit); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock sb = jumps.destination.block; |
|
|
|
StructuredBlock sb = successor.block; |
|
|
|
if (sb instanceof SequentialBlock) |
|
|
|
if (sb instanceof SequentialBlock) |
|
|
|
sb = sb.getSubBlocks()[0]; |
|
|
|
sb = sb.getSubBlocks()[0]; |
|
|
|
|
|
|
|
if (sb instanceof JsrBlock |
|
|
|
|
|
|
|
&& sb.getSubBlocks()[0] instanceof EmptyBlock) { |
|
|
|
|
|
|
|
StructuredBlock jsrInner = sb.getSubBlocks()[0]; |
|
|
|
|
|
|
|
FlowBlock dest = jsrInner.jump.destination; |
|
|
|
|
|
|
|
if (subRoutine == null |
|
|
|
|
|
|
|
&& dest.getAddr() >= startMonExit |
|
|
|
|
|
|
|
&& dest.getNextAddr() <= endMonExit) { |
|
|
|
|
|
|
|
dest.analyze(startMonExit, endMonExit); |
|
|
|
|
|
|
|
if (isMonitorExitSubRoutine(dest, local)) |
|
|
|
|
|
|
|
subRoutine = dest; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (subRoutine == dest) { |
|
|
|
|
|
|
|
sb.removeBlock(); |
|
|
|
|
|
|
|
continue dest_loop; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
if (sb instanceof InstructionBlock) { |
|
|
|
if (sb instanceof InstructionBlock) { |
|
|
|
Expression instr = ((InstructionBlock)sb) |
|
|
|
Expression instr = ((InstructionBlock)sb) |
|
|
|
.getInstruction(); |
|
|
|
.getInstruction(); |
|
|
|
if (isMonitorExit(instr, local)) { |
|
|
|
if (isMonitorExit(instr, local)) { |
|
|
|
sb.removeBlock(); |
|
|
|
sb.removeBlock(); |
|
|
|
exitBlock = jumps.destination; |
|
|
|
|
|
|
|
continue dest_loop; |
|
|
|
continue dest_loop; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -488,8 +511,10 @@ public class TransformExceptionHandlers { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (subRoutine != null) |
|
|
|
if (subRoutine != null) { |
|
|
|
removeJSR(tryFlow, subRoutine); |
|
|
|
removeJSR(tryFlow, subRoutine); |
|
|
|
|
|
|
|
tryFlow.mergeAddr(subRoutine); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private boolean analyzeSynchronized(FlowBlock tryFlow, |
|
|
|
private boolean analyzeSynchronized(FlowBlock tryFlow, |
|
|
@ -545,6 +570,13 @@ public class TransformExceptionHandlers { |
|
|
|
((LocalLoadOperator)monexit.getSubExpressions()[0]) |
|
|
|
((LocalLoadOperator)monexit.getSubExpressions()[0]) |
|
|
|
.getLocalInfo(); |
|
|
|
.getLocalInfo(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((GlobalOptions.debuggingFlags |
|
|
|
|
|
|
|
& GlobalOptions.DEBUG_ANALYZE) != 0) |
|
|
|
|
|
|
|
GlobalOptions.err.println |
|
|
|
|
|
|
|
("analyzeSynchronized(" + tryFlow.getAddr() |
|
|
|
|
|
|
|
+ "," + tryFlow.getNextAddr() + "," + catchFlow.getAddr() |
|
|
|
|
|
|
|
+ "," + catchFlow.getNextAddr() + "," + endHandler + ")"); |
|
|
|
|
|
|
|
|
|
|
|
checkAndRemoveMonitorExit |
|
|
|
checkAndRemoveMonitorExit |
|
|
|
(tryFlow, local, |
|
|
|
(tryFlow, local, |
|
|
|
tryFlow.getNextAddr(), catchFlow.getAddr(), |
|
|
|
tryFlow.getNextAddr(), catchFlow.getAddr(), |
|
|
@ -942,7 +974,7 @@ public class TransformExceptionHandlers { |
|
|
|
if ((GlobalOptions.debuggingFlags |
|
|
|
if ((GlobalOptions.debuggingFlags |
|
|
|
& GlobalOptions.DEBUG_ANALYZE) != 0) |
|
|
|
& GlobalOptions.DEBUG_ANALYZE) != 0) |
|
|
|
GlobalOptions.err.println |
|
|
|
GlobalOptions.err.println |
|
|
|
("analyzeCatch(" + tryFlow.getAddr() + ", " |
|
|
|
("analyzeTryCatch(" + tryFlow.getAddr() + ", " |
|
|
|
+ tryFlow.getNextAddr() + ") done."); |
|
|
|
+ tryFlow.getNextAddr() + ") done."); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|