diff --git a/jode/jode/flow/FlowBlock.java b/jode/jode/flow/FlowBlock.java index fc7fa38..03a8942 100644 --- a/jode/jode/flow/FlowBlock.java +++ b/jode/jode/flow/FlowBlock.java @@ -37,14 +37,15 @@ import jode.expr.CombineableOperator; */ public class FlowBlock { - static FlowBlock END_OF_METHOD = + public static FlowBlock END_OF_METHOD = new FlowBlock(null, Integer.MAX_VALUE, 0, new EmptyBlock()); - static FlowBlock ILLEGAL = - new FlowBlock(null, -1, 0, new DescriptionBlock("ILLEGAL BLOCK")); + public static FlowBlock NEXT_BY_ADDR = + new FlowBlock(null, -1, 0, new DescriptionBlock("FALL THROUGH")); static { 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(); - /** - * 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. * It is null for the last flow block. @@ -135,6 +129,15 @@ public class FlowBlock { */ 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 * only the given structured block. @@ -144,10 +147,18 @@ public class FlowBlock { this.code = code; 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() { @@ -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 * successing flow block simultanous to a T1 transformation. @@ -679,6 +669,7 @@ public class FlowBlock { if (!Decompiler.doChecks) return; + try { if (block.outer != null || block.flowBlock != this) { throw new AssertError("Inconsistency"); } @@ -717,8 +708,9 @@ public class FlowBlock { if (jumps.destination != dest) throw new AssertError("Inconsistency"); - if (jumps.prev.flowBlock != this || - jumps.prev.jump != jumps) + if (jumps.prev == null + || jumps.prev.flowBlock != this + || jumps.prev.jump != jumps) throw new AssertError("Inconsistency"); 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. */ public void doSequentialT1(StructuredBlock succ, int length) { + checkConsistent(); if (Decompiler.isFlowDebugging) { Decompiler.err.println("merging sequentialBlock: "+this); Decompiler.err.println("and: "+succ); @@ -758,16 +755,40 @@ public class FlowBlock { succIn.merge(lastModified.jump.gen); succIn.subtract(lastModified.jump.kill); + succ.jump.gen.mergeGenKill(lastModified.jump.gen, succ.jump.kill); succ.jump.kill.add(lastModified.jump.kill); this.in.unionExact(succIn); + removeSuccessor(lastModified.jump); lastModified.removeJump(); lastModified = lastModified.appendBlock(succ); + succ.fillSuccessors(); this.length += length; + checkConsistent(); 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, * iff succ has exactly this block as predecessor. @@ -1154,6 +1175,7 @@ public class FlowBlock { if (Decompiler.debugAnalyze) Decompiler.err.println("analyze("+start+", "+end+")"); + checkConsistent(); boolean changed = false; while (true) { @@ -1307,7 +1329,7 @@ public class FlowBlock { lastJumps = lastFlow.resolveSomeJumps(lastJumps, nextFlow); lastFlow.resolveRemaining(lastJumps); - switchBlock.caseBlocks[last].isFallThrough = true; + switchBlock.caseBlocks[last+1].isFallThrough = true; } else updateInOut(nextFlow, jumps); @@ -1341,37 +1363,6 @@ public class FlowBlock { 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. */ @@ -1387,7 +1378,7 @@ public class FlowBlock { destJumps = destJumps.next; } if (destJumps == null) - throw new AssertError(""+addr+": removing non existent jump: " + jump); + throw new AssertError(addr+": removing non existent jump: " + jump); if (prev != null) prev.next = destJumps.next; else { @@ -1481,44 +1472,6 @@ public class FlowBlock { 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.
- * - * 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 * everything that is unique for all structured blocks and calls @@ -1554,6 +1507,13 @@ public class FlowBlock { */ 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 * there wasn't a label previously. @@ -1575,7 +1535,7 @@ public class FlowBlock { try { java.io.StringWriter strw = new java.io.StringWriter(); TabbedPrintWriter writer = new TabbedPrintWriter(strw); - writer.println(super.toString()); + writer.println(super.toString() + ": "+addr+"-"+(addr+length)); writer.tab(); block.dumpSource(writer); return strw.toString();