|
|
@ -60,14 +60,16 @@ import jode.util.SimpleSet; |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class FlowBlock { |
|
|
|
public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
public static FlowBlock END_OF_METHOD = |
|
|
|
public static FlowBlock END_OF_METHOD; |
|
|
|
new FlowBlock(null, Integer.MAX_VALUE, 0, new EmptyBlock()); |
|
|
|
public static FlowBlock NEXT_BY_ADDR; |
|
|
|
|
|
|
|
|
|
|
|
public static FlowBlock NEXT_BY_ADDR = |
|
|
|
|
|
|
|
new FlowBlock(null, -1, 0, new DescriptionBlock("FALL THROUGH")); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static { |
|
|
|
static { |
|
|
|
|
|
|
|
END_OF_METHOD = new FlowBlock(null, Integer.MAX_VALUE); |
|
|
|
|
|
|
|
END_OF_METHOD.appendBlock(new EmptyBlock(), 0); |
|
|
|
END_OF_METHOD.label = "END_OF_METHOD"; |
|
|
|
END_OF_METHOD.label = "END_OF_METHOD"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NEXT_BY_ADDR = new FlowBlock(null, -1); |
|
|
|
|
|
|
|
NEXT_BY_ADDR.appendBlock(new DescriptionBlock("FALL THROUGH"), 0); |
|
|
|
NEXT_BY_ADDR.label = "NEXT_BY_ADDR"; |
|
|
|
NEXT_BY_ADDR.label = "NEXT_BY_ADDR"; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -182,33 +184,9 @@ public class FlowBlock { |
|
|
|
/** |
|
|
|
/** |
|
|
|
* The default constructor. Creates a new empty flowblock. |
|
|
|
* The default constructor. Creates a new empty flowblock. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public FlowBlock(MethodAnalyzer method, int addr, int length) { |
|
|
|
public FlowBlock(MethodAnalyzer method, int addr) { |
|
|
|
this.method = method; |
|
|
|
this.method = method; |
|
|
|
this.addr = addr; |
|
|
|
this.addr = addr; |
|
|
|
this.length = length; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* The default constructor. Creates a new flowblock containing |
|
|
|
|
|
|
|
* only the given structured block. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public FlowBlock(MethodAnalyzer method, int addr, int length, |
|
|
|
|
|
|
|
StructuredBlock block) { |
|
|
|
|
|
|
|
this.method = method; |
|
|
|
|
|
|
|
this.addr = addr; |
|
|
|
|
|
|
|
this.length = length; |
|
|
|
|
|
|
|
setBlock(block); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void setBlock(StructuredBlock block) { |
|
|
|
|
|
|
|
if (this.block != null) |
|
|
|
|
|
|
|
throw new jode.AssertError("FlowBlock.setBlock called twice"); |
|
|
|
|
|
|
|
this.block = block; |
|
|
|
|
|
|
|
lastModified = block; |
|
|
|
|
|
|
|
block.setFlowBlock(this); |
|
|
|
|
|
|
|
block.fillInGenSet(in, gen); |
|
|
|
|
|
|
|
block.fillSuccessors(); |
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public final int getNextAddr() { |
|
|
|
public final int getNextAddr() { |
|
|
@ -692,7 +670,7 @@ public class FlowBlock { |
|
|
|
SuccessorInfo succSuccInfo = (SuccessorInfo) i.next(); |
|
|
|
SuccessorInfo succSuccInfo = (SuccessorInfo) i.next(); |
|
|
|
succSuccInfo.gen.mergeGenKill(gens, succSuccInfo.kill); |
|
|
|
succSuccInfo.gen.mergeGenKill(gens, succSuccInfo.kill); |
|
|
|
if (successor != this) |
|
|
|
if (successor != this) |
|
|
|
succSuccInfo.kill.addAll(kills); |
|
|
|
succSuccInfo.kill.mergeKill(kills); |
|
|
|
} |
|
|
|
} |
|
|
|
this.in.addAll(newIn); |
|
|
|
this.in.addAll(newIn); |
|
|
|
this.gen.addAll(successor.gen); |
|
|
|
this.gen.addAll(successor.gen); |
|
|
@ -829,47 +807,58 @@ public class FlowBlock { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void appendBlock(StructuredBlock block, int length) { |
|
|
|
/** |
|
|
|
SlotSet succIn = new SlotSet(); |
|
|
|
* This is a special T2 transformation, that does also succeed, if |
|
|
|
|
|
|
|
* the jumps in the flow block are not yet resolved. But it has |
|
|
|
|
|
|
|
* a special precondition: The succ must be a simple instruction block, |
|
|
|
|
|
|
|
* mustn't have another predecessor and all structured blocks in this |
|
|
|
|
|
|
|
* flow block must be simple instruction blocks. |
|
|
|
|
|
|
|
* @param succ The successing structured block that should be merged. |
|
|
|
|
|
|
|
* @param length the length of the structured block. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void doSequentialT2(StructuredBlock succ, int length) { |
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
|
|
|
|
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0) { |
|
|
|
|
|
|
|
GlobalOptions.err.println("merging sequentialBlock: "+this); |
|
|
|
|
|
|
|
GlobalOptions.err.println("and: "+succ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
SlotSet succIn = new SlotSet(); |
|
|
|
|
|
|
|
SlotSet succKill = new SlotSet(); |
|
|
|
SlotSet succKill = new SlotSet(); |
|
|
|
VariableSet succGen = new VariableSet(); |
|
|
|
VariableSet succGen = new VariableSet(); |
|
|
|
succ.fillInGenSet(succIn, succKill); |
|
|
|
block.fillInGenSet(succIn, succKill); |
|
|
|
succGen.addAll(succKill); |
|
|
|
succGen.addAll(succKill); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (this.block == null) { |
|
|
|
|
|
|
|
this.block = block; |
|
|
|
|
|
|
|
lastModified = block; |
|
|
|
|
|
|
|
block.setFlowBlock(this); |
|
|
|
|
|
|
|
block.fillSuccessors(); |
|
|
|
|
|
|
|
this.length = length; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
in = succIn; |
|
|
|
|
|
|
|
gen = succGen; |
|
|
|
|
|
|
|
for (Iterator i = successors.values().iterator(); i.hasNext();) { |
|
|
|
|
|
|
|
SuccessorInfo info = (SuccessorInfo) i.next(); |
|
|
|
|
|
|
|
info.gen = new VariableSet(); |
|
|
|
|
|
|
|
info.kill = new SlotSet(); |
|
|
|
|
|
|
|
info.gen.addAll(succGen); |
|
|
|
|
|
|
|
info.kill.addAll(succKill); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
|
|
|
|
if ((GlobalOptions.debuggingFlags |
|
|
|
|
|
|
|
& GlobalOptions.DEBUG_FLOW) != 0) { |
|
|
|
|
|
|
|
GlobalOptions.err.println("appending Block: "+block); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
SuccessorInfo succInfo = (SuccessorInfo) successors.get(NEXT_BY_ADDR); |
|
|
|
SuccessorInfo succInfo |
|
|
|
succIn.merge(succInfo.gen); |
|
|
|
= (SuccessorInfo) successors.get(NEXT_BY_ADDR); |
|
|
|
succIn.removeAll(succInfo.kill); |
|
|
|
succIn.merge(succInfo.gen); |
|
|
|
|
|
|
|
succIn.removeAll(succInfo.kill); |
|
|
|
succGen.mergeGenKill(succInfo.gen, succKill); |
|
|
|
|
|
|
|
succKill.addAll(succInfo.kill); |
|
|
|
succGen.mergeGenKill(succInfo.gen, succKill); |
|
|
|
this.in.addAll(succIn); |
|
|
|
succKill.mergeKill(succInfo.kill); |
|
|
|
this.gen.addAll(succKill); |
|
|
|
this.in.addAll(succIn); |
|
|
|
|
|
|
|
this.gen.addAll(succKill); |
|
|
|
removeSuccessor(lastModified.jump); |
|
|
|
|
|
|
|
lastModified.removeJump(); |
|
|
|
removeSuccessor(lastModified.jump); |
|
|
|
lastModified = lastModified.appendBlock(succ); |
|
|
|
lastModified.removeJump(); |
|
|
|
succ.fillSuccessors(); |
|
|
|
lastModified = lastModified.appendBlock(block); |
|
|
|
succInfo = (SuccessorInfo) successors.get(NEXT_BY_ADDR); |
|
|
|
block.fillSuccessors(); |
|
|
|
succInfo.gen = succGen; |
|
|
|
succInfo = (SuccessorInfo) successors.get(NEXT_BY_ADDR); |
|
|
|
succInfo.kill = succKill; |
|
|
|
succInfo.gen = succGen; |
|
|
|
this.length += length; |
|
|
|
succInfo.kill = succKill; |
|
|
|
checkConsistent(); |
|
|
|
this.length += length; |
|
|
|
doTransformations(); |
|
|
|
checkConsistent(); |
|
|
|
|
|
|
|
doTransformations(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -925,6 +914,12 @@ public class FlowBlock { |
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
succ.checkConsistent(); |
|
|
|
succ.checkConsistent(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((GlobalOptions.debuggingFlags |
|
|
|
|
|
|
|
& GlobalOptions.DEBUG_ANALYZE) != 0) |
|
|
|
|
|
|
|
GlobalOptions.err.println |
|
|
|
|
|
|
|
("T2(["+addr+","+getNextAddr()+"],[" |
|
|
|
|
|
|
|
+succ.addr+","+succ.getNextAddr()+"])"); |
|
|
|
|
|
|
|
|
|
|
|
SuccessorInfo succInfo = (SuccessorInfo) successors.remove(succ); |
|
|
|
SuccessorInfo succInfo = (SuccessorInfo) successors.remove(succ); |
|
|
|
|
|
|
|
|
|
|
|
/* Update the in/out-Vectors now */ |
|
|
|
/* Update the in/out-Vectors now */ |
|
|
@ -1051,6 +1046,8 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_ANALYZE) != 0) |
|
|
|
|
|
|
|
GlobalOptions.err.println("T1(["+addr+","+getNextAddr()+"])"); |
|
|
|
SuccessorInfo succInfo = (SuccessorInfo) successors.remove(this); |
|
|
|
SuccessorInfo succInfo = (SuccessorInfo) successors.remove(this); |
|
|
|
|
|
|
|
|
|
|
|
/* Update the in/out-Vectors now */ |
|
|
|
/* Update the in/out-Vectors now */ |
|
|
@ -1203,11 +1200,12 @@ public class FlowBlock { |
|
|
|
GlobalOptions.err.println("before Transformation: "+this); |
|
|
|
GlobalOptions.err.println("before Transformation: "+this); |
|
|
|
|
|
|
|
|
|
|
|
while (lastModified instanceof SequentialBlock) { |
|
|
|
while (lastModified instanceof SequentialBlock) { |
|
|
|
if (!lastModified.getSubBlocks()[0].doTransformations()) |
|
|
|
if (lastModified.getSubBlocks()[0].doTransformations()) |
|
|
|
lastModified = lastModified.getSubBlocks()[1]; |
|
|
|
continue; |
|
|
|
|
|
|
|
lastModified = lastModified.getSubBlocks()[1]; |
|
|
|
} |
|
|
|
} |
|
|
|
while (lastModified.doTransformations()) |
|
|
|
while (lastModified.doTransformations()) |
|
|
|
/* empty */; |
|
|
|
{ /* empty */ } |
|
|
|
|
|
|
|
|
|
|
|
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0) |
|
|
|
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0) |
|
|
|
GlobalOptions.err.println("after Transformation: "+this); |
|
|
|
GlobalOptions.err.println("after Transformation: "+this); |
|
|
@ -1261,7 +1259,7 @@ public class FlowBlock { |
|
|
|
boolean changed = false; |
|
|
|
boolean changed = false; |
|
|
|
|
|
|
|
|
|
|
|
while (true) { |
|
|
|
while (true) { |
|
|
|
|
|
|
|
|
|
|
|
if (lastModified instanceof SwitchBlock) { |
|
|
|
if (lastModified instanceof SwitchBlock) { |
|
|
|
/* analyze the switch first. |
|
|
|
/* analyze the switch first. |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -1274,9 +1272,6 @@ public class FlowBlock { |
|
|
|
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0) |
|
|
|
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0) |
|
|
|
GlobalOptions.err.println("after T1: "+this); |
|
|
|
GlobalOptions.err.println("after T1: "+this); |
|
|
|
|
|
|
|
|
|
|
|
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_ANALYZE) != 0) |
|
|
|
|
|
|
|
GlobalOptions.err.println("T1("+addr+","+getNextAddr() |
|
|
|
|
|
|
|
+") succeeded"); |
|
|
|
|
|
|
|
/* T1 transformation succeeded. This may |
|
|
|
/* T1 transformation succeeded. This may |
|
|
|
* make another T2 analysis in the previous |
|
|
|
* make another T2 analysis in the previous |
|
|
|
* block possible. |
|
|
|
* block possible. |
|
|
@ -1301,20 +1296,17 @@ public class FlowBlock { |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if ((nextByAddr == succ || succ.nextByAddr == this) |
|
|
|
if ((nextByAddr == succ || succ.nextByAddr == this) |
|
|
|
/* Only do T2 transformation if the blocks are |
|
|
|
/* Only do T2 transformation if the blocks are |
|
|
|
* adjacent. */ |
|
|
|
* adjacent. |
|
|
|
|
|
|
|
*/ |
|
|
|
&& doT2(succ)) { |
|
|
|
&& doT2(succ)) { |
|
|
|
/* T2 transformation succeeded. */ |
|
|
|
/* T2 transformation succeeded. */ |
|
|
|
changed = true; |
|
|
|
changed = true; |
|
|
|
|
|
|
|
|
|
|
|
if ((GlobalOptions.debuggingFlags |
|
|
|
|
|
|
|
& GlobalOptions.DEBUG_FLOW) != 0) |
|
|
|
|
|
|
|
GlobalOptions.err.println("after T2: "+this); |
|
|
|
|
|
|
|
if ((GlobalOptions.debuggingFlags |
|
|
|
if ((GlobalOptions.debuggingFlags |
|
|
|
& GlobalOptions.DEBUG_ANALYZE) != 0) |
|
|
|
& GlobalOptions.DEBUG_FLOW) != 0) |
|
|
|
GlobalOptions.err.println |
|
|
|
GlobalOptions.err.println("after T2: "+this); |
|
|
|
("T2("+addr+","+getNextAddr()+") succeeded"); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Check if all predecessors of succ |
|
|
|
/* Check if all predecessors of succ |
|
|
|
* lie in range [start,end). Otherwise |
|
|
|
* lie in range [start,end). Otherwise |
|
|
@ -1363,6 +1355,9 @@ public class FlowBlock { |
|
|
|
* @param end the end of the address range. |
|
|
|
* @param end the end of the address range. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public boolean analyzeSwitch(int start, int end) { |
|
|
|
public boolean analyzeSwitch(int start, int end) { |
|
|
|
|
|
|
|
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_ANALYZE) != 0) |
|
|
|
|
|
|
|
GlobalOptions.err.println("analyzeSwitch("+start+", "+end+")"); |
|
|
|
|
|
|
|
|
|
|
|
SwitchBlock switchBlock = (SwitchBlock) lastModified; |
|
|
|
SwitchBlock switchBlock = (SwitchBlock) lastModified; |
|
|
|
boolean changed = false; |
|
|
|
boolean changed = false; |
|
|
|
|
|
|
|
|
|
|
@ -1453,6 +1448,11 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0) |
|
|
|
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0) |
|
|
|
GlobalOptions.err.println("after analyzeSwitch: "+this); |
|
|
|
GlobalOptions.err.println("after analyzeSwitch: "+this); |
|
|
|
|
|
|
|
if ((GlobalOptions.debuggingFlags |
|
|
|
|
|
|
|
& GlobalOptions.DEBUG_ANALYZE) != 0) |
|
|
|
|
|
|
|
GlobalOptions.err.println |
|
|
|
|
|
|
|
("analyzeSwitch done: " + start + " - " + end + "; " |
|
|
|
|
|
|
|
+ addr + " - " + getNextAddr()); |
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
return changed; |
|
|
|
return changed; |
|
|
|
} |
|
|
|
} |
|
|
@ -1504,10 +1504,6 @@ public class FlowBlock { |
|
|
|
SuccessorInfo info = (SuccessorInfo) successors.get(jump.destination); |
|
|
|
SuccessorInfo info = (SuccessorInfo) successors.get(jump.destination); |
|
|
|
if (info == null) { |
|
|
|
if (info == null) { |
|
|
|
info = new SuccessorInfo(); |
|
|
|
info = new SuccessorInfo(); |
|
|
|
info.gen = new VariableSet(); |
|
|
|
|
|
|
|
info.kill = new SlotSet(); |
|
|
|
|
|
|
|
block.fillInGenSet(null, info.kill); |
|
|
|
|
|
|
|
info.gen.addAll(info.kill); |
|
|
|
|
|
|
|
info.jumps = jump; |
|
|
|
info.jumps = jump; |
|
|
|
if (jump.destination != END_OF_METHOD) |
|
|
|
if (jump.destination != END_OF_METHOD) |
|
|
|
jump.destination.predecessors.add(this); |
|
|
|
jump.destination.predecessors.add(this); |
|
|
|