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 25 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,
int startOutExit, int endOutExit,
int startMonExit, int endMonExit) {
FlowBlock subRoutine = null;
FlowBlock exitBlock = null;
Iterator succs = tryFlow.successors.values().iterator();
dest_loop:
while (succs.hasNext()) {
boolean isFirstJump = true;
for (Jump jumps = (Jump) succs.next();
jumps != null; jumps = jumps.next) {
jumps != null; jumps = jumps.next, isFirstJump = false) {
StructuredBlock prev = jumps.prev;
@ -437,28 +440,59 @@ public class TransformExceptionHandlers {
continue;
}
/* The block is a jsr that is not preceeded by 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;
}
}
}
if (isFirstJump) {
/* This is the first jump to that destination.
* Check if the destination does the monitorExit
*/
/* Now we have a jump that is not preceded by a monitorexit.
* Complain!
/* The block is a jsr that is not preceeded by
* 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
= new DescriptionBlock("ERROR: NO MONITOREXIT");
@ -523,11 +557,13 @@ public class TransformExceptionHandlers {
LocalInfo local =
((LocalLoadOperator)monexit.getSubExpressions()[0])
.getLocalInfo();
tryFlow.mergeAddr(catchFlow);
checkAndRemoveMonitorExit
(tryFlow, local, catchFlow.getNextAddr(), endHandler);
(tryFlow, local,
tryFlow.getNextAddr(), catchFlow.getAddr(),
catchFlow.getNextAddr(), endHandler);
tryFlow.mergeAddr(catchFlow);
SynchronizedBlock syncBlock = new SynchronizedBlock(local);
TryBlock tryBlock = (TryBlock) tryFlow.block;
syncBlock.replace(tryBlock);
@ -683,12 +719,13 @@ public class TransformExceptionHandlers {
TryBlock tryBlock = (TryBlock)tryFlow.block;
if (tryBlock.getSubBlocks()[0] instanceof TryBlock) {
/* remove the nested tryBlock */
/* remove the surrounding tryBlock */
TryBlock innerTry = (TryBlock)tryBlock.getSubBlocks()[0];
innerTry.gen = tryBlock.gen;
innerTry.replace(tryBlock);
tryBlock = innerTry;
tryFlow.lastModified = innerTry;
tryFlow.lastModified = tryBlock;
tryFlow.block = tryBlock;
}
FinallyBlock newBlock = new FinallyBlock();
newBlock.setCatchBlock(finallyBlock);
@ -832,22 +869,23 @@ public class TransformExceptionHandlers {
FlowBlock tryFlow = exc.start;
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.endAddr != exc.endAddr) {
/* The last handler does catch another range.
* 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);
} else if (! (tryFlow.block instanceof TryBlock))
throw new AssertError("no TryBlock");
} else if (!(tryFlow.block instanceof TryBlock))
throw new AssertError("no TryBlock");
FlowBlock catchFlow = exc.handler;
boolean isMultiUsed = catchFlow.predecessors.size() != 0;
@ -871,8 +909,8 @@ public class TransformExceptionHandlers {
FlowBlock newFlow = new FlowBlock(catchFlow.method,
catchFlow.addr, 0);
newFlow.setBlock(jump);
catchFlow.prevByAddr.setNextByAddr(newFlow);
newFlow.setNextByAddr(catchFlow);
catchFlow.prevByAddr.nextByAddr = newFlow;
newFlow.nextByAddr = catchFlow;
catchFlow = newFlow;
} else {
if ((GlobalOptions.debuggingFlags

Loading…
Cancel
Save