fixed a bug, when MONITOREXIT is outside of the try block for synchronized

git-svn-id: https://svn.code.sf.net/p/jode/code/branches/stable@1059 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent d49e59a3ef
commit b863984781
  1. 114
      jode/jode/flow/TransformExceptionHandlers.java

@ -370,13 +370,16 @@ public class TransformExceptionHandlers {
} }
public void checkAndRemoveMonitorExit(FlowBlock tryFlow, LocalInfo local, public void checkAndRemoveMonitorExit(FlowBlock tryFlow, LocalInfo local,
int startOutExit, int endOutExit,
int startMonExit, int endMonExit) { int startMonExit, int endMonExit) {
FlowBlock subRoutine = null; FlowBlock subRoutine = null;
FlowBlock exitBlock = null;
Iterator succs = tryFlow.successors.values().iterator(); Iterator succs = tryFlow.successors.values().iterator();
dest_loop: dest_loop:
while (succs.hasNext()) { while (succs.hasNext()) {
boolean isFirstJump = true;
for (Jump jumps = (Jump) succs.next(); for (Jump jumps = (Jump) succs.next();
jumps != null; jumps = jumps.next) { jumps != null; jumps = jumps.next, isFirstJump = false) {
StructuredBlock prev = jumps.prev; StructuredBlock prev = jumps.prev;
@ -437,28 +440,59 @@ public class TransformExceptionHandlers {
continue; continue;
} }
/* The block is a jsr that is not preceeded by another jsr. if (isFirstJump) {
* This must be the monitorexit subroutine. /* This is the first jump to that destination.
*/ * Check if the destination does the monitorExit
if (prev instanceof JsrBlock && subRoutine == null) { */
subRoutine = jumps.destination;
subRoutine.analyze(startMonExit, endMonExit);
transformSubRoutine(subRoutine.block);
if (subRoutine.block instanceof InstructionBlock) {
Expression instr =
((InstructionBlock)subRoutine.block)
.getInstruction();
if (isMonitorExit(instr, local)) {
tryFlow.mergeAddr(subRoutine);
continue dest_loop;
}
}
}
/* Now we have a jump that is not preceded by a monitorexit. /* The block is a jsr that is not preceeded by
* Complain! * another jsr. This must be the monitorexit
* subroutine.
*/
if (prev instanceof JsrBlock && subRoutine == null) {
subRoutine = jumps.destination;
subRoutine.analyze(startMonExit, endMonExit);
transformSubRoutine(subRoutine.block);
if (subRoutine.block instanceof InstructionBlock) {
Expression instr =
((InstructionBlock)subRoutine.block)
.getInstruction();
if (isMonitorExit(instr, local)) {
tryFlow.mergeAddr(subRoutine);
continue dest_loop;
}
}
}
/* Now we have a jump that is not preceded by a
* monitorexit. There's a last chance: the jump
* jumps directly to the correct monitorexit
* instruction, which lies outside the try/catch
* block.
*/
if (exitBlock == null
&& jumps.destination.getAddr() >= startOutExit
&& jumps.destination.getNextAddr() <= endOutExit) {
jumps.destination.analyze(startOutExit, endOutExit);
StructuredBlock sb = jumps.destination.block;
if (sb instanceof SequentialBlock)
sb = sb.getSubBlocks()[0];
if (sb instanceof InstructionBlock) {
Expression instr = ((InstructionBlock)sb)
.getInstruction();
if (isMonitorExit(instr, local)) {
sb.removeBlock();
exitBlock = jumps.destination;
continue dest_loop;
}
}
}
}
/* Complain!
*/ */
DescriptionBlock msg DescriptionBlock msg
= new DescriptionBlock("ERROR: NO MONITOREXIT"); = new DescriptionBlock("ERROR: NO MONITOREXIT");
@ -523,11 +557,13 @@ public class TransformExceptionHandlers {
LocalInfo local = LocalInfo local =
((LocalLoadOperator)monexit.getSubExpressions()[0]) ((LocalLoadOperator)monexit.getSubExpressions()[0])
.getLocalInfo(); .getLocalInfo();
tryFlow.mergeAddr(catchFlow);
checkAndRemoveMonitorExit checkAndRemoveMonitorExit
(tryFlow, local, catchFlow.getNextAddr(), endHandler); (tryFlow, local,
tryFlow.getNextAddr(), catchFlow.getAddr(),
catchFlow.getNextAddr(), endHandler);
tryFlow.mergeAddr(catchFlow);
SynchronizedBlock syncBlock = new SynchronizedBlock(local); SynchronizedBlock syncBlock = new SynchronizedBlock(local);
TryBlock tryBlock = (TryBlock) tryFlow.block; TryBlock tryBlock = (TryBlock) tryFlow.block;
syncBlock.replace(tryBlock); syncBlock.replace(tryBlock);
@ -683,12 +719,13 @@ public class TransformExceptionHandlers {
TryBlock tryBlock = (TryBlock)tryFlow.block; TryBlock tryBlock = (TryBlock)tryFlow.block;
if (tryBlock.getSubBlocks()[0] instanceof TryBlock) { if (tryBlock.getSubBlocks()[0] instanceof TryBlock) {
/* remove the nested tryBlock */ /* remove the surrounding tryBlock */
TryBlock innerTry = (TryBlock)tryBlock.getSubBlocks()[0]; TryBlock innerTry = (TryBlock)tryBlock.getSubBlocks()[0];
innerTry.gen = tryBlock.gen; innerTry.gen = tryBlock.gen;
innerTry.replace(tryBlock); innerTry.replace(tryBlock);
tryBlock = innerTry; tryBlock = innerTry;
tryFlow.lastModified = innerTry; tryFlow.lastModified = tryBlock;
tryFlow.block = tryBlock;
} }
FinallyBlock newBlock = new FinallyBlock(); FinallyBlock newBlock = new FinallyBlock();
newBlock.setCatchBlock(finallyBlock); newBlock.setCatchBlock(finallyBlock);
@ -832,22 +869,23 @@ public class TransformExceptionHandlers {
FlowBlock tryFlow = exc.start; FlowBlock tryFlow = exc.start;
tryFlow.checkConsistent(); tryFlow.checkConsistent();
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_ANALYZE) != 0)
GlobalOptions.err.println
("analyzeTry("
+ exc.start.addr + ", " + exc.endAddr+")");
while (tryFlow.analyze(tryFlow.addr, exc.endAddr));
if (last == null if (last == null || exc.type == null
|| last.start.addr != exc.start.addr || last.start.addr != exc.start.addr
|| last.endAddr != exc.endAddr) { || last.endAddr != exc.endAddr) {
/* The last handler does catch another range. /* The last handler does catch another range.
* Create a new try block. * Create a new try block.
*/ */
if ((GlobalOptions.debuggingFlags
& GlobalOptions.DEBUG_ANALYZE) != 0)
GlobalOptions.err.println
("analyzeTry("
+ exc.start.addr + ", " + exc.endAddr+")");
while (tryFlow.analyze(tryFlow.addr, exc.endAddr));
TryBlock tryBlock = new TryBlock(tryFlow); TryBlock tryBlock = new TryBlock(tryFlow);
} else if (! (tryFlow.block instanceof TryBlock)) } else if (!(tryFlow.block instanceof TryBlock))
throw new AssertError("no TryBlock"); throw new AssertError("no TryBlock");
FlowBlock catchFlow = exc.handler; FlowBlock catchFlow = exc.handler;
boolean isMultiUsed = catchFlow.predecessors.size() != 0; boolean isMultiUsed = catchFlow.predecessors.size() != 0;
@ -871,8 +909,8 @@ public class TransformExceptionHandlers {
FlowBlock newFlow = new FlowBlock(catchFlow.method, FlowBlock newFlow = new FlowBlock(catchFlow.method,
catchFlow.addr, 0); catchFlow.addr, 0);
newFlow.setBlock(jump); newFlow.setBlock(jump);
catchFlow.prevByAddr.setNextByAddr(newFlow); catchFlow.prevByAddr.nextByAddr = newFlow;
newFlow.setNextByAddr(catchFlow); newFlow.nextByAddr = catchFlow;
catchFlow = newFlow; catchFlow = newFlow;
} else { } else {
if ((GlobalOptions.debuggingFlags if ((GlobalOptions.debuggingFlags

Loading…
Cancel
Save