*** empty log message ***

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@50 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 27 years ago
parent 2d1648439c
commit 92f7046e3f
  1. 430
      jode/jode/flow/FlowBlock.java
  2. 5
      jode/jode/flow/SwitchBlock.java

@ -145,7 +145,9 @@ public class FlowBlock {
/** /**
* This method optimizes the jumps to successor. * This method optimizes the jumps to successor.
* Returns the new appendBlock, it may have changed. * @param successor The successing flow block
* @param appendBlock the block where the successor is appended to.
* @return the new appendBlock, it may have changed.
*/ */
public StructuredBlock optimizeJumps(FlowBlock successor, public StructuredBlock optimizeJumps(FlowBlock successor,
StructuredBlock appendBlock) { StructuredBlock appendBlock) {
@ -374,6 +376,98 @@ public class FlowBlock {
return appendBlock; return appendBlock;
} }
/**
* Move the successors of the given flow block to this flow block.
* @param succ the other flow block
*/
void mergeSuccessors(FlowBlock succ) {
/* Merge the sucessors from the successing flow block
*/
Enumeration enum = succ.successors.elements();
while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement();
if (jump == null)
continue;
successors.addElement(jump);
if (jump.destination.predecessors.contains(succ)) {
/*XXX comment and make clearer, better etc.*/
jump.destination.predecessors.removeElement(succ);
if (!jump.destination.predecessors.contains(this))
jump.destination.predecessors.addElement(this);
}
}
}
/**
* Resolve remaining jumps to the successor by generating break
* instructions. As last resort generate a do while(false) block.
* @param successor The successing flow block
* @param appendBlock the block where the successor is appended to.
* @return the new appendBlock, it may have changed.
*/
StructuredBlock resolveRemaining(FlowBlock succ,
StructuredBlock appendBlock) {
LoopBlock doWhileFalse = null;
Enumeration enum = successors.elements();
next_jump:
while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement();
if (jump == null || jump.destination != succ
|| jump.prev == appendBlock)
continue;
int breaklevel = 0;
BreakableBlock breakToBlock = null;
for (StructuredBlock surrounder = jump.prev.outer;
surrounder != null && surrounder != appendBlock.outer;
surrounder = surrounder.outer) {
if (surrounder instanceof BreakableBlock) {
breaklevel++;
if (surrounder.getNextFlowBlock() == succ) {
breakToBlock = (BreakableBlock) surrounder;
break;
}
}
}
StructuredBlock prevBlock = jump.prev;
prevBlock.removeJump();
if (breakToBlock == null) {
/* Nothing else helped, so put a do/while(0)
* block around appendBlock and break to that
* block.
*/
if (doWhileFalse == null) {
doWhileFalse = new LoopBlock(LoopBlock.DOWHILE,
LoopBlock.FALSE);
doWhileFalse.setJump(new Jump(succ));
successors.addElement(doWhileFalse.jump);
}
prevBlock.appendBlock
(new BreakBlock(doWhileFalse, breaklevel > 0));
} else
prevBlock.appendBlock
(new BreakBlock(breakToBlock, breaklevel > 1));
}
if (doWhileFalse != null) {
doWhileFalse.replace(appendBlock, appendBlock);
doWhileFalse.setBody(appendBlock);
doWhileFalse.removeJump();
}
/* Now remove the jump of the appendBlock if it points to
* successor.
*/
if (appendBlock.jump != null
&& appendBlock.jump.destination == succ)
appendBlock.removeJump();
return appendBlock;
}
/** /**
* 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.
@ -497,34 +591,45 @@ public class FlowBlock {
public void checkConsistent() { public void checkConsistent() {
if (!Decompiler.doChecks) if (!Decompiler.doChecks)
return; return;
if (block.outer != null || block.flowBlock != this) { // try {
throw new RuntimeException("Inconsistency"); if (block.outer != null || block.flowBlock != this) {
}
block.checkConsistent();
Enumeration enum = successors.elements();
while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement();
if (jump == null)
continue;
if (jump.prev.flowBlock != this ||
jump.prev.jump != jump)
throw new RuntimeException("Inconsistency"); throw new RuntimeException("Inconsistency");
}
StructuredBlock sb = jump.prev; block.checkConsistent();
while (sb != block) { Enumeration enum = successors.elements();
if (sb.outer == null) while (enum.hasMoreElements()) {
throw new RuntimeException("Inconsistency"); Jump jump = (Jump) enum.nextElement();
StructuredBlock[] blocks = sb.outer.getSubBlocks(); if (jump == null)
int i; continue;
for (i=0; i<blocks.length; i++)
if (blocks[i] == sb) if (jump.prev.flowBlock != this ||
break; jump.prev.jump != jump)
if (i == blocks.length)
throw new RuntimeException("Inconsistency"); throw new RuntimeException("Inconsistency");
sb = sb.outer;
StructuredBlock sb = jump.prev;
while (sb != block) {
if (sb.outer == null)
throw new RuntimeException("Inconsistency");
StructuredBlock[] blocks = sb.outer.getSubBlocks();
int i;
for (i=0; i<blocks.length; i++)
if (blocks[i] == sb)
break;
if (i == blocks.length)
throw new RuntimeException("Inconsistency");
sb = sb.outer;
}
} }
} // } catch (RuntimeException ex) {
// ex.printStackTrace();
// try {
// jode.TabbedPrintWriter writer =
// new jode.TabbedPrintWriter(System.err, " ");
// writer.tab();
// block.dumpSource(writer);
// } catch (java.io.IOException ioex) {
// }
// }
} }
/** /**
@ -540,20 +645,8 @@ public class FlowBlock {
succ.predecessors.elementAt(0) != this) succ.predecessors.elementAt(0) != this)
return false; return false;
try{ checkConsistent();
checkConsistent(); succ.checkConsistent();
succ.checkConsistent();
} catch (RuntimeException ex) {
ex.printStackTrace();
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
block.dumpSource(writer);
succ.block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
/* First find the innermost block that contains all jumps to this /* First find the innermost block that contains all jumps to this
* successor and the last modified block. * successor and the last modified block.
@ -647,34 +740,9 @@ public class FlowBlock {
sequBlock.setSecond(succ.block); sequBlock.setSecond(succ.block);
} }
/* Merge the sucessors from the successing flow block mergeSuccessors(succ);
*/
enum = succ.successors.elements();
while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement();
if (jump == null)
continue;
successors.addElement(jump);
if (jump.destination.predecessors.contains(succ)) {
/*XXX comment and make clearer, better etc.*/
jump.destination.predecessors.removeElement(succ);
if (!jump.destination.predecessors.contains(this))
jump.destination.predecessors.addElement(this);
}
}
try { checkConsistent();
checkConsistent();
} catch (RuntimeException ex) {
ex.printStackTrace();
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
/* Try to eliminate as many jumps as possible. /* Try to eliminate as many jumps as possible.
*/ */
@ -687,72 +755,9 @@ public class FlowBlock {
appendBlock = optimizeJumps(succ, appendBlock); appendBlock = optimizeJumps(succ, appendBlock);
try { checkConsistent();
checkConsistent();
} catch (RuntimeException ex) {
ex.printStackTrace();
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
LoopBlock doWhileFalse = null;
enum = successors.elements();
next_jump:
while (enum.hasMoreElements()) {
Jump jump = (Jump) enum.nextElement();
if (jump == null || jump.destination != succ
|| jump.prev == appendBlock)
continue;
int breaklevel = 0;
BreakableBlock breakToBlock = null;
for (StructuredBlock surrounder = jump.prev.outer;
surrounder != null && surrounder != appendBlock.outer;
surrounder = surrounder.outer) {
if (surrounder instanceof BreakableBlock) {
breaklevel++;
if (surrounder.getNextFlowBlock() == succ) {
breakToBlock = (BreakableBlock) surrounder;
break;
}
}
}
StructuredBlock prevBlock = jump.prev;
prevBlock.removeJump();
if (breakToBlock == null) {
/* Nothing else helped, so put a do/while(0)
* block around appendBlock and break to that
* block.
*/
if (doWhileFalse == null)
doWhileFalse = new LoopBlock(LoopBlock.DOWHILE,
LoopBlock.FALSE);
prevBlock.appendBlock
(new BreakBlock(doWhileFalse, breaklevel > 0));
} else
prevBlock.appendBlock
(new BreakBlock(breakToBlock, breaklevel > 1));
}
if (doWhileFalse != null) {
doWhileFalse.replace(appendBlock, appendBlock);
doWhileFalse.setBody(appendBlock);
}
/* Now remove the jump of the appendBlock if it points to appendBlock = resolveRemaining(succ, appendBlock);
* successor.
*/
if (appendBlock.jump != null
&& appendBlock.jump.destination == succ)
appendBlock.removeJump();
} }
/* Believe it or not: Now the rule, that the first part of a /* Believe it or not: Now the rule, that the first part of a
@ -774,21 +779,11 @@ public class FlowBlock {
length += succ.length; length += succ.length;
/* T1 transformation succeeded */ /* T1 transformation succeeded */
try { checkConsistent();
checkConsistent();
} catch (RuntimeException ex) {
ex.printStackTrace();
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
return true; return true;
} }
public boolean doT2(int start, int end) { public boolean doT2(int start, int end) {
/* If there are no jumps to the beginning of this flow block /* If there are no jumps to the beginning of this flow block
* or if this block has other predecessors with a higher * or if this block has other predecessors with a higher
@ -806,18 +801,7 @@ public class FlowBlock {
} }
} }
try { checkConsistent();
checkConsistent();
} catch (RuntimeException ex) {
ex.printStackTrace();
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
/* Update the in/out-Vectors now */ /* Update the in/out-Vectors now */
updateInOut(this, false); updateInOut(this, false);
@ -922,18 +906,7 @@ public class FlowBlock {
predecessors.removeElement(this); predecessors.removeElement(this);
/* T2 analysis succeeded */ /* T2 analysis succeeded */
try { checkConsistent();
checkConsistent();
} catch (RuntimeException ex) {
ex.printStackTrace();
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
return true; return true;
} }
@ -943,18 +916,7 @@ public class FlowBlock {
* Do a T1 transformation with the end_of_method block. * Do a T1 transformation with the end_of_method block.
*/ */
public void mergeEndBlock() { public void mergeEndBlock() {
try{ checkConsistent();
checkConsistent();
} catch (RuntimeException ex) {
ex.printStackTrace();
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
/* First find the innermost block that contains all jumps to the /* First find the innermost block that contains all jumps to the
* END_OF_METHOD block. * END_OF_METHOD block.
@ -1032,18 +994,7 @@ public class FlowBlock {
appendBlock.removeJump(); appendBlock.removeJump();
/* transformation succeeded */ /* transformation succeeded */
try { checkConsistent();
checkConsistent();
} catch (RuntimeException ex) {
ex.printStackTrace();
try {
jode.TabbedPrintWriter writer =
new jode.TabbedPrintWriter(System.err, " ");
writer.tab();
block.dumpSource(writer);
} catch (java.io.IOException ioex) {
}
}
} }
@ -1161,14 +1112,22 @@ public class FlowBlock {
*/ */
return changed; return changed;
} else { } else {
if (succ.block instanceof RawTryCatchBlock) {
int subStart = succ.addr;
int subEnd = (subStart > addr)? end : addr;
succ.analyze(subStart, subEnd);
}
/* Only do T1 transformation if the blocks are /* Only do T1 transformation if the blocks are
* adjacent. */ * adjacent. */
if ((succ.addr == addr+length if (succ.block instanceof SwitchBlock) {
/* analyze succ, the new region is the
* continous region of
* [start,end) \cap \compl [addr, addr+length)
* where succ.addr lies in.
*/
int newStart = (succ.addr > addr)
? addr+length : start;
int newEnd = (succ.addr > addr)
? end : addr;
if (succ.analyzeSwitch(newStart, newEnd))
break;
} if ((succ.addr == addr+length
|| succ.addr+succ.length == addr) || succ.addr+succ.length == addr)
&& doT1(succ)) { && doT1(succ)) {
/* T1 transformation succeeded. */ /* T1 transformation succeeded. */
@ -1206,7 +1165,82 @@ public class FlowBlock {
} }
} }
/**
* The switch analyzation. This calls doSwitchT1 and doT2 on apropriate
* regions. Only blocks whose address lies in the given address
* range are considered and it is taken care of, that the switch
* is never leaved. <p>
* The current flow block must contain the switch block as main
* block.
* @param start the start of the address range.
* @param end the end of the address range.
*/
public boolean analyzeSwitch(int start, int end) {
SwitchBlock switchBlock = (SwitchBlock) block;
boolean changed = false;
StructuredBlock lastBlock = null;
lastModified = block;
/* XXX - move to switchBlock??? */
for (int i=0; i < switchBlock.caseBlocks.length; i++) {
if (switchBlock.caseBlocks[i].subBlock != null
&& switchBlock.caseBlocks[i].subBlock.jump != null) {
FlowBlock next = switchBlock.caseBlocks[i].
subBlock.jump.destination;
if (next.addr >= end)
return changed;
else if (next.addr >= start) {
/* First analyze the next block. */
changed = next.analyze(next.addr, end) || changed;
/* Check if next has only the previous case
* and this case as predecessor. Otherwise
* break the analysis.
*/
if (next.predecessors.size() != 1
|| next.predecessors.elementAt(0) != this)
return changed;
boolean lastContains = false;
for (int j=0; j<successors.size(); j++) {
Jump jump = (Jump) successors.elementAt(j);
if (jump != null && jump.destination == next
&& jump !=
switchBlock.caseBlocks[i].subBlock.jump) {
if (lastBlock != null
&& lastBlock.contains(jump.prev))
lastContains = true;
else
return changed;
}
}
checkConsistent();
updateInOut(next, true);
switchBlock.caseBlocks[i].subBlock.removeJump();
next.block.replace(switchBlock.caseBlocks[i].subBlock,
null);
mergeSuccessors(next);
if (lastContains) {
lastBlock = optimizeJumps(next, lastBlock);
lastBlock = resolveRemaining(next, lastBlock);
}
/* Set addr+length to (semi-)correct value */
if (next.addr < addr)
addr = next.addr;
length += next.length;
lastBlock = next.block;
checkConsistent();
changed = true;
}
}
}
return changed;
}
/** /**
* Resolves the destinations of all jumps. * Resolves the destinations of all jumps.
*/ */

@ -128,6 +128,11 @@ implements BreakableBlock {
public void dumpInstruction(TabbedPrintWriter writer) public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException throws java.io.IOException
{ {
if (label != null) {
writer.untab();
writer.println(label+":");
writer.tab();
}
writer.println("switch ("+instr+") {"); writer.println("switch ("+instr+") {");
for (int i=0; i < caseBlocks.length; i++) for (int i=0; i < caseBlocks.length; i++)
caseBlocks[i].dumpSource(writer); caseBlocks[i].dumpSource(writer);

Loading…
Cancel
Save