Clean up of optimizeJump/resolveRemaining.

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@74 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent cc81c74ebd
commit c25b9e7cb4
  1. 572
      jode/jode/flow/FlowBlock.java

@ -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.setThenBlock(sequBlock.getSubBlocks()[1]); newIfBlock.replace(sequBlock, thenBlock);
newIfBlock.setThenBlock(thenBlock);
if (appendBlock == sequBlock) { if (thenBlock.contains(lastModified)) {
newIfBlock.moveJump(appendBlock.jump); if (lastModified.jump != null
appendBlock = newIfBlock; && lastModified.jump.destination == successor) {
jump.prev.removeJump(); newIfBlock.moveJump(lastModified.jump);
} else { lastModified = newIfBlock;
newIfBlock.moveJump(jump); jump.prev.removeJump();
/* consider this jump again */ continue;
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,21 +428,42 @@ 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());
}
}
} }
/** /**
* Updates the in/out-Vectors of the structured block of the * Updates the in/out-Vectors of the structured block of the
* successing flow block simultanous to a T1 transformation. * successing flow block simultanous to a T1 transformation.
@ -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 keys = successors.keys();
Enumeration stacks = successors.elements();
while (keys.hasMoreElements()) {
FlowBlock dest = (FlowBlock) keys.nextElement();
if (!dest.predecessors.contains(this))
throw new AssertError("Inconsistency");
Enumeration enum = ((Stack)stacks.nextElement()).elements(); Enumeration enum = ((Stack)stacks.nextElement()).elements();
if (!enum.hasMoreElements()) if (!enum.hasMoreElements())
throw new AssertError("Inconsistency"); throw new AssertError("Inconsistency");
while (enum.hasMoreElements()) { while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement(); Jump jump = (Jump) enum.nextElement();
if (jump.destination != dest) 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,25 +738,16 @@ 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);
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,21 +1328,14 @@ 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) {
/* simple try catch block: /* simple try catch block:
* *
@ -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;
@ -1583,15 +1509,16 @@ public class FlowBlock {
rawBlock.tryBlock.setJump(jump); rawBlock.tryBlock.setJump(jump);
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)))
boolean lastContains = false; || ((Stack)successors.get(nextFlow)).size() > 1)
Stack jumps = new Stack(); break;
Enumeration enum =
((Stack) successors.get(next)).elements();
while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement();
if (jump == switchBlock.caseBlocks[i].subBlock.jump)
continue;
jumps.push(jump);
if (lastBlock == null
|| !lastBlock.contains(jump.prev))
return changed;
}
checkConsistent(); checkConsistent();
updateInOut(next, true, (Stack) successors.remove(next)); Stack jumps = (Stack) successors.remove(nextFlow);
switchBlock.caseBlocks[i].subBlock.removeJump(); /* note that jumps.size() == 1 */
next.block.replace(switchBlock.caseBlocks[i].subBlock,
null); if (nextFlow.predecessors.size() == 2) {
Stack lastJumps =
(Stack) lastFlow.successors.remove(nextFlow);
/* 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);
mergeSuccessors(next); if (lastFlow != null) {
if (!jumps.isEmpty()) { lastFlow.block.replace
lastBlock = optimizeJumps(lastBlock, jumps); (switchBlock.caseBlocks[last].subBlock, null);
lastBlock = resolveRemaining(lastBlock, jumps); mergeSuccessors(lastFlow);
} }
/* Set length to correct value */ /* We merge the blocks into the caseBlock later, but
length += next.length; * that doesn't affect consistency.
*/
lastBlock = next.block;
switchBlock.caseBlocks[i].subBlock.removeJump();
length += nextFlow.length;
lastFlow = nextFlow;
last = i;
checkConsistent(); checkConsistent();
changed = true; changed = true;
} }
} }
} }
if (lastFlow != null) {
lastFlow.block.replace
(switchBlock.caseBlocks[last].subBlock, null);
mergeSuccessors(lastFlow);
}
checkConsistent();
return changed; return changed;
} }

Loading…
Cancel
Save