|
|
@ -122,9 +122,15 @@ public class FlowBlock { |
|
|
|
* @param jumps The jumps that jump to successor. All jumps that |
|
|
|
* @param jumps The jumps that jump to successor. All jumps that |
|
|
|
* can be optimized are removed from this stack. |
|
|
|
* can be optimized are removed from this stack. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void optimizeJumps(Stack jumps) { |
|
|
|
public void optimizeJumps(Stack jumps, FlowBlock succ) { |
|
|
|
Stack remainingJumps = new Stack(); |
|
|
|
Stack remainingJumps = new Stack(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (lastModified.jump == null) { |
|
|
|
|
|
|
|
Jump jump = new Jump(succ); |
|
|
|
|
|
|
|
lastModified.setJump(jump); |
|
|
|
|
|
|
|
remainingJumps.push(jump); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
next_jump: |
|
|
|
next_jump: |
|
|
|
while (!jumps.isEmpty()) { |
|
|
|
while (!jumps.isEmpty()) { |
|
|
|
Jump jump = (Jump) jumps.pop(); |
|
|
|
Jump jump = (Jump) jumps.pop(); |
|
|
@ -206,7 +212,7 @@ public class FlowBlock { |
|
|
|
(loopBlock.jumpMayBeChanged() |
|
|
|
(loopBlock.jumpMayBeChanged() |
|
|
|
|| loopBlock.getNextFlowBlock() == successor)) { |
|
|
|
|| loopBlock.getNextFlowBlock() == successor)) { |
|
|
|
|
|
|
|
|
|
|
|
if (loopBlock.jumpMayBeChanged()) { |
|
|
|
if (loopBlock.jump == null) { |
|
|
|
loopBlock.moveJump(jump); |
|
|
|
loopBlock.moveJump(jump); |
|
|
|
jumps.push(jump); |
|
|
|
jumps.push(jump); |
|
|
|
} else |
|
|
|
} else |
|
|
@ -240,7 +246,7 @@ public class FlowBlock { |
|
|
|
(loopBlock.jumpMayBeChanged() |
|
|
|
(loopBlock.jumpMayBeChanged() |
|
|
|
|| loopBlock.getNextFlowBlock() == successor)) { |
|
|
|
|| loopBlock.getNextFlowBlock() == successor)) { |
|
|
|
|
|
|
|
|
|
|
|
if (loopBlock.jumpMayBeChanged()) { |
|
|
|
if (loopBlock.jump == null) { |
|
|
|
loopBlock.moveJump(jump); |
|
|
|
loopBlock.moveJump(jump); |
|
|
|
jumps.push(jump); |
|
|
|
jumps.push(jump); |
|
|
|
} else |
|
|
|
} else |
|
|
@ -274,8 +280,7 @@ public class FlowBlock { |
|
|
|
newIfBlock.setThenBlock(thenBlock); |
|
|
|
newIfBlock.setThenBlock(thenBlock); |
|
|
|
|
|
|
|
|
|
|
|
if (thenBlock.contains(lastModified)) { |
|
|
|
if (thenBlock.contains(lastModified)) { |
|
|
|
if (lastModified.jump != null |
|
|
|
if (lastModified.jump.destination == successor) { |
|
|
|
&& lastModified.jump.destination == successor) { |
|
|
|
|
|
|
|
newIfBlock.moveJump(lastModified.jump); |
|
|
|
newIfBlock.moveJump(lastModified.jump); |
|
|
|
lastModified = newIfBlock; |
|
|
|
lastModified = newIfBlock; |
|
|
|
jump.prev.removeJump(); |
|
|
|
jump.prev.removeJump(); |
|
|
@ -327,8 +332,7 @@ public class FlowBlock { |
|
|
|
ifBlock.setElseBlock(elseBlock); |
|
|
|
ifBlock.setElseBlock(elseBlock); |
|
|
|
|
|
|
|
|
|
|
|
if (elseBlock.contains(lastModified)) { |
|
|
|
if (elseBlock.contains(lastModified)) { |
|
|
|
if (lastModified.jump != null |
|
|
|
if (lastModified.jump.destination == successor) { |
|
|
|
&& lastModified.jump.destination == successor) { |
|
|
|
|
|
|
|
ifBlock.moveJump(lastModified.jump); |
|
|
|
ifBlock.moveJump(lastModified.jump); |
|
|
|
lastModified = ifBlock; |
|
|
|
lastModified = ifBlock; |
|
|
|
jump.prev.removeJump(); |
|
|
|
jump.prev.removeJump(); |
|
|
@ -617,7 +621,7 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
optimizeJumps(jumps); |
|
|
|
optimizeJumps(jumps, succ); |
|
|
|
resolveRemaining(jumps); |
|
|
|
resolveRemaining(jumps); |
|
|
|
|
|
|
|
|
|
|
|
/* Now unify the blocks. |
|
|
|
/* Now unify the blocks. |
|
|
@ -737,7 +741,7 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
optimizeJumps(jumps); |
|
|
|
optimizeJumps(jumps, this); |
|
|
|
|
|
|
|
|
|
|
|
LoopBlock whileBlock = |
|
|
|
LoopBlock whileBlock = |
|
|
|
new LoopBlock(LoopBlock.WHILE, LoopBlock.TRUE); |
|
|
|
new LoopBlock(LoopBlock.WHILE, LoopBlock.TRUE); |
|
|
@ -751,7 +755,7 @@ public class FlowBlock { |
|
|
|
while (!jumps.isEmpty()) { |
|
|
|
while (!jumps.isEmpty()) { |
|
|
|
Jump jump = (Jump) jumps.pop(); |
|
|
|
Jump jump = (Jump) jumps.pop(); |
|
|
|
|
|
|
|
|
|
|
|
if (jump.prev == bodyBlock) |
|
|
|
if (jump.prev == lastModified) |
|
|
|
/* handled later */ |
|
|
|
/* handled later */ |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
@ -780,11 +784,10 @@ public class FlowBlock { |
|
|
|
(new BreakBlock(breakToBlock, breaklevel > 1)); |
|
|
|
(new BreakBlock(breakToBlock, breaklevel > 1)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Now remove the jump of bodyBlock if it points to this. |
|
|
|
/* Now remove the jump of lastModified if it points to this. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (bodyBlock.jump != null |
|
|
|
if (lastModified.jump.destination == this) |
|
|
|
&& bodyBlock.jump.destination == this) |
|
|
|
lastModified.removeJump(); |
|
|
|
bodyBlock.removeJump(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* remove ourself from the predecessor list. |
|
|
|
/* remove ourself from the predecessor list. |
|
|
@ -805,11 +808,13 @@ public class FlowBlock { |
|
|
|
public void mergeEndBlock() { |
|
|
|
public void mergeEndBlock() { |
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
|
|
|
|
|
|
|
|
/* First find the innermost block that contains all jumps to the |
|
|
|
Stack allJumps = (Stack) successors.remove(END_OF_METHOD); |
|
|
|
* END_OF_METHOD block. |
|
|
|
if (allJumps == null) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* First remove all implicit jumps to the END_OF_METHOD block. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
Stack jumps = new Stack(); |
|
|
|
Stack jumps = new Stack(); |
|
|
|
Stack allJumps = (Stack) successors.remove(END_OF_METHOD); |
|
|
|
|
|
|
|
Enumeration enum = allJumps.elements(); |
|
|
|
Enumeration enum = allJumps.elements(); |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
@ -824,7 +829,7 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
optimizeJumps(jumps); |
|
|
|
optimizeJumps(jumps, END_OF_METHOD); |
|
|
|
|
|
|
|
|
|
|
|
next_jump: |
|
|
|
next_jump: |
|
|
|
while (!jumps.isEmpty()) { |
|
|
|
while (!jumps.isEmpty()) { |
|
|
@ -863,8 +868,7 @@ public class FlowBlock { |
|
|
|
/* Now remove the jump of the lastModified if it points to |
|
|
|
/* Now remove the jump of the lastModified if it points to |
|
|
|
* END_OF_METHOD. |
|
|
|
* END_OF_METHOD. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (lastModified.jump != null |
|
|
|
if (lastModified.jump.destination == END_OF_METHOD) |
|
|
|
&& lastModified.jump.destination == END_OF_METHOD) |
|
|
|
|
|
|
|
lastModified.removeJump(); |
|
|
|
lastModified.removeJump(); |
|
|
|
|
|
|
|
|
|
|
|
/* transformation succeeded */ |
|
|
|
/* transformation succeeded */ |
|
|
@ -1327,9 +1331,11 @@ public class FlowBlock { |
|
|
|
if (tryFlow == catchFlow) |
|
|
|
if (tryFlow == catchFlow) |
|
|
|
throw new AssertError("try == catch"); |
|
|
|
throw new AssertError("try == catch"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
boolean changed = false; |
|
|
|
boolean changed = false; |
|
|
|
while(tryFlow.analyze(addr, catchFlow.addr)); |
|
|
|
while(tryFlow.analyze(addr, catchFlow.addr)); |
|
|
|
while(catchFlow.analyze(catchFlow.addr, end)); |
|
|
|
while(catchFlow.analyze(catchFlow.addr, end)); |
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
|
|
|
|
|
|
|
|
updateInOut(tryFlow, true, (Stack) successors.remove(tryFlow)); |
|
|
|
updateInOut(tryFlow, true, (Stack) successors.remove(tryFlow)); |
|
|
|
updateInOut(catchFlow, true, (Stack) successors.remove(catchFlow)); |
|
|
|
updateInOut(catchFlow, true, (Stack) successors.remove(catchFlow)); |
|
|
@ -1410,7 +1416,9 @@ public class FlowBlock { |
|
|
|
((LocalLoadOperator)monexit.getSubExpressions()[0]) |
|
|
|
((LocalLoadOperator)monexit.getSubExpressions()[0]) |
|
|
|
.getLocalInfo(); |
|
|
|
.getLocalInfo(); |
|
|
|
|
|
|
|
|
|
|
|
checkAndRemoveMonitorExit(local, end); |
|
|
|
length -= tryFlow.length; |
|
|
|
|
|
|
|
tryFlow.checkAndRemoveMonitorExit(local, end); |
|
|
|
|
|
|
|
length += tryFlow.length; |
|
|
|
|
|
|
|
|
|
|
|
SynchronizedBlock syncBlock = new SynchronizedBlock(local); |
|
|
|
SynchronizedBlock syncBlock = new SynchronizedBlock(local); |
|
|
|
syncBlock.replace(rawBlock, rawBlock); |
|
|
|
syncBlock.replace(rawBlock, rawBlock); |
|
|
@ -1475,7 +1483,7 @@ public class FlowBlock { |
|
|
|
if (subRoutine.successors.size() != 0) |
|
|
|
if (subRoutine.successors.size() != 0) |
|
|
|
throw new AssertError("Jump inside subroutine"); |
|
|
|
throw new AssertError("Jump inside subroutine"); |
|
|
|
length += subRoutine.length; |
|
|
|
length += subRoutine.length; |
|
|
|
checkAndRemoveJSR(subRoutine); |
|
|
|
tryFlow.checkAndRemoveJSR(subRoutine); |
|
|
|
|
|
|
|
|
|
|
|
CatchFinallyBlock newBlock = new CatchFinallyBlock(); |
|
|
|
CatchFinallyBlock newBlock = new CatchFinallyBlock(); |
|
|
|
newBlock.replace(rawBlock, rawBlock); |
|
|
|
newBlock.replace(rawBlock, rawBlock); |
|
|
@ -1491,50 +1499,53 @@ public class FlowBlock { |
|
|
|
&& ((InstructionBlock) catchFlow.block).getInstruction() |
|
|
|
&& ((InstructionBlock) catchFlow.block).getInstruction() |
|
|
|
instanceof PopOperator |
|
|
|
instanceof PopOperator |
|
|
|
&& ((PopOperator) ((InstructionBlock) catchFlow.block) |
|
|
|
&& ((PopOperator) ((InstructionBlock) catchFlow.block) |
|
|
|
.getInstruction()).getCount() == 1 |
|
|
|
.getInstruction()).getCount() == 1) { |
|
|
|
&& successors.size() == 1) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This is a special try/finally-block, where |
|
|
|
/* This is a special try/finally-block, where |
|
|
|
* the finally block ends with a break, return or |
|
|
|
* the finally block ends with a break, return or |
|
|
|
* similar. |
|
|
|
* similar. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
FlowBlock succ = catchFlow.block.jump.destination; |
|
|
|
FlowBlock succ = catchFlow.block.jump.destination; |
|
|
|
Stack jumps = (Stack) successors.remove(succ); |
|
|
|
Stack jumps = (Stack) tryFlow.successors.remove(succ); |
|
|
|
updateInOut(succ, true, jumps); |
|
|
|
if (tryFlow.successors.size() > 0) { |
|
|
|
|
|
|
|
/* Only do the rest if tryFlow has no other exit point, |
|
|
|
Stack stack = new Stack(); |
|
|
|
* undo the previous remove. |
|
|
|
stack.push(catchFlow.block.jump); |
|
|
|
*/ |
|
|
|
successors.put(succ, stack); |
|
|
|
tryFlow.successors.put(succ,jumps); |
|
|
|
|
|
|
|
|
|
|
|
jumps.removeElement(catchFlow.block.jump); |
|
|
|
|
|
|
|
if (rawBlock.tryBlock.jump == null) { |
|
|
|
|
|
|
|
Jump jump = new Jump(succ); |
|
|
|
|
|
|
|
rawBlock.tryBlock.setJump(jump); |
|
|
|
|
|
|
|
jumps.push(jump); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lastModified = tryFlow.lastModified; |
|
|
|
|
|
|
|
optimizeJumps(jumps); |
|
|
|
|
|
|
|
resolveRemaining(jumps); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CatchFinallyBlock newBlock = new CatchFinallyBlock(); |
|
|
|
|
|
|
|
newBlock.replace(rawBlock, rawBlock); |
|
|
|
|
|
|
|
newBlock.setTryBlock(rawBlock.tryBlock); |
|
|
|
|
|
|
|
if (succ.predecessors.size() == 1) { |
|
|
|
|
|
|
|
while (succ.analyze(addr+length, end)); |
|
|
|
|
|
|
|
length += succ.length; |
|
|
|
|
|
|
|
successors.remove(succ); |
|
|
|
|
|
|
|
newBlock.setFinallyBlock(succ.block); |
|
|
|
|
|
|
|
mergeSuccessors(succ); |
|
|
|
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
/* The finally block is empty, put the jump back |
|
|
|
|
|
|
|
* into the finally block. |
|
|
|
succ.predecessors.removeElement(tryFlow); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Handle the jumps in the tryFlow. Note that |
|
|
|
|
|
|
|
* we call updateInOut on ourself, don't change it. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
newBlock.setFinallyBlock(new EmptyBlock()); |
|
|
|
updateInOut(succ, true, jumps); |
|
|
|
newBlock.finallyBlock.moveJump(catchFlow.block.jump); |
|
|
|
tryFlow.optimizeJumps(jumps, succ); |
|
|
|
|
|
|
|
tryFlow.resolveRemaining(jumps); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CatchFinallyBlock newBlock = new CatchFinallyBlock(); |
|
|
|
|
|
|
|
newBlock.replace(rawBlock, rawBlock); |
|
|
|
|
|
|
|
newBlock.setTryBlock(tryFlow.block); |
|
|
|
|
|
|
|
/* try block has no successors */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (succ.predecessors.size() == 1) { |
|
|
|
|
|
|
|
while (succ.analyze(addr+length, end)); |
|
|
|
|
|
|
|
length += succ.length; |
|
|
|
|
|
|
|
successors.remove(succ); |
|
|
|
|
|
|
|
newBlock.setFinallyBlock(succ.block); |
|
|
|
|
|
|
|
mergeSuccessors(succ); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
/* The finally block is empty, put the jump back |
|
|
|
|
|
|
|
* into the finally block. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
newBlock.setFinallyBlock |
|
|
|
|
|
|
|
(new EmptyBlock(catchFlow.block.jump)); |
|
|
|
|
|
|
|
mergeSuccessors(catchFlow); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
lastModified = newBlock; |
|
|
|
|
|
|
|
changed = true; |
|
|
|
} |
|
|
|
} |
|
|
|
lastModified = newBlock; |
|
|
|
|
|
|
|
changed = true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
if (Decompiler.debugAnalyze) |
|
|
|
if (Decompiler.debugAnalyze) |
|
|
@ -1628,7 +1639,7 @@ public class FlowBlock { |
|
|
|
updateInOut(nextFlow, true, lastJumps); |
|
|
|
updateInOut(nextFlow, true, lastJumps); |
|
|
|
lastJumps.pop(); |
|
|
|
lastJumps.pop(); |
|
|
|
|
|
|
|
|
|
|
|
lastFlow.optimizeJumps(lastJumps); |
|
|
|
lastFlow.optimizeJumps(lastJumps, nextFlow); |
|
|
|
lastFlow.resolveRemaining(lastJumps); |
|
|
|
lastFlow.resolveRemaining(lastJumps); |
|
|
|
} else |
|
|
|
} else |
|
|
|
updateInOut(nextFlow, true, jumps); |
|
|
|
updateInOut(nextFlow, true, jumps); |
|
|
@ -1709,7 +1720,7 @@ public class FlowBlock { |
|
|
|
destJumps = new Stack(); |
|
|
|
destJumps = new Stack(); |
|
|
|
successors.put(jump.destination, destJumps); |
|
|
|
successors.put(jump.destination, destJumps); |
|
|
|
} |
|
|
|
} |
|
|
|
destJumps.addElement(jump); |
|
|
|
destJumps.push(jump); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void makeDeclaration(VariableSet param) { |
|
|
|
public void makeDeclaration(VariableSet param) { |
|
|
|