some changes, especially resolveJump()... has to do with new BytecodeInfo

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@457 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 8e762d9d2e
commit 2a2e89452e
  1. 170
      jode/jode/flow/FlowBlock.java

@ -37,14 +37,15 @@ import jode.expr.CombineableOperator;
*/ */
public class FlowBlock { public class FlowBlock {
static FlowBlock END_OF_METHOD = public static FlowBlock END_OF_METHOD =
new FlowBlock(null, Integer.MAX_VALUE, 0, new EmptyBlock()); new FlowBlock(null, Integer.MAX_VALUE, 0, new EmptyBlock());
static FlowBlock ILLEGAL = public static FlowBlock NEXT_BY_ADDR =
new FlowBlock(null, -1, 0, new DescriptionBlock("ILLEGAL BLOCK")); new FlowBlock(null, -1, 0, new DescriptionBlock("FALL THROUGH"));
static { static {
END_OF_METHOD.label = "END_OF_METHOD"; END_OF_METHOD.label = "END_OF_METHOD";
NEXT_BY_ADDR.label = "NEXT_BY_ADDR";
} }
/** /**
@ -109,13 +110,6 @@ public class FlowBlock {
*/ */
Vector predecessors = new Vector(); Vector predecessors = new Vector();
/**
* This is set if the block is reachable. If this is false after
* marking the start block and the catch blocks as reachable, this
* block is dead code and may (must) be removed.
*/
boolean reachable = false;
/** /**
* This is a pointer to the next flow block in byte code order. * This is a pointer to the next flow block in byte code order.
* It is null for the last flow block. * It is null for the last flow block.
@ -135,6 +129,15 @@ public class FlowBlock {
*/ */
VariableStack stackMap; VariableStack stackMap;
/**
* The default constructor. Creates a new empty flowblock.
*/
public FlowBlock(CodeAnalyzer code, int addr, int length) {
this.code = code;
this.addr = addr;
this.length = length;
}
/** /**
* The default constructor. Creates a new flowblock containing * The default constructor. Creates a new flowblock containing
* only the given structured block. * only the given structured block.
@ -144,10 +147,18 @@ public class FlowBlock {
this.code = code; this.code = code;
this.addr = addr; this.addr = addr;
this.length = length; 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; this.block = block;
lastModified = block; lastModified = block;
block.setFlowBlock(this); block.setFlowBlock(this);
block.fillInGenSet(in, gen); block.fillInGenSet(in, gen);
block.fillSuccessors();
checkConsistent();
} }
public final int getNextAddr() { public final int getNextAddr() {
@ -589,27 +600,6 @@ public class FlowBlock {
} }
} }
// /**
// * Mark all predecessors of this block as illegal, i.e. change the
// * successor to the ILLEGAL block.
// */
// public void markPredecessorsIllegal() {
// Enumeration preds = predecessors.elements();
// while (preds.hasMoreElements()) {
// FlowBlock pred = (FlowBlock) preds.nextElement();
// Jump jump = (Jump)pred.successors.remove(this);
// for (/**/; jump.next != null; jump = jump.next)
// jump.destination = ILLEGAL;
// jump.destination = ILLEGAL;
// jump.next = (Jump) pred.successors.get(jump.destination);
// if (jump.next == null)
// ILLEGAL.predecessors.addElement(this);
// pred.successors.put(jump.destination, jump);
// }
// predecessors.removeAllElements();
// }
/** /**
* 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.
@ -679,6 +669,7 @@ public class FlowBlock {
if (!Decompiler.doChecks) if (!Decompiler.doChecks)
return; return;
try {
if (block.outer != null || block.flowBlock != this) { if (block.outer != null || block.flowBlock != this) {
throw new AssertError("Inconsistency"); throw new AssertError("Inconsistency");
} }
@ -717,8 +708,9 @@ public class FlowBlock {
if (jumps.destination != dest) if (jumps.destination != dest)
throw new AssertError("Inconsistency"); throw new AssertError("Inconsistency");
if (jumps.prev.flowBlock != this || if (jumps.prev == null
jumps.prev.jump != jumps) || jumps.prev.flowBlock != this
|| jumps.prev.jump != jumps)
throw new AssertError("Inconsistency"); throw new AssertError("Inconsistency");
prev_loop: prev_loop:
@ -736,6 +728,10 @@ public class FlowBlock {
} }
} }
} }
} catch (AssertError err) {
System.err.println("Inconsistency in: "+this);
throw err;
}
} }
@ -749,6 +745,7 @@ public class FlowBlock {
* @param length the length of the structured block. * @param length the length of the structured block.
*/ */
public void doSequentialT1(StructuredBlock succ, int length) { public void doSequentialT1(StructuredBlock succ, int length) {
checkConsistent();
if (Decompiler.isFlowDebugging) { if (Decompiler.isFlowDebugging) {
Decompiler.err.println("merging sequentialBlock: "+this); Decompiler.err.println("merging sequentialBlock: "+this);
Decompiler.err.println("and: "+succ); Decompiler.err.println("and: "+succ);
@ -758,16 +755,40 @@ public class FlowBlock {
succIn.merge(lastModified.jump.gen); succIn.merge(lastModified.jump.gen);
succIn.subtract(lastModified.jump.kill); succIn.subtract(lastModified.jump.kill);
succ.jump.gen.mergeGenKill(lastModified.jump.gen, succ.jump.kill); succ.jump.gen.mergeGenKill(lastModified.jump.gen, succ.jump.kill);
succ.jump.kill.add(lastModified.jump.kill); succ.jump.kill.add(lastModified.jump.kill);
this.in.unionExact(succIn); this.in.unionExact(succIn);
removeSuccessor(lastModified.jump);
lastModified.removeJump(); lastModified.removeJump();
lastModified = lastModified.appendBlock(succ); lastModified = lastModified.appendBlock(succ);
succ.fillSuccessors();
this.length += length; this.length += length;
checkConsistent();
doTransformations(); doTransformations();
} }
/**
* Append the given flowblock to the nextByAddr/prevByAddr chain.
* nextByAddr should be null, when calling this.
* @param flow The flowBlock to append
*/
public void setNextByAddr(FlowBlock flow) {
Jump jumps = (Jump) successors.remove(NEXT_BY_ADDR);
if (jumps != null) {
NEXT_BY_ADDR.predecessors.removeElement(this);
for (Jump jump = jumps; jump != null; jump = jump.next)
jump.destination = flow;
successors.put(flow, jumps);
flow.predecessors.addElement(this);
}
checkConsistent();
nextByAddr = flow;
flow.prevByAddr = this;
}
/** /**
* Do a T1 transformation with succ if possible. It is possible, * Do a T1 transformation with succ if possible. It is possible,
* iff succ has exactly this block as predecessor. * iff succ has exactly this block as predecessor.
@ -1154,6 +1175,7 @@ public class FlowBlock {
if (Decompiler.debugAnalyze) if (Decompiler.debugAnalyze)
Decompiler.err.println("analyze("+start+", "+end+")"); Decompiler.err.println("analyze("+start+", "+end+")");
checkConsistent();
boolean changed = false; boolean changed = false;
while (true) { while (true) {
@ -1307,7 +1329,7 @@ public class FlowBlock {
lastJumps = lastJumps =
lastFlow.resolveSomeJumps(lastJumps, nextFlow); lastFlow.resolveSomeJumps(lastJumps, nextFlow);
lastFlow.resolveRemaining(lastJumps); lastFlow.resolveRemaining(lastJumps);
switchBlock.caseBlocks[last].isFallThrough = true; switchBlock.caseBlocks[last+1].isFallThrough = true;
} else } else
updateInOut(nextFlow, jumps); updateInOut(nextFlow, jumps);
@ -1341,37 +1363,6 @@ public class FlowBlock {
return changed; return changed;
} }
/**
* Resolves the destinations of all jumps. This will also create
* the successors map.
*/
public void resolveJumps(FlowBlock[] instr) {
Vector allJumps = new Vector();
block.fillSuccessors(allJumps);
Enumeration enum = allJumps.elements();
while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement();
if (jump != null && jump.destination == null) {
if (jump.destAddr == -1)
jump.destination = END_OF_METHOD;
else if (jump.destAddr == instr.length)
// In this case, the jump must belong to dead code.
jump.destination = ILLEGAL;
else {
jump.destination = instr[jump.destAddr];
if (jump.destination == null)
throw new AssertError("Missing dest: "+jump.destAddr);
}
addSuccessor(jump);
}
}
if (getNextAddr() < instr.length) {
nextByAddr = instr[getNextAddr()];
nextByAddr.prevByAddr = this;
}
}
/** /**
* Mark the flow block as first flow block in a method. * Mark the flow block as first flow block in a method.
*/ */
@ -1387,7 +1378,7 @@ public class FlowBlock {
destJumps = destJumps.next; destJumps = destJumps.next;
} }
if (destJumps == null) if (destJumps == null)
throw new AssertError(""+addr+": removing non existent jump: " + jump); throw new AssertError(addr+": removing non existent jump: " + jump);
if (prev != null) if (prev != null)
prev.next = destJumps.next; prev.next = destJumps.next;
else { else {
@ -1481,44 +1472,6 @@ public class FlowBlock {
block.makeDeclaration(param); block.makeDeclaration(param);
} }
/**
* Mark this block and all successing blocks as reachable. */
public void markReachable() {
if (reachable) {
// This block was already checked. This prevents infinite
// recursion.
return;
}
reachable = true;
Enumeration succs = successors.keys();
while (succs.hasMoreElements())
((FlowBlock) succs.nextElement()).markReachable();
}
/**
* Removes dead code, i.e. merges the dead flow block with there
* prevByAddr and removing their code completely. <br>
*
* Why is it necessary? Because jikes actually generates a lot
* of dead code in try, catch and finally blocks. This will break
* a lot of other code, e.g. checking that a catch handler has no
* entries or merging only adjacent blocks.
*
* @param flow The first flow block in this method.
*/
public static void removeDeadCode(FlowBlock flow) {
while (flow.nextByAddr != null) {
if (!flow.nextByAddr.reachable) {
Enumeration succs = flow.nextByAddr.successors.keys();
while (succs.hasMoreElements())
((FlowBlock) succs.nextElement()).predecessors
.removeElement(flow.nextByAddr);
flow.mergeAddr(flow.nextByAddr);
} else
flow = flow.nextByAddr;
}
}
/** /**
* Print the source code for this structured block. This handles * Print the source code for this structured block. This handles
* everything that is unique for all structured blocks and calls * everything that is unique for all structured blocks and calls
@ -1554,6 +1507,13 @@ public class FlowBlock {
*/ */
String label = null; String label = null;
/**
* Returns the address, where the code in this flow block starts.
*/
public int getAddr() {
return addr;
}
/** /**
* Returns the label of this block and creates a new label, if * Returns the label of this block and creates a new label, if
* there wasn't a label previously. * there wasn't a label previously.
@ -1575,7 +1535,7 @@ public class FlowBlock {
try { try {
java.io.StringWriter strw = new java.io.StringWriter(); java.io.StringWriter strw = new java.io.StringWriter();
TabbedPrintWriter writer = new TabbedPrintWriter(strw); TabbedPrintWriter writer = new TabbedPrintWriter(strw);
writer.println(super.toString()); writer.println(super.toString() + ": "+addr+"-"+(addr+length));
writer.tab(); writer.tab();
block.dumpSource(writer); block.dumpSource(writer);
return strw.toString(); return strw.toString();

Loading…
Cancel
Save