|
|
@ -119,13 +119,10 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* This method optimizes the jumps to successor. |
|
|
|
* This method optimizes the jumps to successor. |
|
|
|
* @param appendBlock the block where the successor is appended to. |
|
|
|
|
|
|
|
* @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. |
|
|
|
* @return the new appendBlock, it may have changed. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public StructuredBlock optimizeJumps(StructuredBlock appendBlock, |
|
|
|
public void optimizeJumps(Stack jumps) { |
|
|
|
Stack jumps) { |
|
|
|
|
|
|
|
Stack remainingJumps = new Stack(); |
|
|
|
Stack remainingJumps = new Stack(); |
|
|
|
|
|
|
|
|
|
|
|
next_jump: |
|
|
|
next_jump: |
|
|
@ -134,15 +131,15 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
FlowBlock successor = jump.destination; |
|
|
|
FlowBlock successor = jump.destination; |
|
|
|
|
|
|
|
|
|
|
|
/* if the jump is the jump of the appendBlock, skip it. |
|
|
|
/* if the jump is the jump of the lastModified, skip it. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (jump.prev == appendBlock) { |
|
|
|
if (jump.prev == lastModified) { |
|
|
|
remainingJumps.push(jump); |
|
|
|
remainingJumps.push(jump); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* jump.prev.outer is not null since appendBlock is an |
|
|
|
/* jump.prev.outer is not null, otherwise jump.prev would |
|
|
|
* outer block. |
|
|
|
* be lastModified. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
/* remove this jump if it jumps to the getNextFlowBlock(). |
|
|
|
/* remove this jump if it jumps to the getNextFlowBlock(). |
|
|
@ -186,8 +183,8 @@ public class FlowBlock { |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Now cb.jump is null and cb.outer is not null, |
|
|
|
/* Now cb.jump is null, so cb.outer is not null, |
|
|
|
* since appendBlock is around it. */ |
|
|
|
* since otherwise it would have no successor. */ |
|
|
|
|
|
|
|
|
|
|
|
ConditionalBlock cb = (ConditionalBlock) jump.prev.outer; |
|
|
|
ConditionalBlock cb = (ConditionalBlock) jump.prev.outer; |
|
|
|
Expression instr = cb.getInstruction(); |
|
|
|
Expression instr = cb.getInstruction(); |
|
|
@ -206,19 +203,19 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
if (loopBlock.getCondition() == LoopBlock.TRUE && |
|
|
|
if (loopBlock.getCondition() == LoopBlock.TRUE && |
|
|
|
loopBlock.getType() != LoopBlock.DOWHILE && |
|
|
|
loopBlock.getType() != LoopBlock.DOWHILE && |
|
|
|
loopBlock.getNextFlowBlock() == successor) { |
|
|
|
(loopBlock.jumpMayBeChanged() |
|
|
|
|
|
|
|
|| loopBlock.getNextFlowBlock() == successor)) { |
|
|
|
|
|
|
|
|
|
|
|
jump.prev.removeJump(); |
|
|
|
|
|
|
|
loopBlock.setCondition(instr.negate()); |
|
|
|
loopBlock.setCondition(instr.negate()); |
|
|
|
loopBlock.moveDefinitions(cb, null); |
|
|
|
loopBlock.moveDefinitions(cb, null); |
|
|
|
|
|
|
|
|
|
|
|
cb.removeBlock(); |
|
|
|
cb.removeBlock(); |
|
|
|
|
|
|
|
if (loopBlock.jumpMayBeChanged()) { |
|
|
|
/* Note that cb.outer != appendBlock because |
|
|
|
loopBlock.moveJump(jump); |
|
|
|
* appendBlock contains loopBlock. This is |
|
|
|
jumps.push(jump); |
|
|
|
* because lastModified is in the outermost |
|
|
|
continue; |
|
|
|
* block. |
|
|
|
} |
|
|
|
*/ |
|
|
|
jump.prev.removeJump(); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -241,14 +238,21 @@ public class FlowBlock { |
|
|
|
LoopBlock loopBlock = (LoopBlock) sb; |
|
|
|
LoopBlock loopBlock = (LoopBlock) sb; |
|
|
|
if (loopBlock.getCondition() == LoopBlock.TRUE && |
|
|
|
if (loopBlock.getCondition() == LoopBlock.TRUE && |
|
|
|
loopBlock.getType() == LoopBlock.WHILE && |
|
|
|
loopBlock.getType() == LoopBlock.WHILE && |
|
|
|
loopBlock.getNextFlowBlock() == successor) { |
|
|
|
(loopBlock.jumpMayBeChanged() |
|
|
|
|
|
|
|
|| loopBlock.getNextFlowBlock() == successor)) { |
|
|
|
|
|
|
|
|
|
|
|
jump.prev.removeJump(); |
|
|
|
|
|
|
|
loopBlock.setType(LoopBlock.DOWHILE); |
|
|
|
loopBlock.setType(LoopBlock.DOWHILE); |
|
|
|
loopBlock.setCondition(instr.negate()); |
|
|
|
loopBlock.setCondition(instr.negate()); |
|
|
|
loopBlock.moveDefinitions(cb, null); |
|
|
|
loopBlock.moveDefinitions(cb, null); |
|
|
|
|
|
|
|
|
|
|
|
cb.removeBlock(); |
|
|
|
cb.removeBlock(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (loopBlock.jumpMayBeChanged()) { |
|
|
|
|
|
|
|
loopBlock.moveJump(jump); |
|
|
|
|
|
|
|
jumps.push(jump); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
jump.prev.removeJump(); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -263,49 +267,48 @@ public class FlowBlock { |
|
|
|
(cb.outer.getNextFlowBlock() == successor || |
|
|
|
(cb.outer.getNextFlowBlock() == successor || |
|
|
|
cb.outer.jumpMayBeChanged())) { |
|
|
|
cb.outer.jumpMayBeChanged())) { |
|
|
|
|
|
|
|
|
|
|
|
SequentialBlock sequBlock = |
|
|
|
SequentialBlock sequBlock = (SequentialBlock) cb.outer; |
|
|
|
(SequentialBlock) cb.outer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IfThenElseBlock newIfBlock = |
|
|
|
IfThenElseBlock newIfBlock |
|
|
|
new IfThenElseBlock(instr.negate()); |
|
|
|
= new IfThenElseBlock(instr.negate()); |
|
|
|
|
|
|
|
StructuredBlock thenBlock = sequBlock.getSubBlocks()[1]; |
|
|
|
|
|
|
|
|
|
|
|
newIfBlock.replace(sequBlock, sequBlock.getSubBlocks()[1]); |
|
|
|
newIfBlock.replace(sequBlock, thenBlock); |
|
|
|
newIfBlock.setThenBlock(sequBlock.getSubBlocks()[1]); |
|
|
|
newIfBlock.setThenBlock(thenBlock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (thenBlock.contains(lastModified)) { |
|
|
|
if (appendBlock == sequBlock) { |
|
|
|
if (lastModified.jump != null |
|
|
|
newIfBlock.moveJump(appendBlock.jump); |
|
|
|
&& lastModified.jump.destination == successor) { |
|
|
|
appendBlock = newIfBlock; |
|
|
|
newIfBlock.moveJump(lastModified.jump); |
|
|
|
jump.prev.removeJump(); |
|
|
|
lastModified = newIfBlock; |
|
|
|
} else { |
|
|
|
jump.prev.removeJump(); |
|
|
|
newIfBlock.moveJump(jump); |
|
|
|
continue; |
|
|
|
/* consider this jump again */ |
|
|
|
} |
|
|
|
jumps.push(jump); |
|
|
|
lastModified = newIfBlock; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
newIfBlock.moveJump(jump); |
|
|
|
|
|
|
|
/* consider this jump again */ |
|
|
|
|
|
|
|
jumps.push(jump); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
|
|
/* Now find the real outer block, that is ascend the chain |
|
|
|
/* Now find the real outer block, that is ascend the chain |
|
|
|
* of SequentialBlocks. But don't leave appendBlock. |
|
|
|
* of SequentialBlocks. |
|
|
|
* |
|
|
|
* |
|
|
|
* Note that only the last instr in a SequentialBlock chain |
|
|
|
* Note that only the last instr in a SequentialBlock chain |
|
|
|
* can have a jump. |
|
|
|
* can have a jump. |
|
|
|
* |
|
|
|
* |
|
|
|
* Note further, that jump.prev must be a inner block, since |
|
|
|
* We rely on the fact, that instanceof returns false |
|
|
|
* otherwise its normal flow block is that of appendBlock, |
|
|
|
* for a null pointer. |
|
|
|
* and appendblocks successor must be the destination, since |
|
|
|
|
|
|
|
* it is then a sequential block. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* Yes, I know this data structure is quite subtile. But |
|
|
|
|
|
|
|
* that's why the function checkConsistent exists. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
StructuredBlock sb = jump.prev.outer; |
|
|
|
StructuredBlock sb = jump.prev.outer; |
|
|
|
while (sb instanceof SequentialBlock) |
|
|
|
while (sb instanceof SequentialBlock) |
|
|
|
sb = sb.outer; |
|
|
|
sb = sb.outer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if this is a jumps at the end of a then block belonging |
|
|
|
/* if this is a jump at the end of a then block belonging |
|
|
|
* to a if-then block without else part, and the if-then |
|
|
|
* to a if-then block without else part, and the if-then |
|
|
|
* block is followed by a single block, then replace the |
|
|
|
* block is followed by a single block, then replace the |
|
|
|
* if-then block with a if-then-else block and remove the |
|
|
|
* if-then block with a if-then-else block and remove the |
|
|
@ -326,15 +329,20 @@ public class FlowBlock { |
|
|
|
ifBlock.replace(sequBlock, elseBlock); |
|
|
|
ifBlock.replace(sequBlock, elseBlock); |
|
|
|
ifBlock.setElseBlock(elseBlock); |
|
|
|
ifBlock.setElseBlock(elseBlock); |
|
|
|
|
|
|
|
|
|
|
|
if (appendBlock == sequBlock) { |
|
|
|
if (elseBlock.contains(lastModified)) { |
|
|
|
ifBlock.moveJump(appendBlock.jump); |
|
|
|
if (lastModified.jump != null |
|
|
|
appendBlock = ifBlock; |
|
|
|
&& lastModified.jump.destination == successor) { |
|
|
|
jump.prev.removeJump(); |
|
|
|
ifBlock.moveJump(lastModified.jump); |
|
|
|
} else { |
|
|
|
lastModified = ifBlock; |
|
|
|
/* consider this jump again */ |
|
|
|
jump.prev.removeJump(); |
|
|
|
ifBlock.moveJump(jump); |
|
|
|
continue; |
|
|
|
jumps.push(jump); |
|
|
|
} |
|
|
|
|
|
|
|
lastModified = ifBlock; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* consider this jump again */ |
|
|
|
|
|
|
|
ifBlock.moveJump(jump); |
|
|
|
|
|
|
|
jumps.push(jump); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -348,8 +356,7 @@ public class FlowBlock { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
for (StructuredBlock surrounder = jump.prev.outer; |
|
|
|
for (StructuredBlock surrounder = jump.prev.outer; |
|
|
|
surrounder != null && surrounder != appendBlock.outer; |
|
|
|
surrounder != null; surrounder = surrounder.outer) { |
|
|
|
surrounder = surrounder.outer) { |
|
|
|
|
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
if (surrounder.getNextFlowBlock() != successor |
|
|
|
if (surrounder.getNextFlowBlock() != successor |
|
|
|
&& surrounder.jumpMayBeChanged()) { |
|
|
|
&& surrounder.jumpMayBeChanged()) { |
|
|
@ -364,61 +371,32 @@ public class FlowBlock { |
|
|
|
} |
|
|
|
} |
|
|
|
while(!remainingJumps.isEmpty()) |
|
|
|
while(!remainingJumps.isEmpty()) |
|
|
|
jumps.push(remainingJumps.pop()); |
|
|
|
jumps.push(remainingJumps.pop()); |
|
|
|
return appendBlock; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Move the successors of the given flow block to this flow block. |
|
|
|
|
|
|
|
* @param succ the other flow block |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
void mergeSuccessors(FlowBlock succ) { |
|
|
|
|
|
|
|
/* Merge the sucessors from the successing flow block |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
Enumeration keys = succ.successors.keys(); |
|
|
|
|
|
|
|
Enumeration stacks = succ.successors.elements(); |
|
|
|
|
|
|
|
while (keys.hasMoreElements()) { |
|
|
|
|
|
|
|
FlowBlock dest = (FlowBlock) keys.nextElement(); |
|
|
|
|
|
|
|
Stack hisJumps = (Stack) stacks.nextElement(); |
|
|
|
|
|
|
|
Stack myJumps = (Stack) successors.get(dest); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dest.predecessors.removeElement(succ); |
|
|
|
|
|
|
|
if (myJumps == null) { |
|
|
|
|
|
|
|
dest.predecessors.addElement(this); |
|
|
|
|
|
|
|
successors.put(dest, hisJumps); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
while (!hisJumps.isEmpty()) |
|
|
|
|
|
|
|
myJumps.push(hisJumps.pop()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Resolve remaining jumps to the successor by generating break |
|
|
|
* Resolve remaining jumps to the successor by generating break |
|
|
|
* instructions. As last resort generate a do while(false) block. |
|
|
|
* instructions. As last resort generate a do while(false) block. |
|
|
|
* @param appendBlock the block where the successor is appended to. |
|
|
|
|
|
|
|
* @param jumps The jumps that should be resolved. |
|
|
|
* @param jumps The jumps that should be resolved. |
|
|
|
* @return the new appendBlock, it may have changed. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
StructuredBlock resolveRemaining(StructuredBlock appendBlock, |
|
|
|
void resolveRemaining(Stack jumps) { |
|
|
|
Stack jumps) { |
|
|
|
|
|
|
|
LoopBlock doWhileFalse = null; |
|
|
|
LoopBlock doWhileFalse = null; |
|
|
|
boolean removeAppendJump = false; |
|
|
|
StructuredBlock outerMost = lastModified; |
|
|
|
|
|
|
|
boolean removeLast = false; |
|
|
|
next_jump: |
|
|
|
next_jump: |
|
|
|
while (!jumps.isEmpty()) { |
|
|
|
while (!jumps.isEmpty()) { |
|
|
|
Jump jump = (Jump) jumps.pop(); |
|
|
|
Jump jump = (Jump) jumps.pop(); |
|
|
|
StructuredBlock prevBlock = jump.prev; |
|
|
|
StructuredBlock prevBlock = jump.prev; |
|
|
|
|
|
|
|
|
|
|
|
if (prevBlock == appendBlock) { |
|
|
|
if (prevBlock == lastModified) { |
|
|
|
/* handled below */ |
|
|
|
/* handled below */ |
|
|
|
removeAppendJump = true; |
|
|
|
removeLast = true; |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int breaklevel = 0; |
|
|
|
int breaklevel = 0; |
|
|
|
BreakableBlock breakToBlock = null; |
|
|
|
BreakableBlock breakToBlock = null; |
|
|
|
for (StructuredBlock surrounder = prevBlock.outer; |
|
|
|
for (StructuredBlock surrounder = prevBlock.outer; |
|
|
|
surrounder != null && surrounder != appendBlock.outer; |
|
|
|
surrounder != null; surrounder = surrounder.outer) { |
|
|
|
surrounder = surrounder.outer) { |
|
|
|
|
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
breaklevel++; |
|
|
|
breaklevel++; |
|
|
|
if (surrounder.getNextFlowBlock() == jump.destination) { |
|
|
|
if (surrounder.getNextFlowBlock() == jump.destination) { |
|
|
@ -432,7 +410,7 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
if (breakToBlock == null) { |
|
|
|
if (breakToBlock == null) { |
|
|
|
/* Nothing else helped, so put a do/while(0) |
|
|
|
/* Nothing else helped, so put a do/while(0) |
|
|
|
* block around appendBlock and break to that |
|
|
|
* block around outerMost and break to that |
|
|
|
* block. |
|
|
|
* block. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (doWhileFalse == null) { |
|
|
|
if (doWhileFalse == null) { |
|
|
@ -440,6 +418,9 @@ public class FlowBlock { |
|
|
|
LoopBlock.FALSE); |
|
|
|
LoopBlock.FALSE); |
|
|
|
doWhileFalse.setJump(new Jump(jump.destination)); |
|
|
|
doWhileFalse.setJump(new Jump(jump.destination)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/* Adapt outermost, so that it contains the break. */ |
|
|
|
|
|
|
|
while (!outerMost.contains(prevBlock)) |
|
|
|
|
|
|
|
outerMost = outerMost.outer; |
|
|
|
prevBlock.appendBlock |
|
|
|
prevBlock.appendBlock |
|
|
|
(new BreakBlock(doWhileFalse, breaklevel > 0)); |
|
|
|
(new BreakBlock(doWhileFalse, breaklevel > 0)); |
|
|
|
} else |
|
|
|
} else |
|
|
@ -447,19 +428,40 @@ public class FlowBlock { |
|
|
|
(new BreakBlock(breakToBlock, breaklevel > 1)); |
|
|
|
(new BreakBlock(breakToBlock, breaklevel > 1)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (removeLast) |
|
|
|
|
|
|
|
lastModified.removeJump(); |
|
|
|
|
|
|
|
|
|
|
|
if (doWhileFalse != null) { |
|
|
|
if (doWhileFalse != null) { |
|
|
|
doWhileFalse.replace(appendBlock, appendBlock); |
|
|
|
doWhileFalse.replace(outerMost, outerMost); |
|
|
|
doWhileFalse.setBody(appendBlock); |
|
|
|
doWhileFalse.setBody(outerMost); |
|
|
|
doWhileFalse.jump = null; |
|
|
|
doWhileFalse.jump = null; |
|
|
|
|
|
|
|
lastModified = doWhileFalse; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Now remove the jump of the appendBlock if it points to |
|
|
|
/** |
|
|
|
* successor. |
|
|
|
* Move the successors of the given flow block to this flow block. |
|
|
|
|
|
|
|
* @param succ the other flow block |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
void mergeSuccessors(FlowBlock succ) { |
|
|
|
|
|
|
|
/* Merge the sucessors from the successing flow block |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (removeAppendJump) |
|
|
|
Enumeration keys = succ.successors.keys(); |
|
|
|
appendBlock.removeJump(); |
|
|
|
Enumeration stacks = succ.successors.elements(); |
|
|
|
|
|
|
|
while (keys.hasMoreElements()) { |
|
|
|
|
|
|
|
FlowBlock dest = (FlowBlock) keys.nextElement(); |
|
|
|
|
|
|
|
Stack hisJumps = (Stack) stacks.nextElement(); |
|
|
|
|
|
|
|
Stack myJumps = (Stack) successors.get(dest); |
|
|
|
|
|
|
|
|
|
|
|
return appendBlock; |
|
|
|
dest.predecessors.removeElement(succ); |
|
|
|
|
|
|
|
if (myJumps == null) { |
|
|
|
|
|
|
|
dest.predecessors.addElement(this); |
|
|
|
|
|
|
|
successors.put(dest, hisJumps); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
while (!hisJumps.isEmpty()) |
|
|
|
|
|
|
|
myJumps.push(hisJumps.pop()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -470,7 +472,7 @@ public class FlowBlock { |
|
|
|
* @return The variables that must be defined in this block. |
|
|
|
* @return The variables that must be defined in this block. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
void updateInOut (FlowBlock successor, boolean t1Transformation, |
|
|
|
void updateInOut (FlowBlock successor, boolean t1Transformation, |
|
|
|
Stack jumps) { |
|
|
|
Stack jumps) { |
|
|
|
/* First get the out vectors of all jumps to successor and |
|
|
|
/* First get the out vectors of all jumps to successor and |
|
|
|
* calculate the intersection. |
|
|
|
* calculate the intersection. |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -530,70 +532,69 @@ public class FlowBlock { |
|
|
|
* checkConsistent functions. |
|
|
|
* checkConsistent functions. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void checkConsistent() { |
|
|
|
public void checkConsistent() { |
|
|
|
|
|
|
|
/* This checks are very time consuming, so don't do them |
|
|
|
|
|
|
|
* normally. |
|
|
|
|
|
|
|
*/ |
|
|
|
if (!Decompiler.doChecks) |
|
|
|
if (!Decompiler.doChecks) |
|
|
|
return; |
|
|
|
return; |
|
|
|
// try {
|
|
|
|
|
|
|
|
if (block.outer != null || block.flowBlock != this) { |
|
|
|
|
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
block.checkConsistent(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Enumeration preds = predecessors.elements(); |
|
|
|
if (block.outer != null || block.flowBlock != this) { |
|
|
|
while (preds.hasMoreElements()) { |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
FlowBlock pred = (FlowBlock)preds.nextElement(); |
|
|
|
} |
|
|
|
if (pred == null) |
|
|
|
block.checkConsistent(); |
|
|
|
/* The special start marker */ |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
if (pred.successors.get(this) == null) |
|
|
|
|
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock last = lastModified; |
|
|
|
Enumeration preds = predecessors.elements(); |
|
|
|
while (last.outer instanceof SequentialBlock) |
|
|
|
while (preds.hasMoreElements()) { |
|
|
|
last = last.outer; |
|
|
|
FlowBlock pred = (FlowBlock)preds.nextElement(); |
|
|
|
if (last.outer != null) |
|
|
|
if (pred == null) |
|
|
|
|
|
|
|
/* The special start marker */ |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
if (pred.successors.get(this) == null) |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Enumeration keys = successors.keys(); |
|
|
|
StructuredBlock last = lastModified; |
|
|
|
Enumeration stacks = successors.elements(); |
|
|
|
while (last.outer instanceof SequentialBlock) |
|
|
|
while (keys.hasMoreElements()) { |
|
|
|
last = last.outer; |
|
|
|
FlowBlock dest = (FlowBlock) keys.nextElement(); |
|
|
|
if (last.outer != null) |
|
|
|
if (!dest.predecessors.contains(this)) |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Enumeration enum = ((Stack)stacks.nextElement()).elements(); |
|
|
|
Enumeration keys = successors.keys(); |
|
|
|
if (!enum.hasMoreElements()) |
|
|
|
Enumeration stacks = successors.elements(); |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
while (keys.hasMoreElements()) { |
|
|
|
|
|
|
|
FlowBlock dest = (FlowBlock) keys.nextElement(); |
|
|
|
|
|
|
|
if (!dest.predecessors.contains(this)) |
|
|
|
|
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
|
|
|
|
|
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
Enumeration enum = ((Stack)stacks.nextElement()).elements(); |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
if (!enum.hasMoreElements()) |
|
|
|
|
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
|
|
|
|
|
|
|
|
if (jump.destination != dest) |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
|
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (jump.destination != dest) |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
|
|
|
|
|
|
|
|
if (jump.prev.flowBlock != this || |
|
|
|
if (jump.prev.flowBlock != this || |
|
|
|
jump.prev.jump != jump) |
|
|
|
jump.prev.jump != jump) |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
|
|
|
|
|
|
|
|
prev_loop: |
|
|
|
prev_loop: |
|
|
|
for (StructuredBlock prev = jump.prev; prev != block; |
|
|
|
for (StructuredBlock prev = jump.prev; prev != block; |
|
|
|
prev = prev.outer) { |
|
|
|
prev = prev.outer) { |
|
|
|
if (prev.outer == null) |
|
|
|
if (prev.outer == null) |
|
|
|
throw new RuntimeException("Inconsistency"); |
|
|
|
throw new RuntimeException("Inconsistency"); |
|
|
|
StructuredBlock[] blocks = prev.outer.getSubBlocks(); |
|
|
|
StructuredBlock[] blocks = prev.outer.getSubBlocks(); |
|
|
|
int i; |
|
|
|
int i; |
|
|
|
for (i=0; i<blocks.length; i++) |
|
|
|
for (i=0; i<blocks.length; i++) |
|
|
|
if (blocks[i] == prev) |
|
|
|
if (blocks[i] == prev) |
|
|
|
continue prev_loop; |
|
|
|
continue prev_loop; |
|
|
|
|
|
|
|
|
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// } catch (AssertError ex) {
|
|
|
|
} |
|
|
|
// System.err.println("in: "+this);
|
|
|
|
|
|
|
|
// throw ex;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -612,79 +613,25 @@ public class FlowBlock { |
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
succ.checkConsistent(); |
|
|
|
succ.checkConsistent(); |
|
|
|
|
|
|
|
|
|
|
|
/* First find the innermost block that contains all jumps to this |
|
|
|
|
|
|
|
* successor and the last modified block. |
|
|
|
|
|
|
|
* Build the stack of interesting jumps on the fly. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
Stack jumps = (Stack) successors.remove(succ); |
|
|
|
Stack jumps = (Stack) successors.remove(succ); |
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock appendBlock = lastModified; |
|
|
|
|
|
|
|
Enumeration enum = jumps.elements(); |
|
|
|
|
|
|
|
while(enum.hasMoreElements()) { |
|
|
|
|
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
|
|
|
|
while (!appendBlock.contains(jump.prev)) { |
|
|
|
|
|
|
|
appendBlock = appendBlock.outer; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/* appendBlock can't be null now, because the |
|
|
|
|
|
|
|
* outermost block contains every structured block. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Update the in/out-Vectors now */ |
|
|
|
/* Update the in/out-Vectors now */ |
|
|
|
updateInOut(succ, true, jumps); |
|
|
|
updateInOut(succ, true, jumps); |
|
|
|
|
|
|
|
|
|
|
|
/* Prepare the unification of the blocks: Make sure if |
|
|
|
|
|
|
|
* possible that appendBlock has a successor outside of |
|
|
|
|
|
|
|
* this block. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* This doesn't change the semantics, since appendBlock |
|
|
|
|
|
|
|
* is the last block that could be modified. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (appendBlock.jump == null) { |
|
|
|
|
|
|
|
Jump jump = new Jump(succ); |
|
|
|
|
|
|
|
appendBlock.setJump(jump); |
|
|
|
|
|
|
|
jumps.push(jump); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Now unify the blocks: Create a new SequentialBlock |
|
|
|
|
|
|
|
* containing appendBlock and successor.block. Then replace |
|
|
|
|
|
|
|
* appendBlock with the new sequential block. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
SequentialBlock sequBlock = |
|
|
|
|
|
|
|
new SequentialBlock(); |
|
|
|
|
|
|
|
sequBlock.replace(appendBlock, appendBlock); |
|
|
|
|
|
|
|
sequBlock.setFirst(appendBlock); |
|
|
|
|
|
|
|
sequBlock.setSecond(succ.block); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mergeSuccessors(succ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
optimizeJumps(jumps); |
|
|
|
|
|
|
|
resolveRemaining(jumps); |
|
|
|
|
|
|
|
|
|
|
|
/* appendBlock may be zero, if this is the switchcase with |
|
|
|
/* Now unify the blocks. |
|
|
|
* precedingcase = null. But in this case, there can't be |
|
|
|
|
|
|
|
* any jumps. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (appendBlock != null) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
appendBlock = optimizeJumps(appendBlock, jumps); |
|
|
|
|
|
|
|
appendBlock = resolveRemaining(appendBlock, jumps); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Believe it or not: Now the rule, that the first part of a |
|
|
|
|
|
|
|
* SequentialBlock shouldn't be another SequentialBlock is |
|
|
|
|
|
|
|
* fulfilled. <p> |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* This isn't easy to prove, it has a lot to do with the |
|
|
|
|
|
|
|
* transformation in optimizeJump and the fact that |
|
|
|
|
|
|
|
* appendBlock was the innermost Block containing all jumps |
|
|
|
|
|
|
|
* and lastModified. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
lastModified.appendBlock(succ.block); |
|
|
|
|
|
|
|
mergeSuccessors(succ); |
|
|
|
|
|
|
|
|
|
|
|
/* Set last modified to correct value. */ |
|
|
|
/* Set last modified to the new correct value. */ |
|
|
|
lastModified = succ.lastModified; |
|
|
|
lastModified = succ.lastModified; |
|
|
|
|
|
|
|
|
|
|
|
/* Set addr+length to (semi-)correct value */ |
|
|
|
/* Set addr+length to correct value. */ |
|
|
|
if (succ.addr < addr) |
|
|
|
if (succ.addr < addr) |
|
|
|
addr = succ.addr; |
|
|
|
addr = succ.addr; |
|
|
|
length += succ.length; |
|
|
|
length += succ.length; |
|
|
@ -791,14 +738,9 @@ public class FlowBlock { |
|
|
|
/* Creating a for block didn't succeed; create a |
|
|
|
/* Creating a for block didn't succeed; create a |
|
|
|
* while block instead. */ |
|
|
|
* while block instead. */ |
|
|
|
|
|
|
|
|
|
|
|
/* Prepare the unification of the blocks: Make sure that |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
* bodyBlock has a jump. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (bodyBlock.jump == null) { |
|
|
|
optimizeJumps(jumps); |
|
|
|
Jump jump = new Jump(this); |
|
|
|
|
|
|
|
bodyBlock.setJump(jump); |
|
|
|
|
|
|
|
jumps.push(jump); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LoopBlock whileBlock = |
|
|
|
LoopBlock whileBlock = |
|
|
|
new LoopBlock(LoopBlock.WHILE, LoopBlock.TRUE); |
|
|
|
new LoopBlock(LoopBlock.WHILE, LoopBlock.TRUE); |
|
|
@ -806,10 +748,6 @@ public class FlowBlock { |
|
|
|
whileBlock.replace(bodyBlock, bodyBlock); |
|
|
|
whileBlock.replace(bodyBlock, bodyBlock); |
|
|
|
whileBlock.setBody(bodyBlock); |
|
|
|
whileBlock.setBody(bodyBlock); |
|
|
|
|
|
|
|
|
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
bodyBlock = optimizeJumps(bodyBlock, jumps); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if there are further jumps to this, replace every jump with a |
|
|
|
/* if there are further jumps to this, replace every jump with a |
|
|
|
* continue to while block and return true. |
|
|
|
* continue to while block and return true. |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -876,7 +814,6 @@ public class FlowBlock { |
|
|
|
Stack jumps = new Stack(); |
|
|
|
Stack jumps = new Stack(); |
|
|
|
Stack allJumps = (Stack) successors.remove(END_OF_METHOD); |
|
|
|
Stack allJumps = (Stack) successors.remove(END_OF_METHOD); |
|
|
|
Enumeration enum = allJumps.elements(); |
|
|
|
Enumeration enum = allJumps.elements(); |
|
|
|
StructuredBlock appendBlock = lastModified; |
|
|
|
|
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
|
|
|
|
|
|
|
@ -886,19 +823,11 @@ public class FlowBlock { |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
jumps.push(jump); |
|
|
|
jumps.push(jump); |
|
|
|
|
|
|
|
|
|
|
|
while (!appendBlock.contains(jump.prev)) |
|
|
|
|
|
|
|
appendBlock = appendBlock.outer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* appendBlock can't be null now, because the |
|
|
|
|
|
|
|
* outermost block contains every structured block. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
appendBlock = optimizeJumps(appendBlock, jumps); |
|
|
|
optimizeJumps(jumps); |
|
|
|
|
|
|
|
|
|
|
|
next_jump: |
|
|
|
next_jump: |
|
|
|
while (!jumps.isEmpty()) { |
|
|
|
while (!jumps.isEmpty()) { |
|
|
@ -906,14 +835,13 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock prevBlock = jump.prev; |
|
|
|
StructuredBlock prevBlock = jump.prev; |
|
|
|
|
|
|
|
|
|
|
|
if (prevBlock == appendBlock) |
|
|
|
if (lastModified == prevBlock) |
|
|
|
/* handled later */ |
|
|
|
/* handled later */ |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
BreakableBlock breakToBlock = null; |
|
|
|
BreakableBlock breakToBlock = null; |
|
|
|
for (StructuredBlock surrounder = prevBlock.outer; |
|
|
|
for (StructuredBlock surrounder = prevBlock.outer; |
|
|
|
surrounder != null && surrounder != appendBlock.outer; |
|
|
|
surrounder != null; surrounder = surrounder.outer) { |
|
|
|
surrounder = surrounder.outer) { |
|
|
|
|
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
if (surrounder.getNextFlowBlock() == END_OF_METHOD) |
|
|
|
if (surrounder.getNextFlowBlock() == END_OF_METHOD) |
|
|
|
breakToBlock = (BreakableBlock) surrounder; |
|
|
|
breakToBlock = (BreakableBlock) surrounder; |
|
|
@ -935,12 +863,12 @@ public class FlowBlock { |
|
|
|
(new BreakBlock(breakToBlock, false)); |
|
|
|
(new BreakBlock(breakToBlock, false)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Now remove the jump of the appendBlock if it points to |
|
|
|
/* Now remove the jump of the lastModified if it points to |
|
|
|
* successor. |
|
|
|
* END_OF_METHOD. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (appendBlock.jump != null |
|
|
|
if (lastModified.jump != null |
|
|
|
&& appendBlock.jump.destination == END_OF_METHOD) |
|
|
|
&& lastModified.jump.destination == END_OF_METHOD) |
|
|
|
appendBlock.removeJump(); |
|
|
|
lastModified.removeJump(); |
|
|
|
|
|
|
|
|
|
|
|
/* transformation succeeded */ |
|
|
|
/* transformation succeeded */ |
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
@ -1400,19 +1328,12 @@ public class FlowBlock { |
|
|
|
throw new AssertError("try == catch"); |
|
|
|
throw new AssertError("try == catch"); |
|
|
|
|
|
|
|
|
|
|
|
boolean changed = false; |
|
|
|
boolean changed = false; |
|
|
|
tryFlow.analyze(addr, catchFlow.addr); |
|
|
|
while(tryFlow.analyze(addr, catchFlow.addr)); |
|
|
|
catchFlow.analyze(catchFlow.addr, end); |
|
|
|
while(catchFlow.analyze(catchFlow.addr, end)); |
|
|
|
|
|
|
|
|
|
|
|
updateInOut(tryFlow, true, (Stack) successors.remove(tryFlow)); |
|
|
|
updateInOut(tryFlow, true, (Stack) successors.remove(tryFlow)); |
|
|
|
rawBlock.tryBlock.removeJump(); |
|
|
|
|
|
|
|
tryFlow.getBlock().replace(rawBlock.tryBlock, null); |
|
|
|
|
|
|
|
mergeSuccessors(tryFlow); |
|
|
|
|
|
|
|
length += tryFlow.length; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
updateInOut(catchFlow, true, (Stack) successors.remove(catchFlow)); |
|
|
|
updateInOut(catchFlow, true, (Stack) successors.remove(catchFlow)); |
|
|
|
rawBlock.catchBlock.removeJump(); |
|
|
|
length += tryFlow.length; |
|
|
|
catchFlow.block.replace(rawBlock.catchBlock, null); |
|
|
|
|
|
|
|
mergeSuccessors(catchFlow); |
|
|
|
|
|
|
|
length += catchFlow.length; |
|
|
|
length += catchFlow.length; |
|
|
|
|
|
|
|
|
|
|
|
if (rawBlock.type != null) { |
|
|
|
if (rawBlock.type != null) { |
|
|
@ -1426,11 +1347,15 @@ public class FlowBlock { |
|
|
|
* | ... |
|
|
|
* | ... |
|
|
|
* `- catch block |
|
|
|
* `- catch block |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
CatchBlock newBlock = new CatchBlock(rawBlock.type); |
|
|
|
CatchBlock newBlock = new CatchBlock(rawBlock.type); |
|
|
|
newBlock.replace(rawBlock, rawBlock); |
|
|
|
newBlock.replace(rawBlock, rawBlock); |
|
|
|
newBlock.setTryBlock(rawBlock.tryBlock); |
|
|
|
newBlock.moveJump(rawBlock.jump); |
|
|
|
newBlock.setCatchBlock(rawBlock.catchBlock); |
|
|
|
|
|
|
|
|
|
|
|
newBlock.setTryBlock(tryFlow.block); |
|
|
|
|
|
|
|
mergeSuccessors(tryFlow); |
|
|
|
|
|
|
|
newBlock.setCatchBlock(catchFlow.block); |
|
|
|
|
|
|
|
mergeSuccessors(catchFlow); |
|
|
|
|
|
|
|
|
|
|
|
lastModified = newBlock; |
|
|
|
lastModified = newBlock; |
|
|
|
changed = true; |
|
|
|
changed = true; |
|
|
|
} else if (catchFlow.block instanceof SequentialBlock |
|
|
|
} else if (catchFlow.block instanceof SequentialBlock |
|
|
@ -1473,21 +1398,25 @@ public class FlowBlock { |
|
|
|
* return_n |
|
|
|
* return_n |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
/* First remove the jump after the throw */ |
|
|
|
/* Now remove the jump (after the throw) from the |
|
|
|
removeSuccessor(catchBlock.subBlocks[1].jump); |
|
|
|
* catch block so that we can forget about it. |
|
|
|
catchBlock.subBlocks[1].removeJump(); |
|
|
|
*/ |
|
|
|
|
|
|
|
catchBlock.subBlocks[1] |
|
|
|
|
|
|
|
.jump.destination.predecessors.removeElement(catchFlow); |
|
|
|
|
|
|
|
|
|
|
|
ComplexExpression monexit = (ComplexExpression) |
|
|
|
ComplexExpression monexit = (ComplexExpression) |
|
|
|
((InstructionBlock) catchBlock.subBlocks[0]).instr; |
|
|
|
((InstructionBlock) catchBlock.subBlocks[0]).instr; |
|
|
|
LocalInfo local = |
|
|
|
LocalInfo local = |
|
|
|
((LocalLoadOperator)monexit.getSubExpressions()[0]) |
|
|
|
((LocalLoadOperator)monexit.getSubExpressions()[0]) |
|
|
|
.getLocalInfo(); |
|
|
|
.getLocalInfo(); |
|
|
|
|
|
|
|
|
|
|
|
checkAndRemoveMonitorExit(local, end); |
|
|
|
checkAndRemoveMonitorExit(local, end); |
|
|
|
|
|
|
|
|
|
|
|
SynchronizedBlock syncBlock = new SynchronizedBlock(local); |
|
|
|
SynchronizedBlock syncBlock = new SynchronizedBlock(local); |
|
|
|
syncBlock.replace(rawBlock, rawBlock); |
|
|
|
syncBlock.replace(rawBlock, rawBlock); |
|
|
|
syncBlock.moveJump(rawBlock.jump); |
|
|
|
syncBlock.moveJump(rawBlock.jump); |
|
|
|
syncBlock.setBodyBlock(rawBlock.tryBlock); |
|
|
|
syncBlock.setBodyBlock(tryFlow.block); |
|
|
|
|
|
|
|
mergeSuccessors(tryFlow); |
|
|
|
lastModified = syncBlock; |
|
|
|
lastModified = syncBlock; |
|
|
|
changed = true; |
|
|
|
changed = true; |
|
|
|
|
|
|
|
|
|
|
@ -1531,16 +1460,12 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
/* Now remove the two jumps of the catch block |
|
|
|
/* Now remove the two jumps of the catch block |
|
|
|
* so that we can forget about them. |
|
|
|
* so that we can forget about them. |
|
|
|
* This are the throw and the jsr. |
|
|
|
* This are the jsr and the throw. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
removeSuccessor(catchBlock.subBlocks[1] |
|
|
|
catchBlock.subBlocks[1].getSubBlocks()[0].getSubBlocks()[0] |
|
|
|
.getSubBlocks()[1].jump); |
|
|
|
.jump.destination.predecessors.removeElement(catchFlow); |
|
|
|
removeSuccessor(catchBlock.subBlocks[1] |
|
|
|
catchBlock.subBlocks[1].getSubBlocks()[1] |
|
|
|
.getSubBlocks()[0].getSubBlocks()[0].jump); |
|
|
|
.jump.destination.predecessors.removeElement(catchFlow); |
|
|
|
catchBlock.subBlocks[1].getSubBlocks()[1].removeJump(); |
|
|
|
|
|
|
|
catchBlock.subBlocks[1] |
|
|
|
|
|
|
|
.getSubBlocks()[0].getSubBlocks()[0].removeJump(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
subRoutine.analyzeSubRoutine(addr+length, end); |
|
|
|
subRoutine.analyzeSubRoutine(addr+length, end); |
|
|
|
updateInOut(subRoutine, true, |
|
|
|
updateInOut(subRoutine, true, |
|
|
@ -1552,7 +1477,8 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
CatchFinallyBlock newBlock = new CatchFinallyBlock(); |
|
|
|
CatchFinallyBlock newBlock = new CatchFinallyBlock(); |
|
|
|
newBlock.replace(rawBlock, rawBlock); |
|
|
|
newBlock.replace(rawBlock, rawBlock); |
|
|
|
newBlock.setTryBlock(rawBlock.tryBlock); |
|
|
|
newBlock.setTryBlock(tryFlow.block); |
|
|
|
|
|
|
|
mergeSuccessors(tryFlow); |
|
|
|
newBlock.setFinallyBlock(subRoutine.block); |
|
|
|
newBlock.setFinallyBlock(subRoutine.block); |
|
|
|
newBlock.moveJump(rawBlock.jump); |
|
|
|
newBlock.moveJump(rawBlock.jump); |
|
|
|
lastModified = newBlock; |
|
|
|
lastModified = newBlock; |
|
|
@ -1584,14 +1510,15 @@ public class FlowBlock { |
|
|
|
jumps.push(jump); |
|
|
|
jumps.push(jump); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
optimizeJumps(rawBlock.tryBlock, jumps); |
|
|
|
lastModified = tryFlow.lastModified; |
|
|
|
resolveRemaining(rawBlock.tryBlock, jumps); |
|
|
|
optimizeJumps(jumps); |
|
|
|
|
|
|
|
resolveRemaining(jumps); |
|
|
|
|
|
|
|
|
|
|
|
CatchFinallyBlock newBlock = new CatchFinallyBlock(); |
|
|
|
CatchFinallyBlock newBlock = new CatchFinallyBlock(); |
|
|
|
newBlock.replace(rawBlock, rawBlock); |
|
|
|
newBlock.replace(rawBlock, rawBlock); |
|
|
|
newBlock.setTryBlock(rawBlock.tryBlock); |
|
|
|
newBlock.setTryBlock(rawBlock.tryBlock); |
|
|
|
if (succ.predecessors.size() == 1) { |
|
|
|
if (succ.predecessors.size() == 1) { |
|
|
|
succ.analyze(addr+length, end); |
|
|
|
while (succ.analyze(addr+length, end)); |
|
|
|
length += succ.length; |
|
|
|
length += succ.length; |
|
|
|
successors.remove(succ); |
|
|
|
successors.remove(succ); |
|
|
|
newBlock.setFinallyBlock(succ.block); |
|
|
|
newBlock.setFinallyBlock(succ.block); |
|
|
@ -1649,72 +1576,87 @@ public class FlowBlock { |
|
|
|
public boolean analyzeSwitch(int start, int end) { |
|
|
|
public boolean analyzeSwitch(int start, int end) { |
|
|
|
SwitchBlock switchBlock = (SwitchBlock) block; |
|
|
|
SwitchBlock switchBlock = (SwitchBlock) block; |
|
|
|
boolean changed = false; |
|
|
|
boolean changed = false; |
|
|
|
StructuredBlock lastBlock = null; |
|
|
|
int last = -1; |
|
|
|
|
|
|
|
FlowBlock lastFlow = null; |
|
|
|
for (int i=0; i < switchBlock.caseBlocks.length; i++) { |
|
|
|
for (int i=0; i < switchBlock.caseBlocks.length; i++) { |
|
|
|
if (switchBlock.caseBlocks[i].subBlock != null |
|
|
|
if (switchBlock.caseBlocks[i].subBlock != null |
|
|
|
&& switchBlock.caseBlocks[i].subBlock.jump != null) { |
|
|
|
&& switchBlock.caseBlocks[i].subBlock.jump != null) { |
|
|
|
FlowBlock next = switchBlock.caseBlocks[i]. |
|
|
|
FlowBlock nextFlow = switchBlock.caseBlocks[i]. |
|
|
|
subBlock.jump.destination; |
|
|
|
subBlock.jump.destination; |
|
|
|
if (next.addr >= end) |
|
|
|
if (nextFlow.addr >= end) |
|
|
|
return changed; |
|
|
|
break; |
|
|
|
else if (next.addr >= start) { |
|
|
|
else if (nextFlow.addr >= start) { |
|
|
|
|
|
|
|
|
|
|
|
/* First analyze the next block. It may |
|
|
|
/* First analyze the nextFlow block. It may |
|
|
|
* return early after a T2 trafo so call it |
|
|
|
* return early after a T2 trafo so call it |
|
|
|
* until nothing more is possible. |
|
|
|
* until nothing more is possible. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
while (next.analyze(addr + length, end)) |
|
|
|
while (nextFlow.analyze(addr + length, end)) |
|
|
|
changed = changed || true; |
|
|
|
changed = changed || true; |
|
|
|
|
|
|
|
|
|
|
|
if (next.addr != addr + length) |
|
|
|
if (nextFlow.addr != addr + length) |
|
|
|
return changed; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
/* Check if next has only the previous case |
|
|
|
/* Check if nextFlow has only the previous case |
|
|
|
* and this case as predecessor. Otherwise |
|
|
|
* and this case as predecessor. Otherwise |
|
|
|
* break the analysis. |
|
|
|
* break the analysis. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (next.predecessors.size() != 1 |
|
|
|
if (nextFlow.predecessors.size() > 2 |
|
|
|
|| next.predecessors.elementAt(0) != this) |
|
|
|
|| (nextFlow.predecessors.size() > 1 |
|
|
|
return changed; |
|
|
|
&& (lastFlow == null |
|
|
|
|
|
|
|
|| !nextFlow.predecessors.contains(lastFlow))) |
|
|
|
|
|
|
|
|| ((Stack)successors.get(nextFlow)).size() > 1) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
boolean lastContains = false; |
|
|
|
checkConsistent(); |
|
|
|
Stack jumps = new Stack(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Enumeration enum = |
|
|
|
Stack jumps = (Stack) successors.remove(nextFlow); |
|
|
|
((Stack) successors.get(next)).elements(); |
|
|
|
/* note that jumps.size() == 1 */ |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
|
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
|
|
|
|
if (jump == switchBlock.caseBlocks[i].subBlock.jump) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
jumps.push(jump); |
|
|
|
if (nextFlow.predecessors.size() == 2) { |
|
|
|
if (lastBlock == null |
|
|
|
Stack lastJumps = |
|
|
|
|| !lastBlock.contains(jump.prev)) |
|
|
|
(Stack) lastFlow.successors.remove(nextFlow); |
|
|
|
|
|
|
|
|
|
|
|
return changed; |
|
|
|
/* Do the in/out analysis with all jumps |
|
|
|
|
|
|
|
* Note that this won't update lastFlow.in, but |
|
|
|
|
|
|
|
* this will not be used anymore. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
lastJumps.push(jumps.peek()); |
|
|
|
|
|
|
|
updateInOut(nextFlow, true, lastJumps); |
|
|
|
|
|
|
|
lastJumps.pop(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lastFlow.optimizeJumps(jumps); |
|
|
|
|
|
|
|
lastFlow.resolveRemaining(jumps); |
|
|
|
|
|
|
|
} else |
|
|
|
|
|
|
|
updateInOut(nextFlow, true, jumps); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (lastFlow != null) { |
|
|
|
|
|
|
|
lastFlow.block.replace |
|
|
|
|
|
|
|
(switchBlock.caseBlocks[last].subBlock, null); |
|
|
|
|
|
|
|
mergeSuccessors(lastFlow); |
|
|
|
} |
|
|
|
} |
|
|
|
checkConsistent(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
updateInOut(next, true, (Stack) successors.remove(next)); |
|
|
|
/* We merge the blocks into the caseBlock later, but |
|
|
|
switchBlock.caseBlocks[i].subBlock.removeJump(); |
|
|
|
* that doesn't affect consistency. |
|
|
|
next.block.replace(switchBlock.caseBlocks[i].subBlock, |
|
|
|
*/ |
|
|
|
null); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mergeSuccessors(next); |
|
|
|
switchBlock.caseBlocks[i].subBlock.removeJump(); |
|
|
|
if (!jumps.isEmpty()) { |
|
|
|
length += nextFlow.length; |
|
|
|
lastBlock = optimizeJumps(lastBlock, jumps); |
|
|
|
|
|
|
|
lastBlock = resolveRemaining(lastBlock, jumps); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Set length to correct value */ |
|
|
|
lastFlow = nextFlow; |
|
|
|
length += next.length; |
|
|
|
last = i; |
|
|
|
|
|
|
|
|
|
|
|
lastBlock = next.block; |
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
changed = true; |
|
|
|
changed = true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (lastFlow != null) { |
|
|
|
|
|
|
|
lastFlow.block.replace |
|
|
|
|
|
|
|
(switchBlock.caseBlocks[last].subBlock, null); |
|
|
|
|
|
|
|
mergeSuccessors(lastFlow); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
return changed; |
|
|
|
return changed; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|