optimizeJumps -> resolveSomeJumps renamed

mapStackToLocal / removePush added


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@314 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent a86862df6d
commit fb45ae50ab
  1. 134
      jode/jode/flow/FlowBlock.java

@ -128,6 +128,13 @@ public class FlowBlock {
*/ */
FlowBlock prevByAddr; FlowBlock prevByAddr;
/**
* The stack map. This tells how many objects are on stack at
* begin of the flow block, and to what locals they are maped.
* @see mapStackToLocal
*/
VariableStack stackMap;
/** /**
* 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.
@ -152,14 +159,22 @@ public class FlowBlock {
} }
/** /**
* This method optimizes the jumps to successor. * This method resolves some of the jumps to successor.
* @param jumps The list of jumps with that successor. * @param jumps The list of jumps with that successor.
* @return The remaining jumps, that couldn't be optimized. * @param succ The successing flow block.
* @return The remaining jumps, that couldn't be resolved.
*/ */
public Jump optimizeJumps(Jump jumps, FlowBlock succ) { public Jump resolveSomeJumps(Jump jumps, FlowBlock succ) {
/* We will put all jumps that we can not resolve into this
* linked list.
*/
Jump remainingJumps = null; Jump remainingJumps = null;
if (lastModified.jump == null) { if (lastModified.jump == null) {
/* This can happen if lastModified is a breakable block, and
* there is no break to it yet. We give lastModified this jump
* as successor since many other routines rely on this.
*/
Jump lastJump = new Jump(succ); Jump lastJump = new Jump(succ);
lastModified.setJump(lastJump); lastModified.setJump(lastJump);
remainingJumps = lastJump; remainingJumps = lastJump;
@ -185,7 +200,7 @@ public class FlowBlock {
Jump jump = jumps; Jump jump = jumps;
jumps = jumps.next; jumps = jumps.next;
/* if the jump is the jump of the lastModified, skip it. /* if the jump is the jump of lastModified, skip it.
*/ */
if (jump.prev == lastModified) { if (jump.prev == lastModified) {
jump.next = remainingJumps; jump.next = remainingJumps;
@ -366,12 +381,14 @@ public class FlowBlock {
sb = sb.outer; sb = sb.outer;
/* if this is a unconditional jump at the end of a /* if this is an unconditional jump at the end of a
* then block belonging to a if-then block without * then block belonging to a if-then block without
* else part, but a single jump, then replace the * else part, and the if block has a jump then replace
* if-then block with a if-then-else block with an * the if-then block with a if-then-else block with an
* empty block as else block that jumps and move the * else block that contains only the jump and move the
* unconditional jump to the if. * unconditional jump to the if. (The jump in the else
* block will later probably be replaced with a break,
* continue or return statement.)
*/ */
if (sb instanceof IfThenElseBlock) { if (sb instanceof IfThenElseBlock) {
IfThenElseBlock ifBlock = (IfThenElseBlock) sb; IfThenElseBlock ifBlock = (IfThenElseBlock) sb;
@ -440,9 +457,17 @@ public class FlowBlock {
surrounder.setJump(new Jump(succ)); surrounder.setJump(new Jump(succ));
surrounder.jump.next = jumps; surrounder.jump.next = jumps;
/* consider this jump again */
jumps = surrounder.jump; jumps = surrounder.jump;
break; continue next_jump;
} }
if (succ == END_OF_METHOD) {
/* If the jump can be replaced by a return
* we won't do labeled breaks, so we must
* stop here
*/
break;
}
} }
} }
jump.next = remainingJumps; jump.next = remainingJumps;
@ -764,16 +789,16 @@ public class FlowBlock {
/* Update the in/out-Vectors now */ /* Update the in/out-Vectors now */
updateInOut(succ, jumps); updateInOut(succ, jumps);
if (Decompiler.isFlowDebugging) if (Decompiler.isFlowDebugging)
Decompiler.err.println("before Optimize: "+this); Decompiler.err.println("before Resolve: "+this);
/* Try to eliminate as many jumps as possible. /* Try to eliminate as many jumps as possible.
*/ */
jumps = optimizeJumps(jumps, succ); jumps = resolveSomeJumps(jumps, succ);
if (Decompiler.isFlowDebugging) if (Decompiler.isFlowDebugging)
Decompiler.err.println("before Remaining: "+this); Decompiler.err.println("before Remaining: "+this);
resolveRemaining(jumps); resolveRemaining(jumps);
if (Decompiler.isFlowDebugging) if (Decompiler.isFlowDebugging)
Decompiler.err.println("after Optimize: "+this); Decompiler.err.println("after Resolve: "+this);
/* Now unify the blocks. /* Now unify the blocks.
*/ */
@ -931,7 +956,7 @@ public class FlowBlock {
/* Try to eliminate as many jumps as possible. /* Try to eliminate as many jumps as possible.
*/ */
jumps = optimizeJumps(jumps, this); jumps = resolveSomeJumps(jumps, this);
LoopBlock whileBlock = LoopBlock whileBlock =
new LoopBlock(LoopBlock.WHILE, LoopBlock.TRUE); new LoopBlock(LoopBlock.WHILE, LoopBlock.TRUE);
@ -1024,7 +1049,7 @@ public class FlowBlock {
/* Try to eliminate as many jumps as possible. /* Try to eliminate as many jumps as possible.
*/ */
jumps = optimizeJumps(jumps, END_OF_METHOD); jumps = resolveSomeJumps(jumps, END_OF_METHOD);
next_jump: next_jump:
for (; jumps != null; jumps = jumps.next) { for (; jumps != null; jumps = jumps.next) {
@ -1223,7 +1248,7 @@ public class FlowBlock {
* regions. Only blocks whose address lies in the given address * regions. Only blocks whose address lies in the given address
* range are considered and it is taken care of, that the switch * range are considered and it is taken care of, that the switch
* is never leaved. <p> * is never leaved. <p>
* The current flow block must contain the switch block as lastModified * The current flow block must contain the switch block as lastModified.
* @param start the start of the address range. * @param start the start of the address range.
* @param end the end of the address range. * @param end the end of the address range.
*/ */
@ -1242,7 +1267,7 @@ public class FlowBlock {
break; break;
else if (nextFlow.addr >= start) { else if (nextFlow.addr >= start) {
/* First analyze the nextFlow block. It may /* First analyze the nextFlow block. It may
* return early after a T2 trafo so call it * return early after a T2 trafo so call it
* until nothing more is possible. * until nothing more is possible.
*/ */
@ -1280,8 +1305,9 @@ public class FlowBlock {
updateInOut(nextFlow, jumps); updateInOut(nextFlow, jumps);
lastJumps = lastJumps =
lastFlow.optimizeJumps(lastJumps, nextFlow); lastFlow.resolveSomeJumps(lastJumps, nextFlow);
lastFlow.resolveRemaining(lastJumps); lastFlow.resolveRemaining(lastJumps);
switchBlock.caseBlocks[last].isFallThrough = true;
} else } else
updateInOut(nextFlow, jumps); updateInOut(nextFlow, jumps);
@ -1380,6 +1406,73 @@ public class FlowBlock {
successors.put(jump.destination, jump); successors.put(jump.destination, jump);
} }
/**
* This is called after the analysis is completely done. It
* will remove all PUSH/stack_i expressions, (if the bytecode
* is correct).
* @return false if the bytecode isn't correct and stack mapping
* didn't worked.
*/
public final boolean mapStackToLocal() {
try {
return mapStackToLocal(VariableStack.EMPTY);
} catch (RuntimeException ex) {
Decompiler.err.println("Can't resolve all PUSHes, "
+"this is probably illegal bytecode:");
ex.printStackTrace();
return false;
}
}
/**
* This is called after the analysis is completely done. It
* will remove all PUSH/stack_i expressions, (if the bytecode
* is correct).
* @param initialStack the stackmap at begin of the flow block
* @return false if the bytecode isn't correct and stack mapping
* didn't worked.
*/
public boolean mapStackToLocal(VariableStack initialStack) {
if (stackMap != null) {
stackMap.merge(initialStack);
} else
stackMap = initialStack;
if (block.mapStackToLocal(initialStack) == null) {
// bytecode is not correct! Give up!
stackMap = null;
return false;
}
Enumeration enum = successors.elements();
while (enum.hasMoreElements()) {
Jump jumps = (Jump) enum.nextElement();
VariableStack stack;
FlowBlock succ = jumps.destination;
stack = succ.stackMap;
for (/**/; jumps != null; jumps = jumps.next) {
stack = VariableStack.merge(stack, jumps.stackMap);
}
if (succ.stackMap == null)
if (!succ.mapStackToLocal(stack))
return false;
}
return true;
}
public void removePush() {
if (stackMap == null)
/* already done or mapping didn't succeed */
return;
stackMap = null;
block.removePush();
Enumeration enum = successors.keys();
while (enum.hasMoreElements()) {
FlowBlock succ = (FlowBlock)enum.nextElement();
succ.removePush();
}
}
public void makeDeclaration(VariableSet param) { public void makeDeclaration(VariableSet param) {
in.merge(param); in.merge(param);
in.subtract(param); in.subtract(param);
@ -1388,8 +1481,7 @@ public class FlowBlock {
} }
/** /**
* Mark this block and all successing blocks as reachable. * Mark this block and all successing blocks as reachable. */
*/
public void markReachable() { public void markReachable() {
if (reachable) { if (reachable) {
// This block was already checked. This prevents infinite // This block was already checked. This prevents infinite

Loading…
Cancel
Save