|
|
@ -578,18 +578,18 @@ public class FlowBlock { |
|
|
|
jump.prev.jump != jump) |
|
|
|
jump.prev.jump != jump) |
|
|
|
throw new RuntimeException("Inconsistency"); |
|
|
|
throw new RuntimeException("Inconsistency"); |
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock sb = jump.prev; |
|
|
|
StructuredBlock prev = jump.prev; |
|
|
|
while (sb != block) { |
|
|
|
while (prev != block) { |
|
|
|
if (sb.outer == null) |
|
|
|
if (prev.outer == null) |
|
|
|
throw new RuntimeException("Inconsistency"); |
|
|
|
throw new RuntimeException("Inconsistency"); |
|
|
|
StructuredBlock[] blocks = sb.outer.getSubBlocks(); |
|
|
|
StructuredBlock[] blocks = prev.outer.getSubBlocks(); |
|
|
|
int i; |
|
|
|
int i; |
|
|
|
for (i=0; i<blocks.length; i++) |
|
|
|
for (i=0; i<blocks.length; i++) |
|
|
|
if (blocks[i] == sb) |
|
|
|
if (blocks[i] == prev) |
|
|
|
break; |
|
|
|
break; |
|
|
|
if (i == blocks.length) |
|
|
|
if (i == blocks.length) |
|
|
|
throw new RuntimeException("Inconsistency"); |
|
|
|
throw new RuntimeException("Inconsistency"); |
|
|
|
sb = sb.outer; |
|
|
|
prev = prev.outer; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// } catch (RuntimeException ex) {
|
|
|
|
// } catch (RuntimeException ex) {
|
|
|
@ -719,13 +719,6 @@ public class FlowBlock { |
|
|
|
|
|
|
|
|
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
|
|
|
|
|
|
|
|
// TabbedPrintWriter writer = new jode.TabbedPrintWriter(System.err, " ");
|
|
|
|
|
|
|
|
// try {
|
|
|
|
|
|
|
|
// writer.println("XXXXXXXXXXXXXXXX");
|
|
|
|
|
|
|
|
// writer.tab();
|
|
|
|
|
|
|
|
// dumpSource(writer);
|
|
|
|
|
|
|
|
// } catch(java.io.IOException ex) {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
appendBlock = resolveRemaining(succ, appendBlock); |
|
|
|
appendBlock = resolveRemaining(succ, appendBlock); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -956,7 +949,7 @@ public class FlowBlock { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
Enumeration enum = successors.elements(); |
|
|
|
Enumeration enum = successors.elements(); |
|
|
|
StructuredBlock appendBlock = lastModified; |
|
|
|
StructuredBlock appendBlock = lastModified; |
|
|
|
while(enum.hasMoreElements()) { |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
if (jump == null || jump.destination != END_OF_METHOD) |
|
|
|
if (jump == null || jump.destination != END_OF_METHOD) |
|
|
|
continue; |
|
|
|
continue; |
|
|
@ -972,6 +965,17 @@ public class FlowBlock { |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
/* Try to eliminate as many jumps as possible. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
|
|
|
|
Jump jump = (Jump) enum.nextElement(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (jump == null || jump.destination != END_OF_METHOD || |
|
|
|
|
|
|
|
jump.prev == appendBlock) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (jump.prev instanceof ReturnBlock) |
|
|
|
|
|
|
|
jump.prev.removeJump(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
appendBlock = optimizeJumps(END_OF_METHOD, appendBlock); |
|
|
|
appendBlock = optimizeJumps(END_OF_METHOD, appendBlock); |
|
|
|
|
|
|
|
|
|
|
|
enum = successors.elements(); |
|
|
|
enum = successors.elements(); |
|
|
@ -982,7 +986,7 @@ public class FlowBlock { |
|
|
|
if (jump == null || jump.destination != END_OF_METHOD || |
|
|
|
if (jump == null || jump.destination != END_OF_METHOD || |
|
|
|
jump.prev == appendBlock) |
|
|
|
jump.prev == appendBlock) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
BreakableBlock breakToBlock = null; |
|
|
|
BreakableBlock breakToBlock = null; |
|
|
|
for (StructuredBlock surrounder = jump.prev.outer; |
|
|
|
for (StructuredBlock surrounder = jump.prev.outer; |
|
|
|
surrounder != null && surrounder != appendBlock.outer; |
|
|
|
surrounder != null && surrounder != appendBlock.outer; |
|
|
@ -999,12 +1003,13 @@ public class FlowBlock { |
|
|
|
StructuredBlock prevBlock = jump.prev; |
|
|
|
StructuredBlock prevBlock = jump.prev; |
|
|
|
prevBlock.removeJump(); |
|
|
|
prevBlock.removeJump(); |
|
|
|
|
|
|
|
|
|
|
|
if (breakToBlock == null) |
|
|
|
|
|
|
|
|
|
|
|
if (breakToBlock == null) { |
|
|
|
/* The successor is the dummy return instruction, so |
|
|
|
/* The successor is the dummy return instruction, so |
|
|
|
* replace the jump with a return. |
|
|
|
* replace the jump with a return. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
prevBlock.appendBlock(new ReturnBlock()); |
|
|
|
prevBlock.appendBlock(new ReturnBlock()); |
|
|
|
else |
|
|
|
} else |
|
|
|
prevBlock.appendBlock |
|
|
|
prevBlock.appendBlock |
|
|
|
(new BreakBlock(breakToBlock, false)); |
|
|
|
(new BreakBlock(breakToBlock, false)); |
|
|
|
} |
|
|
|
} |
|
|
@ -1031,6 +1036,7 @@ public class FlowBlock { |
|
|
|
new CreateIfThenElseOperator(), |
|
|
|
new CreateIfThenElseOperator(), |
|
|
|
new CreateConstantArray(), |
|
|
|
new CreateConstantArray(), |
|
|
|
new CreateForInitializer(), |
|
|
|
new CreateForInitializer(), |
|
|
|
|
|
|
|
new CompleteSynchronized(), |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1234,6 +1240,239 @@ public class FlowBlock { |
|
|
|
throw new AssertError(ioex.toString()); |
|
|
|
throw new AssertError(ioex.toString()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void checkAndRemoveJSR(FlowBlock subRoutine) { |
|
|
|
|
|
|
|
Enumeration enum = successors.elements(); |
|
|
|
|
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
|
|
|
|
Jump jump = (Jump)enum.nextElement(); |
|
|
|
|
|
|
|
if (jump == null || jump.destination == subRoutine) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock prev = jump.prev; |
|
|
|
|
|
|
|
if (prev instanceof JsrBlock) { |
|
|
|
|
|
|
|
/* The jump is directly preceeded by a jsr. |
|
|
|
|
|
|
|
* Everything okay. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (prev instanceof EmptyBlock |
|
|
|
|
|
|
|
&& prev.outer instanceof JsrBlock) { |
|
|
|
|
|
|
|
/* If jump is a jsr check the outer |
|
|
|
|
|
|
|
* block instead. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
prev = prev.outer; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if ((prev instanceof EmptyBlock |
|
|
|
|
|
|
|
|| prev instanceof ReturnBlock) |
|
|
|
|
|
|
|
&& prev.outer instanceof SequentialBlock) { |
|
|
|
|
|
|
|
SequentialBlock seq = (SequentialBlock) prev.outer; |
|
|
|
|
|
|
|
if (seq.subBlocks[1] == prev |
|
|
|
|
|
|
|
&& (seq.subBlocks[0] instanceof JsrBlock |
|
|
|
|
|
|
|
|| seq.subBlocks[0].jump != null)) { |
|
|
|
|
|
|
|
/* The jump is preceeded by another jump |
|
|
|
|
|
|
|
* or jsr and last in its block, okay. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (seq.subBlocks[0] == prev |
|
|
|
|
|
|
|
&& seq.outer instanceof SequentialBlock |
|
|
|
|
|
|
|
&& (seq.outer.getSubBlocks()[0] instanceof JsrBlock |
|
|
|
|
|
|
|
||seq.outer.getSubBlocks()[0].jump != null)) { |
|
|
|
|
|
|
|
/* The jump is preceeded by another jump |
|
|
|
|
|
|
|
* or jsr and not last in its block, okay. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/* Now we have a jump with a wrong destination. |
|
|
|
|
|
|
|
* Complain! |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
System.err.println("non well formed try-finally block"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
enum = successors.elements(); |
|
|
|
|
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
|
|
|
|
Jump jump = (Jump)enum.nextElement(); |
|
|
|
|
|
|
|
if (jump == null || jump.destination != subRoutine) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock prev = jump.prev; |
|
|
|
|
|
|
|
if (prev instanceof EmptyBlock |
|
|
|
|
|
|
|
&& prev.outer instanceof JsrBlock) { |
|
|
|
|
|
|
|
StructuredBlock sb = prev.outer.getNextBlock(); |
|
|
|
|
|
|
|
if (sb == null |
|
|
|
|
|
|
|
|| ((sb instanceof EmptyBlock |
|
|
|
|
|
|
|
|| sb instanceof ReturnBlock) |
|
|
|
|
|
|
|
&& sb.jump != null)) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock pred = null; |
|
|
|
|
|
|
|
StructuredBlock jsrBlock = prev.outer; |
|
|
|
|
|
|
|
if (jsrBlock.outer instanceof SequentialBlock) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (jsrBlock.outer.getSubBlocks()[1] |
|
|
|
|
|
|
|
== jsrBlock) { |
|
|
|
|
|
|
|
pred = |
|
|
|
|
|
|
|
jsrBlock.outer.getSubBlocks()[0]; |
|
|
|
|
|
|
|
pred.replace(jsrBlock.outer, |
|
|
|
|
|
|
|
jsrBlock.outer); |
|
|
|
|
|
|
|
} else if (jsrBlock.outer.outer instanceof |
|
|
|
|
|
|
|
SequentialBlock) { |
|
|
|
|
|
|
|
pred = |
|
|
|
|
|
|
|
jsrBlock.outer.outer |
|
|
|
|
|
|
|
.getSubBlocks()[0]; |
|
|
|
|
|
|
|
jsrBlock.outer.getSubBlocks()[1] |
|
|
|
|
|
|
|
.replace(jsrBlock.outer, |
|
|
|
|
|
|
|
jsrBlock.outer); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (pred != null) { |
|
|
|
|
|
|
|
if (pred.jump == null) |
|
|
|
|
|
|
|
pred.moveJump(jsrBlock.jump); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
jsrBlock.removeJump(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
EmptyBlock eb = new EmptyBlock(); |
|
|
|
|
|
|
|
eb.moveJump(jsrBlock.jump); |
|
|
|
|
|
|
|
eb.replace(jsrBlock, prev); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
prev.removeJump(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void checkAndRemoveMonitorExit(LocalInfo local, int end) { |
|
|
|
|
|
|
|
FlowBlock subRoutine = null; |
|
|
|
|
|
|
|
Enumeration enum = successors.elements(); |
|
|
|
|
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
|
|
|
|
Jump jump = (Jump)enum.nextElement(); |
|
|
|
|
|
|
|
if (jump == null || jump.destination == subRoutine) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
StructuredBlock prev = jump.prev; |
|
|
|
|
|
|
|
if (prev instanceof EmptyBlock |
|
|
|
|
|
|
|
&& prev.outer instanceof JsrBlock |
|
|
|
|
|
|
|
&& subRoutine == null) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
subRoutine = jump.destination; |
|
|
|
|
|
|
|
subRoutine.analyzeSubRoutine(addr+length, end); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (subRoutine.block instanceof InstructionBlock) { |
|
|
|
|
|
|
|
Instruction instr = |
|
|
|
|
|
|
|
((InstructionBlock)subRoutine.block).getInstruction(); |
|
|
|
|
|
|
|
if (instr instanceof ComplexExpression |
|
|
|
|
|
|
|
&& ((ComplexExpression)instr) |
|
|
|
|
|
|
|
.getOperator() instanceof MonitorExitOperator |
|
|
|
|
|
|
|
&& ((ComplexExpression)instr) |
|
|
|
|
|
|
|
.getSubExpressions()[0] instanceof LocalLoadOperator |
|
|
|
|
|
|
|
&& (((LocalLoadOperator) ((ComplexExpression)instr) |
|
|
|
|
|
|
|
.getSubExpressions()[0]).getLocalInfo().getSlot() |
|
|
|
|
|
|
|
== local.getSlot())) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
updateInOut(subRoutine, true); |
|
|
|
|
|
|
|
length += subRoutine.length; |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (prev instanceof JsrBlock) { |
|
|
|
|
|
|
|
/* The jump is directly preceeded by a jsr. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (prev instanceof EmptyBlock |
|
|
|
|
|
|
|
&& prev.outer instanceof JsrBlock) { |
|
|
|
|
|
|
|
/* If jump is a jsr check the outer |
|
|
|
|
|
|
|
* block instead. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
prev = prev.outer; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((prev instanceof EmptyBlock |
|
|
|
|
|
|
|
|| prev instanceof ReturnBlock) |
|
|
|
|
|
|
|
&& prev.outer instanceof SequentialBlock) { |
|
|
|
|
|
|
|
SequentialBlock seq = (SequentialBlock) prev.outer; |
|
|
|
|
|
|
|
StructuredBlock pred = null; |
|
|
|
|
|
|
|
if (seq.subBlocks[1] == prev) |
|
|
|
|
|
|
|
pred = seq.subBlocks[0]; |
|
|
|
|
|
|
|
else if (seq.outer instanceof SequentialBlock) |
|
|
|
|
|
|
|
pred = seq.outer.getSubBlocks()[0]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pred != null) { |
|
|
|
|
|
|
|
if (pred instanceof JsrBlock || pred.jump != null) |
|
|
|
|
|
|
|
/* The jump is preceeded by another jump |
|
|
|
|
|
|
|
* or jsr and last in its block, okay. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pred instanceof InstructionBlock) { |
|
|
|
|
|
|
|
Instruction instr = |
|
|
|
|
|
|
|
((InstructionBlock)pred).getInstruction(); |
|
|
|
|
|
|
|
if (instr instanceof ComplexExpression |
|
|
|
|
|
|
|
&& ((ComplexExpression)instr) |
|
|
|
|
|
|
|
.getOperator() instanceof MonitorExitOperator |
|
|
|
|
|
|
|
&& ((ComplexExpression)instr) |
|
|
|
|
|
|
|
.getSubExpressions()[0] |
|
|
|
|
|
|
|
instanceof LocalLoadOperator |
|
|
|
|
|
|
|
&& (((LocalLoadOperator) |
|
|
|
|
|
|
|
((ComplexExpression)instr) |
|
|
|
|
|
|
|
.getSubExpressions()[0]).getLocalInfo() |
|
|
|
|
|
|
|
.getSlot() |
|
|
|
|
|
|
|
== local.getSlot())) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Now we have a jump with a wrong destination. |
|
|
|
|
|
|
|
* Complain! |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
System.err.println("non well formed synchronized block"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
enum = successors.elements(); |
|
|
|
|
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
|
|
|
|
Jump jump = (Jump)enum.nextElement(); |
|
|
|
|
|
|
|
if (jump == null || |
|
|
|
|
|
|
|
jump.destination != subRoutine) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock prev = jump.prev; |
|
|
|
|
|
|
|
if (prev instanceof EmptyBlock |
|
|
|
|
|
|
|
&& prev.outer instanceof JsrBlock) { |
|
|
|
|
|
|
|
StructuredBlock sb = prev.outer.getNextBlock(); |
|
|
|
|
|
|
|
if (sb == null |
|
|
|
|
|
|
|
|| ((sb instanceof EmptyBlock |
|
|
|
|
|
|
|
|| sb instanceof ReturnBlock) |
|
|
|
|
|
|
|
&& sb.jump != null)) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
StructuredBlock pred = null; |
|
|
|
|
|
|
|
StructuredBlock jsrBlock = prev.outer; |
|
|
|
|
|
|
|
if (jsrBlock.outer instanceof SequentialBlock) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (jsrBlock.outer.getSubBlocks()[1] == jsrBlock) { |
|
|
|
|
|
|
|
pred = jsrBlock.outer.getSubBlocks()[0]; |
|
|
|
|
|
|
|
pred.replace(jsrBlock.outer, jsrBlock.outer); |
|
|
|
|
|
|
|
} else if (jsrBlock.outer.outer instanceof |
|
|
|
|
|
|
|
SequentialBlock) { |
|
|
|
|
|
|
|
pred = jsrBlock.outer.outer.getSubBlocks()[0]; |
|
|
|
|
|
|
|
jsrBlock.outer.getSubBlocks()[1] |
|
|
|
|
|
|
|
.replace(jsrBlock.outer, jsrBlock.outer); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (pred != null) { |
|
|
|
|
|
|
|
if (pred.jump == null) |
|
|
|
|
|
|
|
pred.moveJump(jsrBlock.jump); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
jsrBlock.removeJump(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
EmptyBlock eb = new EmptyBlock(); |
|
|
|
|
|
|
|
eb.moveJump(jsrBlock.jump); |
|
|
|
|
|
|
|
eb.replace(jsrBlock, prev); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
prev.removeJump(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Create a Catch- resp. FinallyBlock (maybe even SynchronizedBlock). |
|
|
|
* Create a Catch- resp. FinallyBlock (maybe even SynchronizedBlock). |
|
|
@ -1271,112 +1510,104 @@ public class FlowBlock { |
|
|
|
newBlock.setCatchBlock(rawBlock.catchBlock); |
|
|
|
newBlock.setCatchBlock(rawBlock.catchBlock); |
|
|
|
lastModified = newBlock; |
|
|
|
lastModified = newBlock; |
|
|
|
changed = true; |
|
|
|
changed = true; |
|
|
|
} else if (catchFlow.block instanceof SequentialBlock) { |
|
|
|
} else if (catchFlow.block instanceof SequentialBlock |
|
|
|
SequentialBlock catchBlock = null; |
|
|
|
&& catchFlow.block.getSubBlocks()[0] |
|
|
|
|
|
|
|
instanceof InstructionBlock) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SequentialBlock catchBlock = (SequentialBlock) catchFlow.block; |
|
|
|
int type = 0; |
|
|
|
int type = 0; |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
Instruction instr = |
|
|
|
catchBlock = (SequentialBlock) catchFlow.block; |
|
|
|
((InstructionBlock)catchBlock.subBlocks[0]).instr; |
|
|
|
if (((Expression)((InstructionBlock)catchBlock.subBlocks[0]) |
|
|
|
|
|
|
|
.instr).getOperator() instanceof jode.MonitorExitOperator |
|
|
|
if (instr instanceof ComplexExpression |
|
|
|
&& ((ThrowBlock)catchBlock.subBlocks[1]).instr |
|
|
|
&& ((ComplexExpression)instr).getOperator() |
|
|
|
instanceof jode.NopOperator) |
|
|
|
instanceof MonitorExitOperator |
|
|
|
|
|
|
|
&& ((ComplexExpression)instr).getSubExpressions()[0] |
|
|
|
/* This is a synchronized block */ |
|
|
|
instanceof LocalLoadOperator |
|
|
|
type = 2; |
|
|
|
&& catchBlock.subBlocks[1] instanceof ThrowBlock |
|
|
|
|
|
|
|
&& ((ThrowBlock)catchBlock.subBlocks[1]).instr |
|
|
|
|
|
|
|
instanceof jode.NopOperator) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This is a synchronized block */ |
|
|
|
|
|
|
|
((ThrowBlock)catchBlock.subBlocks[1]).removeJump(); |
|
|
|
|
|
|
|
ComplexExpression monexit = (ComplexExpression) |
|
|
|
|
|
|
|
((InstructionBlock) catchBlock.subBlocks[0]).instr; |
|
|
|
|
|
|
|
LocalInfo local = |
|
|
|
|
|
|
|
((LocalLoadOperator)monexit.getSubExpressions()[0]) |
|
|
|
|
|
|
|
.getLocalInfo(); |
|
|
|
|
|
|
|
checkAndRemoveMonitorExit(local, end); |
|
|
|
|
|
|
|
SynchronizedBlock syncBlock = new SynchronizedBlock(local); |
|
|
|
|
|
|
|
syncBlock.replace(rawBlock, rawBlock); |
|
|
|
|
|
|
|
syncBlock.moveJump(rawBlock.jump); |
|
|
|
|
|
|
|
syncBlock.setBodyBlock(rawBlock.tryBlock); |
|
|
|
|
|
|
|
lastModified = syncBlock; |
|
|
|
|
|
|
|
changed = true; |
|
|
|
|
|
|
|
|
|
|
|
else if |
|
|
|
} else if (catchBlock.subBlocks[1] instanceof SequentialBlock |
|
|
|
(((SequentialBlock)catchBlock.subBlocks[1]).subBlocks[0] |
|
|
|
&& catchBlock.subBlocks[1].getSubBlocks()[0] |
|
|
|
instanceof JsrBlock |
|
|
|
instanceof JsrBlock |
|
|
|
&& ((LocalStoreOperator) |
|
|
|
&& instr instanceof LocalStoreOperator |
|
|
|
((Expression) |
|
|
|
&& catchBlock.subBlocks[1].getSubBlocks()[1] |
|
|
|
((InstructionBlock)catchBlock.subBlocks[0]) |
|
|
|
instanceof ThrowBlock |
|
|
|
.instr).getOperator()) |
|
|
|
&& ((ThrowBlock)catchBlock.subBlocks[1] |
|
|
|
|
|
|
|
.getSubBlocks()[1]).instr |
|
|
|
|
|
|
|
instanceof LocalLoadOperator |
|
|
|
|
|
|
|
&& ((LocalStoreOperator) instr) |
|
|
|
.matches((LocalLoadOperator) |
|
|
|
.matches((LocalLoadOperator) |
|
|
|
((Expression) |
|
|
|
((ThrowBlock)catchBlock.subBlocks[1] |
|
|
|
((ThrowBlock) |
|
|
|
.getSubBlocks()[1]).instr)) { |
|
|
|
((SequentialBlock)catchBlock.subBlocks[1]). |
|
|
|
/* Wow that was complicated :-) |
|
|
|
subBlocks[1]) |
|
|
|
* But now we know that the catch block looks |
|
|
|
.instr).getOperator())) |
|
|
|
* exactly like an try finally block. |
|
|
|
/* Wow that was complicated :-) |
|
|
|
*/ |
|
|
|
* But now we know that the catch block looks |
|
|
|
|
|
|
|
* exactly like we exspected. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
type = 1; |
|
|
|
|
|
|
|
} catch (ClassCastException ex) { |
|
|
|
|
|
|
|
/* don't do transformations */ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (type == 2) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This is a synchronized block */ |
|
|
|
|
|
|
|
throw new AssertError ("Synchronized not implemented yet"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else if (type == 1) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Finally block */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FlowBlock subRoutine = |
|
|
|
FlowBlock subRoutine = |
|
|
|
((JsrBlock)catchBlock.subBlocks[1].getSubBlocks()[0]) |
|
|
|
((JsrBlock)catchBlock.subBlocks[1].getSubBlocks()[0]) |
|
|
|
.innerBlock.jump.destination; |
|
|
|
.innerBlock.jump.destination; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Now remove the two jumps of the catch block |
|
|
|
|
|
|
|
* so that we can forget about them. |
|
|
|
|
|
|
|
* This are the throw and the jsr. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
catchBlock.subBlocks[1].getSubBlocks()[1].removeJump(); |
|
|
|
|
|
|
|
catchBlock.subBlocks[1] |
|
|
|
|
|
|
|
.getSubBlocks()[0].getSubBlocks()[0].removeJump(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
subRoutine.analyzeSubRoutine(addr+length, end); |
|
|
|
subRoutine.analyzeSubRoutine(addr+length, end); |
|
|
|
updateInOut(subRoutine, true); |
|
|
|
updateInOut(subRoutine, true); |
|
|
|
|
|
|
|
|
|
|
|
length += subRoutine.length; |
|
|
|
length += subRoutine.length; |
|
|
|
Enumeration enum = successors.elements(); |
|
|
|
checkAndRemoveJSR(subRoutine); |
|
|
|
while (enum.hasMoreElements()) { |
|
|
|
|
|
|
|
Jump jump = (Jump)enum.nextElement(); |
|
|
|
|
|
|
|
if (jump != null && jump.destination == subRoutine) { |
|
|
|
|
|
|
|
if (jump.prev instanceof EmptyBlock |
|
|
|
|
|
|
|
&& jump.prev.outer instanceof JsrBlock) { |
|
|
|
|
|
|
|
/* XXX |
|
|
|
|
|
|
|
* Could check much more here! |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
StructuredBlock prevBlock = null; |
|
|
|
|
|
|
|
StructuredBlock jsrBlock = jump.prev.outer; |
|
|
|
|
|
|
|
if (jsrBlock.outer instanceof SequentialBlock) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (jsrBlock.outer.getSubBlocks()[1] |
|
|
|
|
|
|
|
== jsrBlock) { |
|
|
|
|
|
|
|
prevBlock = |
|
|
|
|
|
|
|
jsrBlock.outer.getSubBlocks()[0]; |
|
|
|
|
|
|
|
prevBlock.replace(jsrBlock.outer, |
|
|
|
|
|
|
|
jsrBlock.outer); |
|
|
|
|
|
|
|
} else if (jsrBlock.outer.outer instanceof |
|
|
|
|
|
|
|
SequentialBlock) { |
|
|
|
|
|
|
|
prevBlock = |
|
|
|
|
|
|
|
jsrBlock.outer.outer |
|
|
|
|
|
|
|
.getSubBlocks()[0]; |
|
|
|
|
|
|
|
jsrBlock.outer.getSubBlocks()[1] |
|
|
|
|
|
|
|
.replace(jsrBlock.outer, |
|
|
|
|
|
|
|
jsrBlock.outer); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (prevBlock != null) { |
|
|
|
|
|
|
|
if (prevBlock.jump == null) |
|
|
|
|
|
|
|
prevBlock.moveJump(jsrBlock.jump); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
jsrBlock.removeJump(); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
EmptyBlock eb = new EmptyBlock(); |
|
|
|
|
|
|
|
eb.moveJump(jsrBlock.jump); |
|
|
|
|
|
|
|
eb.replace(jsrBlock, jump.prev); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
jump.prev.removeJump(); |
|
|
|
|
|
|
|
} else |
|
|
|
|
|
|
|
throw new AssertError("wrong jsr"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CatchFinallyBlock newBlock = new CatchFinallyBlock(); |
|
|
|
CatchFinallyBlock newBlock = new CatchFinallyBlock(); |
|
|
|
newBlock.replace(rawBlock, rawBlock); |
|
|
|
newBlock.replace(rawBlock, rawBlock); |
|
|
|
newBlock.setTryBlock(rawBlock.tryBlock); |
|
|
|
newBlock.setTryBlock(rawBlock.tryBlock); |
|
|
|
newBlock.setFinallyBlock(subRoutine.block); |
|
|
|
newBlock.setFinallyBlock(subRoutine.block); |
|
|
|
|
|
|
|
newBlock.moveJump(rawBlock.jump); |
|
|
|
lastModified = newBlock; |
|
|
|
lastModified = newBlock; |
|
|
|
changed = true; |
|
|
|
changed = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} else if (catchFlow.block instanceof InstructionBlock |
|
|
|
|
|
|
|
&& ((InstructionBlock) catchFlow.block).instr |
|
|
|
|
|
|
|
instanceof PopOperator |
|
|
|
|
|
|
|
&& catchFlow.block.jump != null) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* This is a special try/finally-block, where |
|
|
|
|
|
|
|
* the finally block ends with a break, return or |
|
|
|
|
|
|
|
* similar. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CatchFinallyBlock newBlock = new CatchFinallyBlock(); |
|
|
|
|
|
|
|
newBlock.replace(rawBlock, rawBlock); |
|
|
|
|
|
|
|
newBlock.setTryBlock(rawBlock.tryBlock); |
|
|
|
|
|
|
|
newBlock.setFinallyBlock(new EmptyBlock()); |
|
|
|
|
|
|
|
newBlock.moveJump(rawBlock.jump); |
|
|
|
|
|
|
|
lastModified = newBlock.finallyBlock; |
|
|
|
|
|
|
|
lastModified.moveJump(catchFlow.block.jump); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Enumeration enum = successors.elements(); |
|
|
|
|
|
|
|
changed = true; |
|
|
|
} |
|
|
|
} |
|
|
|
checkConsistent(); |
|
|
|
checkConsistent(); |
|
|
|
if (Decompiler.debugAnalyze) |
|
|
|
if (Decompiler.debugAnalyze) |
|
|
|