New way to handle catch blocks, still needs finetuning

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1414 379699f6-c40d-0410-875b-85095c16579e
master
hoenicke 13 years ago
parent 744346bbcb
commit accfa1271e
  1. 20
      jode/src/net/sf/jode/decompiler/MethodAnalyzer.java
  2. 104
      jode/src/net/sf/jode/flow/FlowBlock.java
  3. 8
      jode/test/TryCatch.java

@ -458,10 +458,7 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
for (int i=0; i < blocks.length; i++)
flows[i] = new FlowBlock(this, i, i > 0 ? flows[i-1]: null);
/* While we read the opcodes into FlowBlocks
* we try to combine sequential blocks, as soon as we
* find two sequential instructions in a row, where the
* second has no predecessors.
/* We transform every basic block into a FlowBlock
*/
int count = 0;
for (int i=0; i < blocks.length; i++) {
@ -510,22 +507,23 @@ public class MethodAnalyzer implements Scope, ClassDeclarer {
excHandlers = new TransformExceptionHandlers(flows);
for (int i=0; i<handlers.length; i++) {
Type type = null;
FlowBlock start = flows[handlers[i].getStart().getBlockNr()];
FlowBlock end = flows[handlers[i].getEnd().getBlockNr()];
FlowBlock handler
= flows[handlers[i].getCatcher().getBlockNr()];
int start = handlers[i].getStart().getBlockNr();
int end = handlers[i].getEnd().getBlockNr();
FlowBlock handler = flows[handlers[i].getCatcher().getBlockNr()];
if (handlers[i].getType() != null)
type = Type.tClass(classAnalyzer.getClassPath(),
handlers[i].getType());
excHandlers.addHandler(start, end, handler, type);
for (int j = start; j <= end; j++) {
if (flows[j] != handler)
flows[j].addExceptionHandler(type, handler);
}
}
}
if (GlobalOptions.verboseLevel > 0)
GlobalOptions.err.print('-');
excHandlers.analyze();
//excHandlers.analyze();
methodHeader.analyze();
methodHeader.removeStartPred();

@ -24,6 +24,7 @@ import net.sf.jode.decompiler.MethodAnalyzer;
import net.sf.jode.decompiler.LocalInfo;
import net.sf.jode.expr.Expression;
import net.sf.jode.expr.CombineableOperator;
import net.sf.jode.type.Type;
import net.sf.jode.util.SimpleMap;
///#def COLLECTIONS java.util
@ -167,12 +168,18 @@ public class FlowBlock {
* The gen locals. This are the locals, which can be
* overwritten in this block on a path to the successor. That
* means, that there exists a path form the start of the
* current flow block to the successor that contains a
* current flow block to the successor that contains an
* assignments to this local, and that is not overwritten
* afterwards.
*/
VariableSet gen;
/**
* If this is non-null it contains an array list of all exception types
* for which the successor is the catch block.
*/
ArrayList catched;
/**
* The linked list of jumps.
*/
@ -216,7 +223,18 @@ public class FlowBlock {
/* We will put all jumps that we can not resolve into this
* linked list.
*/
if (jumps == null)
return null;
Jump remainingJumps = null;
lastModified = jumps.prev;
StructuredBlock b = lastModified.outer;
while (b != null) {
if (b.outer instanceof TryBlock
&& ((TryBlock)b.outer).getSubBlocks()[0] == b) {
lastModified = b.outer;
}
b = b.outer;
}
if (lastModified.jump == null) {
/* This can happen if lastModified is a breakable block, and
@ -420,8 +438,8 @@ public class FlowBlock {
/* remove this jump if it jumps to the
* getNextFlowBlock(). */
if (jump.destination
== jump.prev.outer.getNextFlowBlock(jump.prev)) {
if (jump.prev.outer != null &&
jump.destination == jump.prev.outer.getNextFlowBlock(jump.prev)) {
jump.prev.removeJump();
continue;
}
@ -655,10 +673,14 @@ public class FlowBlock {
} else {
myInfo.gen.addAll(hisInfo.gen);
myInfo.kill.retainAll(hisInfo.kill);
Jump myJumps = myInfo.jumps;
while (myJumps.next != null)
myJumps = myJumps.next;
myJumps.next = hisInfo.jumps;
if (myInfo.jumps == null)
myInfo.jumps = hisInfo.jumps;
else {
Jump myJumps = myInfo.jumps;
while (myJumps.next != null)
myJumps = myJumps.next;
myJumps.next = hisInfo.jumps;
}
}
}
}
@ -979,7 +1001,6 @@ public class FlowBlock {
}
if (jumps.length > 0)
lastModified.setSuccessors(jumps);
gen = null;
kill = null;
checkConsistent();
}
@ -1000,6 +1021,10 @@ public class FlowBlock {
checkConsistent();
succ.checkConsistent();
/* Merge catching successors */
unifyCatchSuccessors(succ);
succ.unifyCatchSuccessors(this);
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_ANALYZE) != 0)
GlobalOptions.err.println
@ -1106,7 +1131,8 @@ public class FlowBlock {
/* Now remove the jump of the lastModified if it points to
* END_OF_METHOD.
*/
if (lastModified.jump.destination == END_OF_METHOD)
if (lastModified.jump != null
&& lastModified.jump.destination == END_OF_METHOD)
lastModified.removeJump();
if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_FLOW) != 0)
@ -1306,7 +1332,7 @@ public class FlowBlock {
}
/**
* Search for an apropriate successor.
* Search for an appropriate successor.
* @param prevSucc The successor, that was previously tried.
* @param start The minimum blockNr
* @param end The maximum blockNr + 1.
@ -1877,4 +1903,62 @@ public class FlowBlock {
return super.toString();
}
}
public void addExceptionHandler(Type excType, FlowBlock handler) {
SuccessorInfo info = (SuccessorInfo) successors.get(handler);
if (info == null) {
info = new SuccessorInfo();
info.gen = (VariableSet) gen.clone();
successors.put(handler, info);
handler.predecessors.add(this);
}
info.kill = new SlotSet();
if (info.catched == null)
info.catched = new ArrayList();
info.catched.add(excType);
}
private void unifyCatchSuccessors(FlowBlock succ) {
Iterator iter = successors.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
FlowBlock dest = (FlowBlock) entry.getKey();
SuccessorInfo myInfo = (SuccessorInfo) entry.getValue();
if (myInfo.catched == null)
continue;
SuccessorInfo succInfo = (SuccessorInfo) succ.successors.get(dest);
Iterator catchedIter = myInfo.catched.iterator();
while (catchedIter.hasNext()) {
Type excType = (Type) catchedIter.next();
if (succInfo != null && succInfo.catched != null
&& succInfo.catched.contains(excType))
continue;
if (!(block instanceof TryBlock))
new TryBlock(this);
TryBlock tryBlock = (TryBlock) block;
if (excType != null) {
CatchBlock catchBlock = new CatchBlock(excType);
tryBlock.addCatchBlock(catchBlock);
Jump jump = new Jump(dest);
jump.next = myInfo.jumps;
myInfo.jumps = jump;
lastModified = new EmptyBlock(jump);
catchBlock.setCatchBlock(lastModified);
catchedIter.remove();
} else {
FinallyBlock catchBlock = new FinallyBlock();
tryBlock.addCatchBlock(catchBlock);
Jump jump = new Jump(dest);
jump.next = myInfo.jumps;
myInfo.jumps = jump;
lastModified = new EmptyBlock(jump);
catchBlock.setCatchBlock(lastModified);
catchedIter.remove();
}
}
if (myInfo.catched.isEmpty())
myInfo.catched = null;
}
}
}

@ -23,7 +23,13 @@
* is try, catch, finally and synchronized.
*/
class TryCatch {
void verysimple() {
try {
foo();
} catch (RuntimeException ex) {
ex.printStackTrace();
}
}
int simple() {
TryCatch i = null;
try {

Loading…
Cancel
Save