diff --git a/jode/jode/decompiler/CodeAnalyzer.java b/jode/jode/decompiler/CodeAnalyzer.java index 18b6865..70581d2 100644 --- a/jode/jode/decompiler/CodeAnalyzer.java +++ b/jode/jode/decompiler/CodeAnalyzer.java @@ -22,6 +22,9 @@ import sun.tools.java.*; import java.util.Stack; import java.io.*; import jode.flow.FlowBlock; +import jode.flow.Jump; +import jode.flow.StructuredBlock; +import jode.flow.RawTryCatchBlock; public class CodeAnalyzer implements Analyzer, Constants { @@ -31,6 +34,7 @@ public class CodeAnalyzer implements Analyzer, Constants { MethodAnalyzer method; public JodeEnvironment env; + jode.flow.VariableSet param; LocalVariableTable lvt; /** @@ -73,26 +77,43 @@ public class CodeAnalyzer implements Analyzer, Constants { } catch (IOException ex) { throw new ClassFormatError(ex.toString()); } - BinaryExceptionHandler[] handlers = bincode.getExceptionHandlers(); for (int addr=0; addr handlers[i].handlerPC)) { + + tryBlock = ((RawTryCatchBlock)tryBlock).getTryBlock(); + } + + Type type = + (handlers[i].exceptionClass != null)? + handlers[i].exceptionClass.getType() : null; + + new RawTryCatchBlock(type, tryBlock, + new Jump(instr[handlers[i].endPC]), + new Jump(instr[handlers[i].handlerPC])); + } + + int paramCount = method.mdef.getType().getArgumentTypes().length + + (method.mdef.isStatic() ? 0 : 1); + param = new jode.flow.VariableSet(); + for (int i=0; i 1)); - continue next_jump; + if (prevBlock instanceof EmptyBlock) { + if (prevBlock.outer instanceof ConditionalBlock) { + IfThenElseBlock ifBlock = + new IfThenElseBlock + (((ConditionalBlock)prevBlock.outer) + .getInstruction()); + ifBlock.replace(prevBlock.outer, prevBlock); + ifBlock.moveJump(prevBlock.outer); + ifBlock.setThenBlock(prevBlock); + } + new BreakBlock((BreakableBlock) surrounder, + breaklevel >1 + ).replace(prevBlock, null); + } else { + sequBlock.replace(prevBlock, prevBlock); + sequBlock.setFirst(prevBlock); + sequBlock.setSecond + (new BreakBlock((BreakableBlock) surrounder, + breaklevel > 1)); + } + continue same_jump; } } } @@ -373,8 +429,8 @@ public class FlowBlock { intersectOut = intersectOut.intersect(jump.out); } - System.err.println("UpdateInOut: allOuts : "+allOuts); - System.err.println(" intersectOut: "+intersectOut); +// System.err.println("UpdateInOut: allOuts : "+allOuts); +// System.err.println(" intersectOut: "+intersectOut); /* Merge the locals used in successing block with those written * by this blocks @@ -382,7 +438,7 @@ public class FlowBlock { VariableSet defineHere = successor.in.merge(allOuts); defineHere.subtractExact(in); - System.err.println(" defineHere : "+defineHere); +// System.err.println(" defineHere : "+defineHere); if (t1Transformation) { /* Now update in and out set of successing block */ successor.in.subtract(intersectOut); @@ -394,9 +450,9 @@ public class FlowBlock { jump.out.add(intersectOut); } } - System.err.println(" successor.in: "+successor.in); +// System.err.println(" successor.in: "+successor.in); in.union(successor.in); - System.err.println(" in : "+in); +// System.err.println(" in : "+in); /* XXX - do something with defineHere */ return defineHere; /*XXX - correct???*/ } @@ -484,7 +540,7 @@ public class FlowBlock { if (prevSucc != null && fb.addr <= prevSucc.addr) continue; if (succ == null || fb.addr < succ.addr) { - System.err.println("trying "+fb.getLabel()); +// System.err.println("trying "+fb.getLabel()); succ = fb; } } @@ -546,13 +602,14 @@ public class FlowBlock { return false; try{ - System.err.println("doing T1 analysis on: "+getLabel()); - System.err.println("***in: "+in); +// System.err.println("doing T1 analysis on: "+getLabel()); +// System.err.println("***in: "+in); checkConsistent(); - System.err.println("and "+succ.getLabel()); - System.err.println("+++in: "+succ.in); +// System.err.println("and "+succ.getLabel()); +// System.err.println("+++in: "+succ.in); succ.checkConsistent(); } catch (RuntimeException ex) { + ex.printStackTrace(); try { jode.TabbedPrintWriter writer = new jode.TabbedPrintWriter(System.err, " "); @@ -573,8 +630,19 @@ public class FlowBlock { if (jump == null || jump.destination != succ) continue; - while (!appendBlock.contains(jump.prev)) + while (!appendBlock.contains(jump.prev)) { appendBlock = appendBlock.outer; + if (appendBlock instanceof SequentialBlock + && appendBlock.getSubBlocks()[0] + instanceof RawTryCatchBlock) { + + /* We leave the catch block of a raw-try-catch-block. + * We shall now create the Catch- resp. FinallyBlock. + */ + appendBlock = + createCatchBlock((SequentialBlock)appendBlock); + } + } /* appendBlock can't be null now, because the * outermost block contains every structured block. */ @@ -650,9 +718,10 @@ public class FlowBlock { } try { - System.err.println("before optimizeJump: "+getLabel()); +// System.err.println("before optimizeJump: "+getLabel()); checkConsistent(); } catch (RuntimeException ex) { + ex.printStackTrace(); try { jode.TabbedPrintWriter writer = new jode.TabbedPrintWriter(System.err, " "); @@ -668,9 +737,10 @@ public class FlowBlock { appendBlock = optimizeJumps(succ, appendBlock); try { - System.err.println("after optimizeJump: "+getLabel()); +// System.err.println("after optimizeJump: "+getLabel()); checkConsistent(); } catch (RuntimeException ex) { + ex.printStackTrace(); try { jode.TabbedPrintWriter writer = new jode.TabbedPrintWriter(System.err, " "); @@ -703,6 +773,7 @@ public class FlowBlock { LoopBlock.FALSE); int breaklevel = 1; + Jump debug=jump; for (StructuredBlock surrounder = jump.prev.outer; surrounder != appendBlock.outer; surrounder = surrounder.outer) { @@ -745,10 +816,11 @@ public class FlowBlock { /* T1 transformation succeeded */ try { - System.err.println("T1 succeeded:"); - System.err.println("===in: "+in); +// System.err.println("T1 succeeded:"); +// System.err.println("===in: "+in); checkConsistent(); } catch (RuntimeException ex) { + ex.printStackTrace(); try { jode.TabbedPrintWriter writer = new jode.TabbedPrintWriter(System.err, " "); @@ -773,17 +845,18 @@ public class FlowBlock { FlowBlock predFlow = (FlowBlock) preds.nextElement(); if (predFlow != null && predFlow != this && !triedBlocks.contains(predFlow)) { - System.err.println("refusing T2 on: "+getLabel()+ - " because of "+predFlow.getLabel()); +// System.err.println("refusing T2 on: "+getLabel()+ +// " because of "+predFlow.getLabel()); /* XXX Is this enough to refuse T2 trafo ??? */ return false; } } try { - System.err.println("doing T2 analysis on: "+getLabel()); +// System.err.println("doing T2 analysis on: "+getLabel()); checkConsistent(); } catch (RuntimeException ex) { + ex.printStackTrace(); try { jode.TabbedPrintWriter writer = new jode.TabbedPrintWriter(System.err, " "); @@ -874,9 +947,10 @@ public class FlowBlock { /* T2 analysis succeeded */ try { - System.err.println("T2 succeeded:"); +// System.err.println("T2 succeeded:"); checkConsistent(); } catch (RuntimeException ex) { + ex.printStackTrace(); try { jode.TabbedPrintWriter writer = new jode.TabbedPrintWriter(System.err, " "); @@ -914,6 +988,12 @@ public class FlowBlock { predecessors.addElement(null); } + public void addSuccessor(Jump jump) { + successors.addElement(jump); + if (!jump.destination.predecessors.contains(this)) + jump.destination.predecessors.addElement(this); + } + public void removeSuccessor(Jump jump) { successors.setElementAt(null, successors.indexOf(jump)); } @@ -969,4 +1049,11 @@ public class FlowBlock { label = "flow_"+addr+"_"+(serialno++)+"_"; return label; } + + /** + * Returns the structured block, that this flow block contains. + */ + public StructuredBlock getBlock() { + return block; + } } diff --git a/jode/jode/flow/RawTryCatchBlock.java b/jode/jode/flow/RawTryCatchBlock.java index 6490f49..e40feb6 100644 --- a/jode/jode/flow/RawTryCatchBlock.java +++ b/jode/jode/flow/RawTryCatchBlock.java @@ -42,24 +42,119 @@ import jode.TabbedPrintWriter; public class RawTryCatchBlock extends StructuredBlock { + public RawTryCatchBlock(sun.tools.java.Type type, + StructuredBlock tryBlock, + Jump endDest, Jump catchDest) { + this.type = type; + + endBlock = new EmptyBlock(endDest); + endBlock.outer = this; + + catchBlock = new EmptyBlock(catchDest); + catchBlock.outer = this; + + replace(tryBlock, tryBlock); + this.tryBlock = tryBlock; + tryBlock.outer = this; + + endBlock.setFlowBlock(flowBlock); + if (tryBlock instanceof RawTryCatchBlock + && ((RawTryCatchBlock)tryBlock).endBlock.jump.destination + == endDest.destination) + endBlock.jump = null; + else + flowBlock.addSuccessor(endDest); + + catchBlock.setFlowBlock(flowBlock); + flowBlock.addSuccessor(catchDest); + } + + /** + * The try block. + */ + StructuredBlock tryBlock; + /** - * An unconditional jump to the EndBlock. + * An empty block containing an unconditional jump to the EndBlock. + * Or null if the try block is completely read. */ - Jump EndBlock; + StructuredBlock endBlock; /** - * An unconditional jump to the CatchBlock. + * The catch block. */ - Jump CatchBlock; + StructuredBlock catchBlock; /** * The type of the exception that is catched. This is null for a * synchronized/finally block */ - jode.MyType type; + sun.tools.java.Type type; + + /** + * Replaces the given sub block with a new block. + * @param oldBlock the old sub block. + * @param newBlock the new sub block. + * @return false, if oldBlock wasn't a direct sub block. + */ + public boolean replaceSubBlock(StructuredBlock oldBlock, + StructuredBlock newBlock) { + if (tryBlock == oldBlock) { + tryBlock = newBlock; + + if (tryBlock instanceof RawTryCatchBlock + && ((RawTryCatchBlock)tryBlock).endBlock.jump.destination + == endBlock.jump.destination) { + endBlock.removeJump(); + } + } else if (endBlock == oldBlock) + endBlock = newBlock; + else if (catchBlock == oldBlock) + catchBlock = newBlock; + else + return false; + return true; + } + + /** + * Returns all sub block of this structured block. + */ + public StructuredBlock[] getSubBlocks() { + StructuredBlock[] result = { tryBlock, endBlock, catchBlock }; + return result; + } + +// /** +// * Determines if there is a sub block, that flows through to the end +// * of this block. If this returns true, you know that jump is null. +// * @return true, if the jump may be safely changed. +// */ +// public boolean jumpMayBeChanged() { +// return ( tryBlock.jump != null || tryBlock.jumpMayBeChanged()) +// && (catchBlock.jump != null || catchBlock.jumpMayBeChanged()); +// } public void dumpInstruction(TabbedPrintWriter writer) throws java.io.IOException { - writer.println("IMPLEMENT FINALLY"); + writer.println("TRY "+(type != null ? type.toString() : "ALL")); + writer.tab(); + tryBlock.dumpSource(writer); + writer.untab(); + writer.println("UNTIL"); + writer.tab(); + endBlock.dumpSource(writer); + writer.untab(); + writer.println("CATCH TO"); + writer.tab(); + catchBlock.dumpSource(writer); + writer.untab(); + } + + public StructuredBlock getTryBlock() { + return tryBlock; + } + + public int getCatchAddr() { + return catchBlock.jump.destination.addr; } }