|
|
@ -86,7 +86,8 @@ public class FlowBlock { |
|
|
|
/** |
|
|
|
/** |
|
|
|
* This contains a map of all successing flow blocks and there |
|
|
|
* This contains a map of all successing flow blocks and there |
|
|
|
* jumps. The key of this dictionary are the flow blocks, while |
|
|
|
* jumps. The key of this dictionary are the flow blocks, while |
|
|
|
* the elements are Stacks of jumps. |
|
|
|
* the elements is the first jump to that dictionary. The other |
|
|
|
|
|
|
|
* jumps are accessible via the jump.next field. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
Dictionary successors = new Hashtable(); |
|
|
|
Dictionary successors = new Hashtable(); |
|
|
|
|
|
|
|
|
|
|
@ -121,28 +122,28 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* This method optimizes the jumps to successor. |
|
|
|
* This method optimizes the jumps to successor. |
|
|
|
* @param jumps The jumps that jump to successor. All jumps that |
|
|
|
* @param jumps The list of jumps with that successor. |
|
|
|
* can be optimized are removed from this stack. |
|
|
|
* @return The remaining jumps, that couldn't be optimized. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public void optimizeJumps(Stack jumps, FlowBlock succ) { |
|
|
|
public Jump optimizeJumps(Jump jumps, FlowBlock succ) { |
|
|
|
Stack remainingJumps = new Stack(); |
|
|
|
Jump remainingJumps = null; |
|
|
|
|
|
|
|
|
|
|
|
if (lastModified.jump == null) { |
|
|
|
if (lastModified.jump == null) { |
|
|
|
Jump jump = new Jump(succ); |
|
|
|
Jump lastJump = new Jump(succ); |
|
|
|
lastModified.setJump(jump); |
|
|
|
lastModified.setJump(lastJump); |
|
|
|
remainingJumps.push(jump); |
|
|
|
remainingJumps = lastJump; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
next_jump: |
|
|
|
next_jump: |
|
|
|
while (!jumps.isEmpty()) { |
|
|
|
while (jumps != null) { |
|
|
|
Jump jump = (Jump) jumps.pop(); |
|
|
|
Jump jump = jumps; |
|
|
|
|
|
|
|
jumps = jumps.next; |
|
|
|
FlowBlock successor = jump.destination; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if the jump is the jump of the lastModified, skip it. |
|
|
|
/* if the jump is the jump of the lastModified, skip it. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (jump.prev == lastModified) { |
|
|
|
if (jump.prev == lastModified) { |
|
|
|
remainingJumps.push(jump); |
|
|
|
jump.next = remainingJumps; |
|
|
|
|
|
|
|
remainingJumps = jump; |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -188,7 +189,7 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
/* Consider this jump again |
|
|
|
/* Consider this jump again |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
jumps.push(jump); |
|
|
|
jumps = jump; |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -213,11 +214,12 @@ public class FlowBlock { |
|
|
|
if (loopBlock.getCondition() == LoopBlock.TRUE && |
|
|
|
if (loopBlock.getCondition() == LoopBlock.TRUE && |
|
|
|
loopBlock.getType() != LoopBlock.DOWHILE && |
|
|
|
loopBlock.getType() != LoopBlock.DOWHILE && |
|
|
|
(loopBlock.jumpMayBeChanged() |
|
|
|
(loopBlock.jumpMayBeChanged() |
|
|
|
|| loopBlock.getNextFlowBlock() == successor)) { |
|
|
|
|| loopBlock.getNextFlowBlock() == succ)) { |
|
|
|
|
|
|
|
|
|
|
|
if (loopBlock.jump == null) { |
|
|
|
if (loopBlock.jump == null) { |
|
|
|
|
|
|
|
/* consider this jump again */ |
|
|
|
loopBlock.moveJump(jump); |
|
|
|
loopBlock.moveJump(jump); |
|
|
|
jumps.push(jump); |
|
|
|
jumps = jump; |
|
|
|
} else |
|
|
|
} else |
|
|
|
jump.prev.removeJump(); |
|
|
|
jump.prev.removeJump(); |
|
|
|
|
|
|
|
|
|
|
@ -247,11 +249,12 @@ public class FlowBlock { |
|
|
|
if (loopBlock.getCondition() == LoopBlock.TRUE && |
|
|
|
if (loopBlock.getCondition() == LoopBlock.TRUE && |
|
|
|
loopBlock.getType() == LoopBlock.WHILE && |
|
|
|
loopBlock.getType() == LoopBlock.WHILE && |
|
|
|
(loopBlock.jumpMayBeChanged() |
|
|
|
(loopBlock.jumpMayBeChanged() |
|
|
|
|| loopBlock.getNextFlowBlock() == successor)) { |
|
|
|
|| loopBlock.getNextFlowBlock() == succ)) { |
|
|
|
|
|
|
|
|
|
|
|
if (loopBlock.jump == null) { |
|
|
|
if (loopBlock.jump == null) { |
|
|
|
|
|
|
|
/* consider this jump again */ |
|
|
|
loopBlock.moveJump(jump); |
|
|
|
loopBlock.moveJump(jump); |
|
|
|
jumps.push(jump); |
|
|
|
jumps = jump; |
|
|
|
} else |
|
|
|
} else |
|
|
|
jump.prev.removeJump(); |
|
|
|
jump.prev.removeJump(); |
|
|
|
|
|
|
|
|
|
|
@ -270,7 +273,7 @@ public class FlowBlock { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
if (cb.outer instanceof SequentialBlock && |
|
|
|
if (cb.outer instanceof SequentialBlock && |
|
|
|
cb.outer.getSubBlocks()[0] == cb && |
|
|
|
cb.outer.getSubBlocks()[0] == cb && |
|
|
|
(cb.outer.getNextFlowBlock() == successor || |
|
|
|
(cb.outer.getNextFlowBlock() == succ || |
|
|
|
cb.outer.jumpMayBeChanged())) { |
|
|
|
cb.outer.jumpMayBeChanged())) { |
|
|
|
|
|
|
|
|
|
|
|
SequentialBlock sequBlock = (SequentialBlock) cb.outer; |
|
|
|
SequentialBlock sequBlock = (SequentialBlock) cb.outer; |
|
|
@ -284,7 +287,7 @@ public class FlowBlock { |
|
|
|
newIfBlock.setThenBlock(thenBlock); |
|
|
|
newIfBlock.setThenBlock(thenBlock); |
|
|
|
|
|
|
|
|
|
|
|
if (thenBlock.contains(lastModified)) { |
|
|
|
if (thenBlock.contains(lastModified)) { |
|
|
|
if (lastModified.jump.destination == successor) { |
|
|
|
if (lastModified.jump.destination == succ) { |
|
|
|
newIfBlock.moveJump(lastModified.jump); |
|
|
|
newIfBlock.moveJump(lastModified.jump); |
|
|
|
lastModified = newIfBlock; |
|
|
|
lastModified = newIfBlock; |
|
|
|
jump.prev.removeJump(); |
|
|
|
jump.prev.removeJump(); |
|
|
@ -295,7 +298,7 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
newIfBlock.moveJump(jump); |
|
|
|
newIfBlock.moveJump(jump); |
|
|
|
/* consider this jump again */ |
|
|
|
/* consider this jump again */ |
|
|
|
jumps.push(jump); |
|
|
|
jumps = jump; |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -329,14 +332,14 @@ public class FlowBlock { |
|
|
|
StructuredBlock elseBlock = sequBlock.subBlocks[1]; |
|
|
|
StructuredBlock elseBlock = sequBlock.subBlocks[1]; |
|
|
|
|
|
|
|
|
|
|
|
if (ifBlock.elseBlock == null |
|
|
|
if (ifBlock.elseBlock == null |
|
|
|
&& (elseBlock.getNextFlowBlock() == successor |
|
|
|
&& (elseBlock.getNextFlowBlock() == succ |
|
|
|
|| elseBlock.jumpMayBeChanged())) { |
|
|
|
|| elseBlock.jumpMayBeChanged())) { |
|
|
|
|
|
|
|
|
|
|
|
ifBlock.replace(sequBlock); |
|
|
|
ifBlock.replace(sequBlock); |
|
|
|
ifBlock.setElseBlock(elseBlock); |
|
|
|
ifBlock.setElseBlock(elseBlock); |
|
|
|
|
|
|
|
|
|
|
|
if (elseBlock.contains(lastModified)) { |
|
|
|
if (elseBlock.contains(lastModified)) { |
|
|
|
if (lastModified.jump.destination == successor) { |
|
|
|
if (lastModified.jump.destination == succ) { |
|
|
|
ifBlock.moveJump(lastModified.jump); |
|
|
|
ifBlock.moveJump(lastModified.jump); |
|
|
|
lastModified = ifBlock; |
|
|
|
lastModified = ifBlock; |
|
|
|
jump.prev.removeJump(); |
|
|
|
jump.prev.removeJump(); |
|
|
@ -347,7 +350,7 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
/* consider this jump again */ |
|
|
|
/* consider this jump again */ |
|
|
|
ifBlock.moveJump(jump); |
|
|
|
ifBlock.moveJump(jump); |
|
|
|
jumps.push(jump); |
|
|
|
jumps = jump; |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -363,34 +366,34 @@ public class FlowBlock { |
|
|
|
for (StructuredBlock surrounder = jump.prev.outer; |
|
|
|
for (StructuredBlock surrounder = jump.prev.outer; |
|
|
|
surrounder != null; surrounder = surrounder.outer) { |
|
|
|
surrounder != null; surrounder = surrounder.outer) { |
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
if (surrounder.getNextFlowBlock() != successor |
|
|
|
if (surrounder.getNextFlowBlock() != succ |
|
|
|
&& surrounder.jumpMayBeChanged()) { |
|
|
|
&& surrounder.jumpMayBeChanged()) { |
|
|
|
|
|
|
|
|
|
|
|
surrounder.setJump(new Jump(successor)); |
|
|
|
surrounder.setJump(new Jump(succ)); |
|
|
|
jumps.push(surrounder.jump); |
|
|
|
surrounder.jump.next = jumps; |
|
|
|
|
|
|
|
jumps = surrounder.jump; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
remainingJumps.push(jump); |
|
|
|
jump.next = remainingJumps; |
|
|
|
|
|
|
|
remainingJumps = jump; |
|
|
|
} |
|
|
|
} |
|
|
|
while(!remainingJumps.isEmpty()) |
|
|
|
return remainingJumps; |
|
|
|
jumps.push(remainingJumps.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 jumps The jumps that should be resolved. |
|
|
|
* @param jumps The jump list that need to be resolved. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
void resolveRemaining(Stack jumps) { |
|
|
|
void resolveRemaining(Jump jumps) { |
|
|
|
LoopBlock doWhileFalse = null; |
|
|
|
LoopBlock doWhileFalse = null; |
|
|
|
StructuredBlock outerMost = lastModified; |
|
|
|
StructuredBlock outerMost = lastModified; |
|
|
|
boolean removeLast = false; |
|
|
|
boolean removeLast = false; |
|
|
|
next_jump: |
|
|
|
next_jump: |
|
|
|
while (!jumps.isEmpty()) { |
|
|
|
for (; jumps != null; jumps = jumps.next) { |
|
|
|
Jump jump = (Jump) jumps.pop(); |
|
|
|
StructuredBlock prevBlock = jumps.prev; |
|
|
|
StructuredBlock prevBlock = jump.prev; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (prevBlock == lastModified) { |
|
|
|
if (prevBlock == lastModified) { |
|
|
|
/* handled below */ |
|
|
|
/* handled below */ |
|
|
@ -404,7 +407,7 @@ public class FlowBlock { |
|
|
|
surrounder != null; surrounder = surrounder.outer) { |
|
|
|
surrounder != null; surrounder = surrounder.outer) { |
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
breaklevel++; |
|
|
|
breaklevel++; |
|
|
|
if (surrounder.getNextFlowBlock() == jump.destination) { |
|
|
|
if (surrounder.getNextFlowBlock() == jumps.destination) { |
|
|
|
breakToBlock = (BreakableBlock) surrounder; |
|
|
|
breakToBlock = (BreakableBlock) surrounder; |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -421,7 +424,6 @@ public class FlowBlock { |
|
|
|
if (doWhileFalse == null) { |
|
|
|
if (doWhileFalse == null) { |
|
|
|
doWhileFalse = new LoopBlock(LoopBlock.DOWHILE, |
|
|
|
doWhileFalse = new LoopBlock(LoopBlock.DOWHILE, |
|
|
|
LoopBlock.FALSE); |
|
|
|
LoopBlock.FALSE); |
|
|
|
doWhileFalse.setJump(new Jump(jump.destination)); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
/* Adapt outermost, so that it contains the break. */ |
|
|
|
/* Adapt outermost, so that it contains the break. */ |
|
|
|
while (!outerMost.contains(prevBlock)) |
|
|
|
while (!outerMost.contains(prevBlock)) |
|
|
@ -439,7 +441,6 @@ public class FlowBlock { |
|
|
|
if (doWhileFalse != null) { |
|
|
|
if (doWhileFalse != null) { |
|
|
|
doWhileFalse.replace(outerMost); |
|
|
|
doWhileFalse.replace(outerMost); |
|
|
|
doWhileFalse.setBody(outerMost); |
|
|
|
doWhileFalse.setBody(outerMost); |
|
|
|
doWhileFalse.jump = null; |
|
|
|
|
|
|
|
lastModified = doWhileFalse; |
|
|
|
lastModified = doWhileFalse; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -452,19 +453,20 @@ public class FlowBlock { |
|
|
|
/* Merge the sucessors from the successing flow block |
|
|
|
/* Merge the sucessors from the successing flow block |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
Enumeration keys = succ.successors.keys(); |
|
|
|
Enumeration keys = succ.successors.keys(); |
|
|
|
Enumeration stacks = succ.successors.elements(); |
|
|
|
Enumeration succs = succ.successors.elements(); |
|
|
|
while (keys.hasMoreElements()) { |
|
|
|
while (keys.hasMoreElements()) { |
|
|
|
FlowBlock dest = (FlowBlock) keys.nextElement(); |
|
|
|
FlowBlock dest = (FlowBlock) keys.nextElement(); |
|
|
|
Stack hisJumps = (Stack) stacks.nextElement(); |
|
|
|
Jump hisJumps = (Jump) succs.nextElement(); |
|
|
|
Stack myJumps = (Stack) successors.get(dest); |
|
|
|
Jump myJumps = (Jump) successors.get(dest); |
|
|
|
|
|
|
|
|
|
|
|
dest.predecessors.removeElement(succ); |
|
|
|
dest.predecessors.removeElement(succ); |
|
|
|
if (myJumps == null) { |
|
|
|
if (myJumps == null) { |
|
|
|
dest.predecessors.addElement(this); |
|
|
|
dest.predecessors.addElement(this); |
|
|
|
successors.put(dest, hisJumps); |
|
|
|
successors.put(dest, hisJumps); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
while (!hisJumps.isEmpty()) |
|
|
|
while (myJumps.next != null) |
|
|
|
myJumps.push(hisJumps.pop()); |
|
|
|
myJumps = myJumps.next; |
|
|
|
|
|
|
|
myJumps.next = hisJumps; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -474,25 +476,22 @@ public class FlowBlock { |
|
|
|
* successing flow block simultanous to a T1 transformation. |
|
|
|
* successing flow block simultanous to a T1 transformation. |
|
|
|
* @param successor The flow block which is unified with this flow |
|
|
|
* @param successor The flow block which is unified with this flow |
|
|
|
* block. |
|
|
|
* block. |
|
|
|
|
|
|
|
* @param jumps The list of jumps to successor in this block. |
|
|
|
* @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, Jump 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. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
VariableSet gens = new VariableSet(); |
|
|
|
VariableSet gens = new VariableSet(); |
|
|
|
VariableSet kills = null; |
|
|
|
VariableSet kills = null; |
|
|
|
|
|
|
|
|
|
|
|
Enumeration enum = jumps.elements(); |
|
|
|
for (;jumps != null; jumps = jumps.next) { |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
gens.unionExact(jumps.gen); |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gens.unionExact(jump.gen); |
|
|
|
|
|
|
|
if (kills == null) |
|
|
|
if (kills == null) |
|
|
|
kills = jump.kill; |
|
|
|
kills = jumps.kill; |
|
|
|
else |
|
|
|
else |
|
|
|
kills = kills.intersect(jump.kill); |
|
|
|
kills = kills.intersect(jumps.kill); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Merge the locals used in successing block with those written |
|
|
|
/* Merge the locals used in successing block with those written |
|
|
@ -502,22 +501,19 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
/* Now update in and out set of successing block */ |
|
|
|
/* Now update in and out set of successing block */ |
|
|
|
|
|
|
|
|
|
|
|
if (t1Transformation) |
|
|
|
if (successor != this) |
|
|
|
successor.in.subtract(kills); |
|
|
|
successor.in.subtract(kills); |
|
|
|
|
|
|
|
|
|
|
|
/* The gen/kill sets must be updated for every jump |
|
|
|
/* The gen/kill sets must be updated for every jump |
|
|
|
* in the other block */ |
|
|
|
* in the other block */ |
|
|
|
Enumeration stacks = successor.successors.elements(); |
|
|
|
Enumeration succSuccs = successor.successors.elements(); |
|
|
|
while (stacks.hasMoreElements()) { |
|
|
|
while (succSuccs.hasMoreElements()) { |
|
|
|
enum = ((Stack) stacks.nextElement()).elements(); |
|
|
|
Jump succJumps = (Jump) succSuccs.nextElement(); |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
for (; succJumps != null; succJumps = succJumps.next) { |
|
|
|
|
|
|
|
|
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
succJumps.gen.mergeGenKill(gens, succJumps.kill); |
|
|
|
if (jump != null) { |
|
|
|
if (successor != this) |
|
|
|
jump.gen.mergeGenKill(gens, jump.kill); |
|
|
|
succJumps.kill.add(kills); |
|
|
|
if (t1Transformation) |
|
|
|
|
|
|
|
jump.kill.add(kills); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
this.in.unionExact(successor.in); |
|
|
|
this.in.unionExact(successor.in); |
|
|
@ -567,28 +563,27 @@ public class FlowBlock { |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
|
|
|
|
|
|
|
|
Enumeration keys = successors.keys(); |
|
|
|
Enumeration keys = successors.keys(); |
|
|
|
Enumeration stacks = successors.elements(); |
|
|
|
Enumeration succs = successors.elements(); |
|
|
|
while (keys.hasMoreElements()) { |
|
|
|
while (keys.hasMoreElements()) { |
|
|
|
FlowBlock dest = (FlowBlock) keys.nextElement(); |
|
|
|
FlowBlock dest = (FlowBlock) keys.nextElement(); |
|
|
|
if (!dest.predecessors.contains(this)) |
|
|
|
if (!dest.predecessors.contains(this)) |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
|
|
|
|
|
|
|
|
Enumeration enum = ((Stack)stacks.nextElement()).elements(); |
|
|
|
Jump jumps = (Jump)succs.nextElement(); |
|
|
|
if (!enum.hasMoreElements()) |
|
|
|
if (jumps == null) |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
|
|
|
|
|
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
for (; jumps != null; jumps = jumps.next) { |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (jump.destination != dest) |
|
|
|
if (jumps.destination != dest) |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
|
|
|
|
|
|
|
|
if (jump.prev.flowBlock != this || |
|
|
|
if (jumps.prev.flowBlock != this || |
|
|
|
jump.prev.jump != jump) |
|
|
|
jumps.prev.jump != jumps) |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
throw new AssertError("Inconsistency"); |
|
|
|
|
|
|
|
|
|
|
|
prev_loop: |
|
|
|
prev_loop: |
|
|
|
for (StructuredBlock prev = jump.prev; prev != block; |
|
|
|
for (StructuredBlock prev = jumps.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"); |
|
|
@ -620,14 +615,14 @@ public class FlowBlock { |
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
succ.checkConsistent(); |
|
|
|
succ.checkConsistent(); |
|
|
|
|
|
|
|
|
|
|
|
Stack jumps = (Stack) successors.remove(succ); |
|
|
|
Jump jumps = (Jump) successors.remove(succ); |
|
|
|
|
|
|
|
|
|
|
|
/* Update the in/out-Vectors now */ |
|
|
|
/* Update the in/out-Vectors now */ |
|
|
|
updateInOut(succ, true, jumps); |
|
|
|
updateInOut(succ, jumps); |
|
|
|
|
|
|
|
|
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
optimizeJumps(jumps, succ); |
|
|
|
jumps = optimizeJumps(jumps, succ); |
|
|
|
resolveRemaining(jumps); |
|
|
|
resolveRemaining(jumps); |
|
|
|
|
|
|
|
|
|
|
|
/* Now unify the blocks. |
|
|
|
/* Now unify the blocks. |
|
|
@ -668,10 +663,10 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
|
|
|
|
|
|
|
|
Stack jumps = (Stack) successors.remove(this); |
|
|
|
Jump jumps = (Jump) successors.remove(this); |
|
|
|
|
|
|
|
|
|
|
|
/* Update the in/out-Vectors now */ |
|
|
|
/* Update the in/out-Vectors now */ |
|
|
|
updateInOut(this, false, jumps); |
|
|
|
updateInOut(this, jumps); |
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock bodyBlock = block; |
|
|
|
StructuredBlock bodyBlock = block; |
|
|
|
|
|
|
|
|
|
|
@ -685,8 +680,8 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
boolean createdForBlock = false; |
|
|
|
boolean createdForBlock = false; |
|
|
|
|
|
|
|
|
|
|
|
if (jumps.size() == 1 |
|
|
|
if (jumps.next == null |
|
|
|
&& ((Jump)jumps.peek()).prev == lastModified |
|
|
|
&& jumps.prev == lastModified |
|
|
|
&& lastModified instanceof InstructionBlock) { |
|
|
|
&& lastModified instanceof InstructionBlock) { |
|
|
|
|
|
|
|
|
|
|
|
Expression instr = |
|
|
|
Expression instr = |
|
|
@ -749,7 +744,7 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
optimizeJumps(jumps, this); |
|
|
|
jumps = optimizeJumps(jumps, this); |
|
|
|
|
|
|
|
|
|
|
|
LoopBlock whileBlock = |
|
|
|
LoopBlock whileBlock = |
|
|
|
new LoopBlock(LoopBlock.WHILE, LoopBlock.TRUE); |
|
|
|
new LoopBlock(LoopBlock.WHILE, LoopBlock.TRUE); |
|
|
@ -760,16 +755,17 @@ public class FlowBlock { |
|
|
|
/* 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. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
while (!jumps.isEmpty()) { |
|
|
|
for (; jumps != null; jumps = jumps.next) { |
|
|
|
Jump jump = (Jump) jumps.pop(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (jump.prev == lastModified) |
|
|
|
if (jumps.prev == lastModified) |
|
|
|
/* handled later */ |
|
|
|
/* handled later */ |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock prevBlock = jumps.prev; |
|
|
|
|
|
|
|
|
|
|
|
int breaklevel = 0, continuelevel = 0; |
|
|
|
int breaklevel = 0, continuelevel = 0; |
|
|
|
BreakableBlock breakToBlock = null; |
|
|
|
BreakableBlock breakToBlock = null; |
|
|
|
for (StructuredBlock surrounder = jump.prev.outer; |
|
|
|
for (StructuredBlock surrounder = prevBlock.outer; |
|
|
|
surrounder != whileBlock; |
|
|
|
surrounder != whileBlock; |
|
|
|
surrounder = surrounder.outer) { |
|
|
|
surrounder = surrounder.outer) { |
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
|
if (surrounder instanceof BreakableBlock) { |
|
|
@ -782,7 +778,6 @@ public class FlowBlock { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
StructuredBlock prevBlock = jump.prev; |
|
|
|
|
|
|
|
prevBlock.removeJump(); |
|
|
|
prevBlock.removeJump(); |
|
|
|
if (breakToBlock == null) |
|
|
|
if (breakToBlock == null) |
|
|
|
prevBlock.appendBlock |
|
|
|
prevBlock.appendBlock |
|
|
@ -816,34 +811,34 @@ public class FlowBlock { |
|
|
|
public void mergeEndBlock() { |
|
|
|
public void mergeEndBlock() { |
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
|
|
|
|
|
|
|
|
Stack allJumps = (Stack) successors.remove(END_OF_METHOD); |
|
|
|
Jump allJumps = (Jump) successors.remove(END_OF_METHOD); |
|
|
|
if (allJumps == null) |
|
|
|
if (allJumps == null) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
/* First remove all implicit jumps to the END_OF_METHOD block. |
|
|
|
/* First remove all implicit jumps to the END_OF_METHOD block. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
Stack jumps = new Stack(); |
|
|
|
Jump jumps = null; |
|
|
|
Enumeration enum = allJumps.elements(); |
|
|
|
for (; allJumps != null; ) { |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
Jump jump = allJumps; |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
allJumps = allJumps.next; |
|
|
|
|
|
|
|
|
|
|
|
if (jump.prev instanceof ReturnBlock) { |
|
|
|
if (jump.prev instanceof ReturnBlock) { |
|
|
|
/* This jump is implicit */ |
|
|
|
/* This jump is implicit */ |
|
|
|
jump.prev.removeJump(); |
|
|
|
jump.prev.removeJump(); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
jumps.push(jump); |
|
|
|
jump.next = jumps; |
|
|
|
|
|
|
|
jumps = jump; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
optimizeJumps(jumps, END_OF_METHOD); |
|
|
|
jumps = optimizeJumps(jumps, END_OF_METHOD); |
|
|
|
|
|
|
|
|
|
|
|
next_jump: |
|
|
|
next_jump: |
|
|
|
while (!jumps.isEmpty()) { |
|
|
|
for (; jumps != null; jumps = jumps.next) { |
|
|
|
Jump jump = (Jump) jumps.pop(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock prevBlock = jump.prev; |
|
|
|
StructuredBlock prevBlock = jumps.prev; |
|
|
|
|
|
|
|
|
|
|
|
if (lastModified == prevBlock) |
|
|
|
if (lastModified == prevBlock) |
|
|
|
/* handled later */ |
|
|
|
/* handled later */ |
|
|
@ -1097,30 +1092,30 @@ public class FlowBlock { |
|
|
|
|| (nextFlow.predecessors.size() > 1 |
|
|
|
|| (nextFlow.predecessors.size() > 1 |
|
|
|
&& (lastFlow == null |
|
|
|
&& (lastFlow == null |
|
|
|
|| !nextFlow.predecessors.contains(lastFlow))) |
|
|
|
|| !nextFlow.predecessors.contains(lastFlow))) |
|
|
|
|| ((Stack)successors.get(nextFlow)).size() > 1) |
|
|
|
|| ((Jump)successors.get(nextFlow)).next != null) |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
|
|
|
|
|
|
|
|
Stack jumps = (Stack) successors.remove(nextFlow); |
|
|
|
Jump jumps = (Jump) successors.remove(nextFlow); |
|
|
|
/* note that jumps.size() == 1 */ |
|
|
|
/* note that this is the single caseBlock jump */ |
|
|
|
|
|
|
|
|
|
|
|
if (nextFlow.predecessors.size() == 2) { |
|
|
|
if (nextFlow.predecessors.size() == 2) { |
|
|
|
Stack lastJumps = |
|
|
|
Jump lastJumps = |
|
|
|
(Stack) lastFlow.successors.remove(nextFlow); |
|
|
|
(Jump) lastFlow.successors.remove(nextFlow); |
|
|
|
|
|
|
|
|
|
|
|
/* Do the in/out analysis with all jumps |
|
|
|
/* Do the in/out analysis with all jumps |
|
|
|
* Note that this won't update lastFlow.in, but |
|
|
|
* Note that this won't update lastFlow.in, but |
|
|
|
* this will not be used anymore. |
|
|
|
* this will not be used anymore. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
lastJumps.push(jumps.peek()); |
|
|
|
jumps.next = lastJumps; |
|
|
|
updateInOut(nextFlow, true, lastJumps); |
|
|
|
updateInOut(nextFlow, jumps); |
|
|
|
lastJumps.pop(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lastFlow.optimizeJumps(lastJumps, nextFlow); |
|
|
|
lastJumps = |
|
|
|
|
|
|
|
lastFlow.optimizeJumps(lastJumps, nextFlow); |
|
|
|
lastFlow.resolveRemaining(lastJumps); |
|
|
|
lastFlow.resolveRemaining(lastJumps); |
|
|
|
} else |
|
|
|
} else |
|
|
|
updateInOut(nextFlow, true, jumps); |
|
|
|
updateInOut(nextFlow, jumps); |
|
|
|
|
|
|
|
|
|
|
|
if (lastFlow != null) { |
|
|
|
if (lastFlow != null) { |
|
|
|
lastFlow.block.replace |
|
|
|
lastFlow.block.replace |
|
|
@ -1180,21 +1175,30 @@ public class FlowBlock { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void removeSuccessor(Jump jump) { |
|
|
|
public void removeSuccessor(Jump jump) { |
|
|
|
Stack destJumps = (Stack) successors.get(jump.destination); |
|
|
|
Jump destJumps = (Jump) successors.get(jump.destination); |
|
|
|
if (!destJumps.removeElement(jump)) |
|
|
|
Jump prev = null; |
|
|
|
|
|
|
|
while (destJumps != jump && destJumps != null) { |
|
|
|
|
|
|
|
prev = destJumps; |
|
|
|
|
|
|
|
destJumps = destJumps.next; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (destJumps == null) |
|
|
|
throw new AssertError("removing non existent jump"); |
|
|
|
throw new AssertError("removing non existent jump"); |
|
|
|
if (destJumps.isEmpty()) |
|
|
|
if (prev != null) |
|
|
|
successors.remove(jump.destination); |
|
|
|
prev.next = destJumps.next; |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
if (destJumps.next == null) |
|
|
|
|
|
|
|
successors.remove(jump.destination); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
successors.put(jump.destination, destJumps.next); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void addSuccessor(Jump jump) { |
|
|
|
public void addSuccessor(Jump jump) { |
|
|
|
Stack destJumps = (Stack) successors.get(jump.destination); |
|
|
|
jump.next = (Jump) successors.get(jump.destination); |
|
|
|
if (destJumps == null) { |
|
|
|
if (jump.next == null) |
|
|
|
jump.destination.predecessors.addElement(this); |
|
|
|
jump.destination.predecessors.addElement(this); |
|
|
|
destJumps = new Stack(); |
|
|
|
|
|
|
|
successors.put(jump.destination, destJumps); |
|
|
|
successors.put(jump.destination, jump); |
|
|
|
} |
|
|
|
|
|
|
|
destJumps.push(jump); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void makeDeclaration(VariableSet param) { |
|
|
|
public void makeDeclaration(VariableSet param) { |
|
|
|