|
|
@ -131,7 +131,7 @@ public class FlowBlock { |
|
|
|
newBlock.setCatchBlock(catchBlock); |
|
|
|
newBlock.setCatchBlock(catchBlock); |
|
|
|
if (sequBlock.jump != null) { |
|
|
|
if (sequBlock.jump != null) { |
|
|
|
if (newBlock.catchBlock.jump == null) |
|
|
|
if (newBlock.catchBlock.jump == null) |
|
|
|
newBlock.catchBlock.moveJump(sequBlock); |
|
|
|
newBlock.catchBlock.moveJump(sequBlock.jump); |
|
|
|
else |
|
|
|
else |
|
|
|
sequBlock.removeJump(); |
|
|
|
sequBlock.removeJump(); |
|
|
|
} |
|
|
|
} |
|
|
@ -156,156 +156,79 @@ public class FlowBlock { |
|
|
|
if (jump == null || jump.destination != successor) |
|
|
|
if (jump == null || jump.destination != successor) |
|
|
|
continue next_jump; |
|
|
|
continue next_jump; |
|
|
|
|
|
|
|
|
|
|
|
same_jump: while(true) { |
|
|
|
while(jump != null) { |
|
|
|
/* if the jump is the jump of the appendBlock, skip it. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (jump.prev == null || jump.prev == appendBlock) |
|
|
|
|
|
|
|
continue next_jump; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Note: jump.prev.outer != null, since appendBlock is |
|
|
|
if (jump.prev instanceof EmptyBlock |
|
|
|
* an outer block of jump.prev |
|
|
|
&& jump.prev.outer != null |
|
|
|
*/ |
|
|
|
&& jump.prev.outer instanceof ConditionalBlock |
|
|
|
|
|
|
|
&& jump.prev.outer.jump != null) { |
|
|
|
|
|
|
|
|
|
|
|
/* remove all jumps to the successor which have the successor |
|
|
|
if (jump.prev.outer.jump.destination == jump.destination) { |
|
|
|
* as getNextFlowBlock(). |
|
|
|
/* This is a weired "if (cond) empty"-block. We |
|
|
|
|
|
|
|
* transform it by hand. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (jump.prev.outer.getNextFlowBlock(jump.prev) == successor) { |
|
|
|
|
|
|
|
jump.prev.removeJump(); |
|
|
|
jump.prev.removeJump(); |
|
|
|
continue next_jump; |
|
|
|
continue next_jump; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* replace all conditional jumps to the successor, which |
|
|
|
/* Swap conditional blocks, that have two jumps, and where |
|
|
|
* are followed by a block which has the end of the block |
|
|
|
* this jump is the inner jump. |
|
|
|
* as normal successor, with "if (not condition) block". |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (jump.prev instanceof EmptyBlock && |
|
|
|
|
|
|
|
jump.prev.outer instanceof ConditionalBlock) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock prev = jump.prev; |
|
|
|
StructuredBlock prev = jump.prev; |
|
|
|
ConditionalBlock cb = (ConditionalBlock) prev.outer; |
|
|
|
ConditionalBlock cb = (ConditionalBlock) prev.outer; |
|
|
|
jode.Instruction instr = cb.getInstruction(); |
|
|
|
jode.Instruction instr = cb.getInstruction(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* XXX Expression clean up is necessary. Otherwise |
|
|
|
if ((cb == appendBlock || |
|
|
|
* this may lead to a ClassCastException. |
|
|
|
cb.outer.getNextFlowBlock(cb) == successor |
|
|
|
* |
|
|
|
/*XXX jumpMayBeChanged()??? */) && |
|
|
|
* Our code below _depends_ on the fact that this |
|
|
|
instr instanceof jode.Expression) { |
|
|
|
* transformation is done. |
|
|
|
|
|
|
|
*/ |
|
|
|
cb.setInstruction(((jode.Expression)instr).negate()); |
|
|
|
cb.setInstruction(((jode.Expression)instr).negate()); |
|
|
|
prev.removeJump(); |
|
|
|
cb.swapJump(jump.prev); |
|
|
|
prev.moveJump(cb); |
|
|
|
|
|
|
|
continue next_jump; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* cb.outer is not null, |
|
|
|
|
|
|
|
* since appendBlock outers cb */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (cb.outer instanceof SequentialBlock && |
|
|
|
|
|
|
|
cb.outer.getSubBlocks()[0] == cb && |
|
|
|
|
|
|
|
(cb.outer.getNextFlowBlock() == successor || |
|
|
|
|
|
|
|
cb.outer.jumpMayBeChanged()) && |
|
|
|
|
|
|
|
instr instanceof jode.Expression) { |
|
|
|
|
|
|
|
SequentialBlock sequBlock = |
|
|
|
|
|
|
|
(SequentialBlock) cb.outer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IfThenElseBlock newIfBlock = |
|
|
|
|
|
|
|
new IfThenElseBlock(((jode.Expression)instr).negate()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
newIfBlock.replace(sequBlock, sequBlock.getSubBlocks()[1]); |
|
|
|
|
|
|
|
newIfBlock.setThenBlock(sequBlock.getSubBlocks()[1]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
newIfBlock.moveJump(sequBlock); |
|
|
|
|
|
|
|
if (appendBlock == sequBlock) |
|
|
|
|
|
|
|
appendBlock = newIfBlock; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (newIfBlock.getNextFlowBlock() != successor && |
|
|
|
|
|
|
|
newIfBlock != appendBlock) { |
|
|
|
|
|
|
|
newIfBlock.moveJump(prev); |
|
|
|
|
|
|
|
continue same_jump; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
prev.removeJump(); |
|
|
|
|
|
|
|
continue next_jump; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* if there are jumps in an if-then block, which |
|
|
|
/* Now move the jump as far to the outer as possible, |
|
|
|
* have as normal successor the end of the if-then block, and |
|
|
|
* without leaving appendBlock. |
|
|
|
* the if-then block is followed by a single block, then replace |
|
|
|
* |
|
|
|
* the if-then block with a if-then-else block and remove the |
|
|
|
* Note: jump.prev != appendblock implies |
|
|
|
* unconditional jump. |
|
|
|
* jump.prev.outer != null, since appendBlock is an outer |
|
|
|
|
|
|
|
* block of jump.prev |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
StructuredBlock elseBlock = |
|
|
|
while (jump.prev != appendBlock |
|
|
|
jump.prev.outer.getNextBlock(jump.prev); |
|
|
|
&& jump.prev.outer.isSingleExit(jump.prev)) { |
|
|
|
if (elseBlock != null |
|
|
|
jump.prev.outer.moveJump(jump); |
|
|
|
&& elseBlock.outer != null |
|
|
|
} |
|
|
|
&& elseBlock.outer instanceof SequentialBlock |
|
|
|
|
|
|
|
&& elseBlock.outer.getSubBlocks()[0] instanceof IfThenElseBlock |
|
|
|
|
|
|
|
&& (elseBlock.outer.getNextFlowBlock() == successor |
|
|
|
|
|
|
|
|| elseBlock.outer.jumpMayBeChanged())) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IfThenElseBlock ifBlock = |
|
|
|
|
|
|
|
(IfThenElseBlock)elseBlock.outer.getSubBlocks()[0]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ifBlock.getSubBlocks().length == 1) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* make sure that only sequential blocks are between |
|
|
|
/* if the jump is the jump of the appendBlock, skip it. |
|
|
|
* jump.prev and the ifBlock |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
StructuredBlock block = jump.prev.outer; |
|
|
|
if (jump.prev == appendBlock) |
|
|
|
while (block instanceof SequentialBlock) |
|
|
|
continue next_jump; |
|
|
|
block = block.outer; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (block == ifBlock) { |
|
|
|
|
|
|
|
elseBlock.outer.removeJump(); |
|
|
|
|
|
|
|
ifBlock.replace(elseBlock.outer, elseBlock); |
|
|
|
|
|
|
|
if (appendBlock == elseBlock.outer) |
|
|
|
|
|
|
|
appendBlock = ifBlock; |
|
|
|
|
|
|
|
ifBlock.moveJump(jump.prev); |
|
|
|
|
|
|
|
ifBlock.setElseBlock(elseBlock); |
|
|
|
|
|
|
|
continue same_jump; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if the successor is the dummy return instruction, replace all |
|
|
|
/* remove this jump if it jumps to the getNextFlowBlock(). |
|
|
|
* jumps with a return. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (successor == END_OF_METHOD) { |
|
|
|
if (jump.prev.outer.getNextFlowBlock(jump.prev) == successor) { |
|
|
|
SequentialBlock sequBlock = new SequentialBlock(); |
|
|
|
jump.prev.removeJump(); |
|
|
|
StructuredBlock prevBlock = jump.prev; |
|
|
|
|
|
|
|
prevBlock.removeJump(); |
|
|
|
|
|
|
|
if (prevBlock instanceof EmptyBlock) { |
|
|
|
|
|
|
|
if (prevBlock.outer instanceof ConditionalBlock) { |
|
|
|
|
|
|
|
IfThenElseBlock ifBlock = |
|
|
|
|
|
|
|
new IfThenElseBlock |
|
|
|
|
|
|
|
(((ConditionalBlock)prevBlock.outer). |
|
|
|
|
|
|
|
getInstruction()); |
|
|
|
|
|
|
|
ifBlock.replace(prevBlock.outer, prevBlock); |
|
|
|
|
|
|
|
ifBlock.moveJump(prevBlock.outer); |
|
|
|
|
|
|
|
ifBlock.setThenBlock(prevBlock); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
new ReturnBlock().replace(prevBlock, null); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
sequBlock.replace(prevBlock, prevBlock); |
|
|
|
|
|
|
|
sequBlock.setFirst(prevBlock); |
|
|
|
|
|
|
|
sequBlock.setSecond(new ReturnBlock()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
continue next_jump; |
|
|
|
continue next_jump; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* If this is a conditional jump, the first instruction of |
|
|
|
|
|
|
|
* a while and the condition of the while is true, use |
|
|
|
|
|
|
|
* the condition as while condition. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (jump.prev instanceof EmptyBlock && |
|
|
|
if (jump.prev instanceof EmptyBlock && |
|
|
|
jump.prev.outer instanceof ConditionalBlock && |
|
|
|
jump.prev.outer instanceof ConditionalBlock) { |
|
|
|
jump.prev.outer.jump == null) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock prev = jump.prev; |
|
|
|
StructuredBlock prev = jump.prev; |
|
|
|
ConditionalBlock cb = (ConditionalBlock) prev.outer; |
|
|
|
ConditionalBlock cb = (ConditionalBlock) prev.outer; |
|
|
|
jode.Instruction instr = cb.getInstruction(); |
|
|
|
jode.Instruction instr = cb.getInstruction(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* cb.jump is null (see above), so cb must have a * |
|
|
|
|
|
|
|
* successor in this block, that means cb.outer is not |
|
|
|
|
|
|
|
* null. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* If this is the first instruction of a while and the |
|
|
|
|
|
|
|
* condition of the while is true, use the condition |
|
|
|
|
|
|
|
* as while condition. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
/* This is the first instruction in a while block */ |
|
|
|
/* This is the first instruction in a while block */ |
|
|
|
if (cb.outer instanceof SequentialBlock && |
|
|
|
if (cb.outer instanceof SequentialBlock && |
|
|
|
cb.outer.getSubBlocks()[0] == cb && |
|
|
|
cb.outer.getSubBlocks()[0] == cb && |
|
|
@ -320,10 +243,14 @@ public class FlowBlock { |
|
|
|
prev.removeJump(); |
|
|
|
prev.removeJump(); |
|
|
|
loopBlock.setCondition(((Expression)instr).negate()); |
|
|
|
loopBlock.setCondition(((Expression)instr).negate()); |
|
|
|
if (cb.outer.jump != null) { |
|
|
|
if (cb.outer.jump != null) { |
|
|
|
if (cb.outer.getSubBlocks()[1].jump != null) |
|
|
|
/* XXX can this happen */ |
|
|
|
|
|
|
|
if (cb.outer.getSubBlocks()[1].jump != null) { |
|
|
|
|
|
|
|
/* XXX if above can happen, |
|
|
|
|
|
|
|
* can this happen at all??? */ |
|
|
|
cb.outer.removeJump(); |
|
|
|
cb.outer.removeJump(); |
|
|
|
else |
|
|
|
} else |
|
|
|
cb.outer.getSubBlocks()[1].moveJump(cb.outer); |
|
|
|
cb.outer.getSubBlocks()[1]. |
|
|
|
|
|
|
|
moveJump(cb.outer.jump); |
|
|
|
} |
|
|
|
} |
|
|
|
cb.outer.getSubBlocks()[1].replace |
|
|
|
cb.outer.getSubBlocks()[1].replace |
|
|
|
(cb.outer, cb.outer.getSubBlocks()[1]); |
|
|
|
(cb.outer, cb.outer.getSubBlocks()[1]); |
|
|
@ -354,58 +281,134 @@ public class FlowBlock { |
|
|
|
continue next_jump; |
|
|
|
continue next_jump; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if there are jumps in a while block or switch block and the |
|
|
|
/* replace all conditional jumps to the successor, which |
|
|
|
* while/switch block is followed by a jump to successor or has |
|
|
|
* are followed by a block which has the end of the block |
|
|
|
* successor as getNextFlowBlock(), replace jump with break to |
|
|
|
* as normal successor, with "if (not condition) block". |
|
|
|
* the innermost such while/switch block. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* If the switch block hasn't been breaked before we could |
|
|
|
|
|
|
|
* take some heuristics and add a jump after the switch to |
|
|
|
|
|
|
|
* succesor, so that the above succeeds. |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
int breaklevel = 0; |
|
|
|
if (cb.outer instanceof SequentialBlock && |
|
|
|
for (StructuredBlock surrounder = jump.prev.outer; |
|
|
|
cb.outer.getSubBlocks()[0] == cb && |
|
|
|
surrounder != null && surrounder != appendBlock.outer; |
|
|
|
(cb.outer.getNextFlowBlock() == successor || |
|
|
|
surrounder = surrounder.outer) { |
|
|
|
cb.outer.jumpMayBeChanged()) && |
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
instr instanceof jode.Expression) { |
|
|
|
breaklevel++; |
|
|
|
SequentialBlock sequBlock = |
|
|
|
if (surrounder.getNextFlowBlock() == successor || |
|
|
|
(SequentialBlock) cb.outer; |
|
|
|
surrounder.jumpMayBeChanged()) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SequentialBlock sequBlock = new SequentialBlock(); |
|
|
|
IfThenElseBlock newIfBlock = |
|
|
|
StructuredBlock prevBlock = jump.prev; |
|
|
|
new IfThenElseBlock(((jode.Expression)instr).negate()); |
|
|
|
if (surrounder.getNextFlowBlock() != successor) |
|
|
|
|
|
|
|
surrounder.moveJump(prevBlock); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
prevBlock.removeJump(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (prevBlock instanceof EmptyBlock) { |
|
|
|
newIfBlock.replace(sequBlock, sequBlock.getSubBlocks()[1]); |
|
|
|
if (prevBlock.outer instanceof ConditionalBlock) { |
|
|
|
newIfBlock.setThenBlock(sequBlock.getSubBlocks()[1]); |
|
|
|
IfThenElseBlock ifBlock = |
|
|
|
|
|
|
|
new IfThenElseBlock |
|
|
|
newIfBlock.moveJump(sequBlock.jump); |
|
|
|
(((ConditionalBlock)prevBlock.outer) |
|
|
|
if (appendBlock == sequBlock) |
|
|
|
.getInstruction()); |
|
|
|
appendBlock = newIfBlock; |
|
|
|
ifBlock.replace(prevBlock.outer, prevBlock); |
|
|
|
|
|
|
|
ifBlock.moveJump(prevBlock.outer); |
|
|
|
if (newIfBlock.getNextFlowBlock() != successor && |
|
|
|
ifBlock.setThenBlock(prevBlock); |
|
|
|
newIfBlock != appendBlock) { |
|
|
|
} |
|
|
|
newIfBlock.moveJump(jump); |
|
|
|
new BreakBlock((BreakableBlock) surrounder, |
|
|
|
continue; |
|
|
|
breaklevel >1 |
|
|
|
|
|
|
|
).replace(prevBlock, null); |
|
|
|
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
sequBlock.replace(prevBlock, prevBlock); |
|
|
|
prev.removeJump(); |
|
|
|
sequBlock.setFirst(prevBlock); |
|
|
|
continue next_jump; |
|
|
|
sequBlock.setSecond |
|
|
|
|
|
|
|
(new BreakBlock((BreakableBlock) surrounder, |
|
|
|
|
|
|
|
breaklevel > 1)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
continue same_jump; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if this is a jumps at the end of a then block belonging |
|
|
|
|
|
|
|
* to a if-then block without else part, and the if-then |
|
|
|
|
|
|
|
* block is followed by a single block, then replace the |
|
|
|
|
|
|
|
* if-then block with a if-then-else block and remove the |
|
|
|
|
|
|
|
* unconditional jump. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
else if (jump.prev.outer instanceof IfThenElseBlock) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IfThenElseBlock ifBlock = |
|
|
|
|
|
|
|
(IfThenElseBlock)jump.prev.outer; |
|
|
|
|
|
|
|
if (ifBlock.elseBlock == null |
|
|
|
|
|
|
|
&& ifBlock.jump == null |
|
|
|
|
|
|
|
&& ifBlock.outer instanceof SequentialBlock |
|
|
|
|
|
|
|
&& ifBlock.outer.getSubBlocks()[0] == ifBlock |
|
|
|
|
|
|
|
&& (ifBlock.outer.getNextFlowBlock() == successor |
|
|
|
|
|
|
|
|| ifBlock.outer.jumpMayBeChanged())) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock elseBlock = |
|
|
|
|
|
|
|
ifBlock.outer.getSubBlocks()[1]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ifBlock.outer.removeJump(); |
|
|
|
|
|
|
|
ifBlock.replace(ifBlock.outer, elseBlock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (appendBlock == elseBlock.outer) |
|
|
|
|
|
|
|
appendBlock = ifBlock; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ifBlock.moveJump(jump); |
|
|
|
|
|
|
|
ifBlock.setElseBlock(elseBlock); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if this is a jump in a breakable block, and that block |
|
|
|
|
|
|
|
* has not yet a next block, then create a new jump to that |
|
|
|
|
|
|
|
* successor. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* The break to the block will be generated later. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (StructuredBlock surrounder = jump.prev.outer; |
|
|
|
|
|
|
|
surrounder != null && surrounder != appendBlock.outer; |
|
|
|
|
|
|
|
surrounder = surrounder.outer) { |
|
|
|
|
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
|
|
|
|
if (surrounder.getNextFlowBlock() != successor |
|
|
|
|
|
|
|
&& surrounder.jumpMayBeChanged()) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
surrounder.setJump(new Jump(successor)); |
|
|
|
|
|
|
|
successors.addElement(surrounder.jump); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// /* XXX - There is a problem with this.
|
|
|
|
|
|
|
|
// * The here created break could be obsoleted later.
|
|
|
|
|
|
|
|
// * We should instead only add the jump to surrounder
|
|
|
|
|
|
|
|
// * if necessary and add the break after all jumps
|
|
|
|
|
|
|
|
// * has been considered.
|
|
|
|
|
|
|
|
// */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// /* if there are jumps in a while block or switch block and the
|
|
|
|
|
|
|
|
// * while/switch block is followed by a jump to successor or has
|
|
|
|
|
|
|
|
// * successor as getNextFlowBlock(), replace jump with break to
|
|
|
|
|
|
|
|
// * the innermost such while/switch block.
|
|
|
|
|
|
|
|
// *
|
|
|
|
|
|
|
|
// * If the switch block hasn't been breaked before we could
|
|
|
|
|
|
|
|
// * take some heuristics and add a jump after the switch to
|
|
|
|
|
|
|
|
// * succesor, so that the above succeeds.
|
|
|
|
|
|
|
|
// */
|
|
|
|
|
|
|
|
// int breaklevel = 0;
|
|
|
|
|
|
|
|
// for (StructuredBlock surrounder = jump.prev.outer;
|
|
|
|
|
|
|
|
// surrounder != null && surrounder != appendBlock.outer;
|
|
|
|
|
|
|
|
// surrounder = surrounder.outer) {
|
|
|
|
|
|
|
|
// if (surrounder instanceof BreakableBlock) {
|
|
|
|
|
|
|
|
// breaklevel++;
|
|
|
|
|
|
|
|
// if (surrounder.getNextFlowBlock() == successor ||
|
|
|
|
|
|
|
|
// surrounder.jumpMayBeChanged()) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SequentialBlock sequBlock = new SequentialBlock();
|
|
|
|
|
|
|
|
// StructuredBlock prevBlock = jump.prev;
|
|
|
|
|
|
|
|
// if (surrounder.getNextFlowBlock() != successor)
|
|
|
|
|
|
|
|
// surrounder.moveJump(prevBlock.jump);
|
|
|
|
|
|
|
|
// else {
|
|
|
|
|
|
|
|
// prevBlock.removeJump();
|
|
|
|
|
|
|
|
// jump = null;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// prevBlock.appendBlock
|
|
|
|
|
|
|
|
// (new BreakBlock((BreakableBlock) surrounder,
|
|
|
|
|
|
|
|
// breaklevel >1));
|
|
|
|
|
|
|
|
// continue;
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
|
|
continue next_jump; |
|
|
|
continue next_jump; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -419,23 +422,23 @@ public class FlowBlock { |
|
|
|
* block. |
|
|
|
* block. |
|
|
|
* @return The variables that must be defined in this block. |
|
|
|
* @return The variables that must be defined in this block. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
VariableSet updateInOut (FlowBlock successor, boolean t1Transformation) { |
|
|
|
void updateInOut (FlowBlock successor, boolean t1Transformation) { |
|
|
|
/* 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. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
VariableSet allOuts = new VariableSet(); |
|
|
|
VariableSet gens = new VariableSet(); |
|
|
|
VariableSet intersectOut = null; |
|
|
|
VariableSet kills = null; |
|
|
|
Enumeration enum = successors.elements(); |
|
|
|
Enumeration enum = successors.elements(); |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
if (jump == null || jump.destination != successor) |
|
|
|
if (jump == null || jump.destination != successor) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
allOuts.union(jump.out); |
|
|
|
gens.unionExact(jump.gen); |
|
|
|
if (intersectOut == null) |
|
|
|
if (kills == null) |
|
|
|
intersectOut = jump.out; |
|
|
|
kills = jump.kill; |
|
|
|
else |
|
|
|
else |
|
|
|
intersectOut = intersectOut.intersect(jump.out); |
|
|
|
kills = kills.intersect(jump.kill); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// System.err.println("UpdateInOut: allOuts : "+allOuts);
|
|
|
|
// System.err.println("UpdateInOut: allOuts : "+allOuts);
|
|
|
@ -444,26 +447,25 @@ public class FlowBlock { |
|
|
|
/* Merge the locals used in successing block with those written |
|
|
|
/* Merge the locals used in successing block with those written |
|
|
|
* by this blocks |
|
|
|
* by this blocks |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
VariableSet defineHere = successor.in.merge(allOuts); |
|
|
|
successor.in.merge(gens); |
|
|
|
defineHere.subtractExact(in); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// System.err.println(" defineHere : "+defineHere);
|
|
|
|
|
|
|
|
if (t1Transformation) { |
|
|
|
|
|
|
|
/* Now update in and out set of successing block */ |
|
|
|
/* Now update in and out set of successing block */ |
|
|
|
successor.in.subtract(intersectOut); |
|
|
|
|
|
|
|
/* The out set must be updated for every jump in the block */ |
|
|
|
if (t1Transformation) |
|
|
|
|
|
|
|
successor.in.subtract(kills); |
|
|
|
|
|
|
|
/* The gen/kill sets must be updated for every jump in the block */ |
|
|
|
enum = successor.successors.elements(); |
|
|
|
enum = successor.successors.elements(); |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
if (jump != null) |
|
|
|
if (jump != null) { |
|
|
|
jump.out.add(intersectOut); |
|
|
|
jump.gen.mergeGenKill(gens, jump.kill); |
|
|
|
|
|
|
|
if (t1Transformation) |
|
|
|
|
|
|
|
jump.kill.add(kills); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// System.err.println(" successor.in: "+successor.in);
|
|
|
|
// System.err.println(" successor.in: "+successor.in);
|
|
|
|
in.union(successor.in); |
|
|
|
in.unionExact(successor.in); |
|
|
|
// System.err.println(" in : "+in);
|
|
|
|
// System.err.println(" in : "+in);
|
|
|
|
/* XXX - do something with defineHere */ |
|
|
|
|
|
|
|
return defineHere; /*XXX - correct???*/ |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -566,6 +568,8 @@ public class FlowBlock { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void checkConsistent() { |
|
|
|
public void checkConsistent() { |
|
|
|
|
|
|
|
if (!jode.Decompiler.doChecks) |
|
|
|
|
|
|
|
return; |
|
|
|
if (block.outer != null || block.flowBlock != this) { |
|
|
|
if (block.outer != null || block.flowBlock != this) { |
|
|
|
throw new RuntimeException("Inconsistency"); |
|
|
|
throw new RuntimeException("Inconsistency"); |
|
|
|
} |
|
|
|
} |
|
|
@ -611,11 +615,7 @@ public class FlowBlock { |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
try{ |
|
|
|
try{ |
|
|
|
// System.err.println("doing T1 analysis on: "+getLabel());
|
|
|
|
|
|
|
|
// System.err.println("***in: "+in);
|
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
// System.err.println("and "+succ.getLabel());
|
|
|
|
|
|
|
|
// System.err.println("+++in: "+succ.in);
|
|
|
|
|
|
|
|
succ.checkConsistent(); |
|
|
|
succ.checkConsistent(); |
|
|
|
} catch (RuntimeException ex) { |
|
|
|
} catch (RuntimeException ex) { |
|
|
|
ex.printStackTrace(); |
|
|
|
ex.printStackTrace(); |
|
|
@ -658,7 +658,7 @@ public class FlowBlock { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Update the in/out-Vectors now */ |
|
|
|
/* Update the in/out-Vectors now */ |
|
|
|
VariableSet defineHere = updateInOut(succ, true); |
|
|
|
updateInOut(succ, true); |
|
|
|
|
|
|
|
|
|
|
|
/* The switch "fall through" case: if the appendBlock is a |
|
|
|
/* The switch "fall through" case: if the appendBlock is a |
|
|
|
* switch, and the successor is the address of a case, and all |
|
|
|
* switch, and the successor is the address of a case, and all |
|
|
@ -669,7 +669,7 @@ public class FlowBlock { |
|
|
|
if (appendBlock instanceof SwitchBlock) { |
|
|
|
if (appendBlock instanceof SwitchBlock) { |
|
|
|
nextcase = ((SwitchBlock) appendBlock).findCase(succ); |
|
|
|
nextcase = ((SwitchBlock) appendBlock).findCase(succ); |
|
|
|
precedingcase = |
|
|
|
precedingcase = |
|
|
|
((SwitchBlock) appendBlock).prevCase(precedingcase); |
|
|
|
((SwitchBlock) appendBlock).prevCase(nextcase); |
|
|
|
|
|
|
|
|
|
|
|
enum = successors.elements(); |
|
|
|
enum = successors.elements(); |
|
|
|
while (nextcase != null && enum.hasMoreElements()) { |
|
|
|
while (nextcase != null && enum.hasMoreElements()) { |
|
|
@ -680,7 +680,6 @@ public class FlowBlock { |
|
|
|
|| (precedingcase != null |
|
|
|
|| (precedingcase != null |
|
|
|
&& precedingcase.contains(jump.prev))) |
|
|
|
&& precedingcase.contains(jump.prev))) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
nextcase = null; |
|
|
|
nextcase = null; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -696,8 +695,6 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
/* Do the following modifications on the struct block. */ |
|
|
|
/* Do the following modifications on the struct block. */ |
|
|
|
appendBlock = precedingcase; |
|
|
|
appendBlock = precedingcase; |
|
|
|
succ.block.setFlowBlock(this); |
|
|
|
|
|
|
|
// switchBlock.define(defineHere);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
|
@ -723,8 +720,6 @@ public class FlowBlock { |
|
|
|
sequBlock.replace(appendBlock, appendBlock); |
|
|
|
sequBlock.replace(appendBlock, appendBlock); |
|
|
|
sequBlock.setFirst(appendBlock); |
|
|
|
sequBlock.setFirst(appendBlock); |
|
|
|
sequBlock.setSecond(succ.block); |
|
|
|
sequBlock.setSecond(succ.block); |
|
|
|
succ.block.setFlowBlock(this); |
|
|
|
|
|
|
|
// sequBlock.define(defineHere);
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Merge the sucessors from the successing flow block |
|
|
|
/* Merge the sucessors from the successing flow block |
|
|
@ -744,7 +739,6 @@ public class FlowBlock { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
// System.err.println("before optimizeJump: "+getLabel());
|
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
} catch (RuntimeException ex) { |
|
|
|
} catch (RuntimeException ex) { |
|
|
|
ex.printStackTrace(); |
|
|
|
ex.printStackTrace(); |
|
|
@ -760,10 +754,15 @@ public class FlowBlock { |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* appendBlock may be zero, if this is the switchcase with |
|
|
|
|
|
|
|
* precedingcase = null. But in this case, there can't be |
|
|
|
|
|
|
|
* any jumps. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (appendBlock != null) { |
|
|
|
|
|
|
|
|
|
|
|
appendBlock = optimizeJumps(succ, appendBlock); |
|
|
|
appendBlock = optimizeJumps(succ, appendBlock); |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
// System.err.println("after optimizeJump: "+getLabel());
|
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
} catch (RuntimeException ex) { |
|
|
|
} catch (RuntimeException ex) { |
|
|
|
ex.printStackTrace(); |
|
|
|
ex.printStackTrace(); |
|
|
@ -776,56 +775,71 @@ public class FlowBlock { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* appendBlock may be zero, if this is the switchcase with |
|
|
|
|
|
|
|
* precedingcase = null. But in this case, there can't be |
|
|
|
|
|
|
|
* any jumps. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (appendBlock != null) { |
|
|
|
|
|
|
|
/* Now remove the jump of the appendBlock if it points to |
|
|
|
|
|
|
|
* successor. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (appendBlock.jump != null |
|
|
|
|
|
|
|
&& appendBlock.jump.destination == succ) |
|
|
|
|
|
|
|
appendBlock.removeJump(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* If there are further jumps, put a do/while(0) block around |
|
|
|
|
|
|
|
* appendBlock and replace every remaining jump with a break |
|
|
|
|
|
|
|
* to the do/while block. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
LoopBlock doWhileFalse = null; |
|
|
|
LoopBlock doWhileFalse = null; |
|
|
|
enum = successors.elements(); |
|
|
|
enum = successors.elements(); |
|
|
|
|
|
|
|
next_jump: |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
|
|
|
|
|
|
|
|
if (jump == null || jump.destination != succ) |
|
|
|
if (jump == null || jump.destination != succ || |
|
|
|
|
|
|
|
jump.prev == appendBlock) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
if (doWhileFalse == null) |
|
|
|
int breaklevel = 0; |
|
|
|
doWhileFalse = new LoopBlock(LoopBlock.DOWHILE, |
|
|
|
BreakableBlock breakToBlock = null; |
|
|
|
LoopBlock.FALSE); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int breaklevel = 1; |
|
|
|
|
|
|
|
for (StructuredBlock surrounder = jump.prev.outer; |
|
|
|
for (StructuredBlock surrounder = jump.prev.outer; |
|
|
|
surrounder != appendBlock.outer; |
|
|
|
surrounder != null && surrounder != appendBlock.outer; |
|
|
|
surrounder = surrounder.outer) { |
|
|
|
surrounder = surrounder.outer) { |
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
breaklevel++; |
|
|
|
breaklevel++; |
|
|
|
|
|
|
|
if (surrounder.getNextFlowBlock() == succ) { |
|
|
|
|
|
|
|
breakToBlock = (BreakableBlock) surrounder; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/* We don't want labeled breaks, if we can |
|
|
|
|
|
|
|
* simply return. */ |
|
|
|
|
|
|
|
if (succ == END_OF_METHOD) |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
SequentialBlock sequBlock = new SequentialBlock(); |
|
|
|
|
|
|
|
StructuredBlock prevBlock = jump.prev; |
|
|
|
StructuredBlock prevBlock = jump.prev; |
|
|
|
prevBlock.removeJump(); |
|
|
|
prevBlock.removeJump(); |
|
|
|
|
|
|
|
|
|
|
|
sequBlock.replace(prevBlock, prevBlock); |
|
|
|
if (breakToBlock == null) { |
|
|
|
sequBlock.setFirst(prevBlock); |
|
|
|
/* if the successor is the dummy return instruction |
|
|
|
sequBlock.setSecond(new BreakBlock(doWhileFalse, breaklevel > 1)); |
|
|
|
* and no simple breakToBlock could be found above, |
|
|
|
|
|
|
|
* replace the jump with a return. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (succ == END_OF_METHOD && breakToBlock == null) |
|
|
|
|
|
|
|
prevBlock.appendBlock(new ReturnBlock()); |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
/* Nothing else helped, so put a do/while(0) |
|
|
|
|
|
|
|
* block around appendBlock and break to that |
|
|
|
|
|
|
|
* block. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (doWhileFalse == null) |
|
|
|
|
|
|
|
doWhileFalse = new LoopBlock(LoopBlock.DOWHILE, |
|
|
|
|
|
|
|
LoopBlock.FALSE); |
|
|
|
|
|
|
|
prevBlock.appendBlock |
|
|
|
|
|
|
|
(new BreakBlock(doWhileFalse, breaklevel > 0)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else |
|
|
|
|
|
|
|
prevBlock.appendBlock |
|
|
|
|
|
|
|
(new BreakBlock(breakToBlock, breaklevel > 1)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (doWhileFalse != null) { |
|
|
|
if (doWhileFalse != null) { |
|
|
|
doWhileFalse.replace(appendBlock, appendBlock); |
|
|
|
doWhileFalse.replace(appendBlock, appendBlock); |
|
|
|
doWhileFalse.setBody(appendBlock); |
|
|
|
doWhileFalse.setBody(appendBlock); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Now remove the jump of the appendBlock if it points to |
|
|
|
|
|
|
|
* successor. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
if (appendBlock.jump != null |
|
|
|
|
|
|
|
&& appendBlock.jump.destination == succ) |
|
|
|
|
|
|
|
appendBlock.removeJump(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Believe it or not: Now the rule, that the first part of a |
|
|
|
/* Believe it or not: Now the rule, that the first part of a |
|
|
@ -899,7 +913,7 @@ public class FlowBlock { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Update the in/out-Vectors now */ |
|
|
|
/* Update the in/out-Vectors now */ |
|
|
|
VariableSet defineHere = updateInOut(this, false); |
|
|
|
updateInOut(this, false); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (lastModified != block) { |
|
|
|
while (lastModified != block) { |
|
|
@ -945,7 +959,6 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
whileBlock.replace(bodyBlock, bodyBlock); |
|
|
|
whileBlock.replace(bodyBlock, bodyBlock); |
|
|
|
whileBlock.setBody(bodyBlock); |
|
|
|
whileBlock.setBody(bodyBlock); |
|
|
|
// whileBlock.define(defineHere);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -1069,13 +1082,13 @@ public class FlowBlock { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!in.isEmpty()) { |
|
|
|
if (!in.isEmpty()) { |
|
|
|
writer.print("in: "+in); |
|
|
|
writer.println("in: "+in); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
block.dumpSource(writer); |
|
|
|
block.dumpSource(writer); |
|
|
|
FlowBlock succ = getSuccessor(); |
|
|
|
// FlowBlock succ = getSuccessor();
|
|
|
|
if (succ != null) |
|
|
|
// if (succ != null)
|
|
|
|
succ.dumpSource(writer); |
|
|
|
// succ.dumpSource(writer);
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|