From b863984781b7bb927e8b619673d40876bc2831a4 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 8 Jul 1999 14:59:00 +0000 Subject: [PATCH] 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 --- .../jode/flow/TransformExceptionHandlers.java | 114 ++++++++++++------ 1 file changed, 76 insertions(+), 38 deletions(-) diff --git a/jode/jode/flow/TransformExceptionHandlers.java b/jode/jode/flow/TransformExceptionHandlers.java index e327058..8cf167f 100644 --- a/jode/jode/flow/TransformExceptionHandlers.java +++ b/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