changeset 2773:27512ea6bbcb

exception dispatch simplification: * BlockMap creates exception dispatch blocks (so they're iterated in the right order) * GraphBuilder uses exception dispatch blocks, simplified handleException, removed updateDispatchChain * simplified mergeOrClone * removed successor & predecessor methods from BlockBegin
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 24 May 2011 12:07:17 +0200
parents 3e3338a1abb9
children 93fd92c9f8b0
files graal/GraalCompiler/src/com/sun/c1x/graph/BlockMap.java graal/GraalCompiler/src/com/sun/c1x/graph/CriticalEdgeFinder.java graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java graal/GraalCompiler/src/com/sun/c1x/graph/IR.java graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java graal/GraalCompiler/src/com/sun/c1x/ir/ComputeLinearScanOrder.java graal/GraalCompiler/src/com/sun/c1x/ir/Deoptimize.java graal/GraalCompiler/src/com/sun/c1x/ir/ExceptionDispatch.java graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java
diffstat 11 files changed, 278 insertions(+), 299 deletions(-) [+]
line wrap: on
line diff
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/BlockMap.java	Tue May 24 10:27:15 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/BlockMap.java	Tue May 24 12:07:17 2011 +0200
@@ -122,12 +122,18 @@
 
         public Instruction firstInstruction;
 
-        private Block[] successors;
+        final HashSet<Block> successors = new HashSet<Block>();
         private boolean visited;
         private boolean active;
         private int loops;
     }
 
+    public static class ExceptionBlock  extends Block {
+        public RiExceptionHandler handler;
+        public Block next;
+        public Block handlerBlock;
+    }
+
     private static final Block[] NO_SUCCESSORS = new Block[0];
 
     /**
@@ -346,7 +352,6 @@
         if (oldBlock == null) {
             Block newBlock = new Block();
             newBlock.startBci = startBci;
-            newBlock.successors = NO_SUCCESSORS;
             blockMap[startBci] = newBlock;
             return newBlock;
 
@@ -356,10 +361,11 @@
             Block newBlock = new Block();
             newBlock.startBci = startBci;
             newBlock.endBci = oldBlock.endBci;
-            newBlock.successors = oldBlock.successors;
+            newBlock.successors.addAll(oldBlock.successors);
 
             oldBlock.endBci = startBci - 1;
-            oldBlock.successors = new Block[] {newBlock };
+            oldBlock.successors.clear();
+            oldBlock.successors.add(newBlock);
 
             for (int i = startBci; i <= newBlock.endBci; i++) {
                 blockMap[i] = newBlock;
@@ -388,8 +394,47 @@
             }
         }
         Block predecessor = blockMap[predBci];
-        assert predecessor.successors.length == 0;
-        predecessor.successors = successors;
+        assert predecessor.successors.size() == 0;
+        predecessor.successors.addAll(Arrays.asList(successors));
+    }
+
+    private HashMap<RiExceptionHandler, ExceptionBlock> exceptionDispatch = new HashMap<RiExceptionHandler, ExceptionBlock>();
+
+    private ExceptionBlock unwindBlock;
+
+    private ExceptionBlock makeUnwind() {
+        if (unwindBlock == null) {
+            unwindBlock = new ExceptionBlock();
+            unwindBlock.startBci = -1;
+            unwindBlock.endBci = -1;
+        }
+        return unwindBlock;
+    }
+
+    private Block makeExceptionDispatch(List<RiExceptionHandler> handlers, int index) {
+        RiExceptionHandler handler = handlers.get(index);
+        if (handler.isCatchAll()) {
+            return blockMap[handler.handlerBCI()];
+        }
+        ExceptionBlock block = exceptionDispatch.get(handler);
+        if (block == null) {
+            block = new ExceptionBlock();
+            block.startBci = -1;
+            block.endBci = -1;
+            block.handler = handler;
+            block.successors.add(blockMap[handler.handlerBCI()]);
+            block.handlerBlock = blockMap[handler.handlerBCI()];
+            Block next;
+            if (index < handlers.size() - 1) {
+                next = makeExceptionDispatch(handlers, index + 1);
+            } else {
+                next = makeUnwind();
+            }
+            block.successors.add(next);
+            block.next = next;
+            exceptionDispatch.put(handler, block);
+        }
+        return block;
     }
 
     private void addExceptionEdges() {
@@ -397,31 +442,25 @@
             return;
         }
 
-        Block block = null;
-        HashSet<Block> newSuccessorsOfBlock = new HashSet<Block>();
+        for (int bci = canTrap.nextSetBit(0); bci >= 0; bci = canTrap.nextSetBit(bci + 1)) {
+            Block block = blockMap[bci];
 
-        for (int bci = canTrap.nextSetBit(0); bci >= 0; bci = canTrap.nextSetBit(bci + 1)) {
-            Block newBlock = blockMap[bci];
-            if (newBlock != block) {
-                if (block != null) {
-                    block.successors = newSuccessorsOfBlock.toArray(new Block[newSuccessorsOfBlock.size()]);
-                    newSuccessorsOfBlock.clear();
-                }
-                Collections.addAll(newSuccessorsOfBlock, newBlock.successors);
-            }
-            block = newBlock;
-
+            ArrayList<RiExceptionHandler> handlers = null;
             for (RiExceptionHandler h : method.exceptionHandlers()) {
                 if (h.startBCI() <= bci && bci < h.endBCI()) {
-                    newSuccessorsOfBlock.add(blockMap[h.handlerBCI()]);
+                    if (handlers == null) {
+                        handlers = new ArrayList<RiExceptionHandler>();
+                    }
+                    handlers.add(h);
                     if (h.isCatchAll()) {
                         break;
                     }
                 }
             }
-        }
-        if (block != null) {
-            block.successors = newSuccessorsOfBlock.toArray(new Block[newSuccessorsOfBlock.size()]);
+            if (handlers != null) {
+                Block dispatch = makeExceptionDispatch(handlers, 0);
+                block.successors.add(dispatch);
+            }
         }
     }
 
@@ -513,18 +552,20 @@
         // process all the stores in this block
         byte[] code = method.code();
         int bci = block.startBci;
-        while (bci <= block.endBci) {
-            int opcode = Bytes.beU1(code, bci);
-            if (isStore(opcode)) {
-                processStore(opcode, Bytes.beU1(code, bci + 1));
+        if (bci >= 0) {
+            while (bci <= block.endBci) {
+                int opcode = Bytes.beU1(code, bci);
+                if (isStore(opcode)) {
+                    processStore(opcode, Bytes.beU1(code, bci + 1));
 
-            } else if (opcode == WIDE) {
-                opcode = Bytes.beU1(code, bci + 1);
-                if (isStore(opcode)) {
-                    processStore(opcode, Bytes.beU2(code, bci + 2));
+                } else if (opcode == WIDE) {
+                    opcode = Bytes.beU1(code, bci + 1);
+                    if (isStore(opcode)) {
+                        processStore(opcode, Bytes.beU2(code, bci + 2));
+                    }
                 }
+                bci += lengthOf(code, bci);
             }
-            bci += lengthOf(code, bci);
         }
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/CriticalEdgeFinder.java	Tue May 24 10:27:15 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/CriticalEdgeFinder.java	Tue May 24 12:07:17 2011 +0200
@@ -51,8 +51,9 @@
     }
 
     public void apply(BlockBegin block) {
-        if (block.numberOfSux() >= 2) {
-            for (BlockBegin succ : block.end().blockSuccessors()) {
+        BlockEnd end = block.end();
+        if (end.blockSuccessorCount() >= 2) {
+            for (BlockBegin succ : end.blockSuccessors()) {
                 if (succ.numberOfPreds() >= 2) {
                     // TODO: (tw) probably we don't have to make it a critical edge if succ only contains the _same_ predecessor multiple times.
                     recordCriticalEdge(block, succ);
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Tue May 24 10:27:15 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Tue May 24 12:07:17 2011 +0200
@@ -32,6 +32,7 @@
 import com.sun.c1x.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.graph.BlockMap.Block;
+import com.sun.c1x.graph.BlockMap.ExceptionBlock;
 import com.sun.c1x.ir.*;
 import com.sun.c1x.util.*;
 import com.sun.c1x.value.*;
@@ -84,7 +85,8 @@
 
     private final BytecodeStream stream;           // the bytecode stream
     // bci-to-block mapping
-    private Block[] blockList;
+    private Block[] blockFromBci;
+    private ArrayList<Block> blockList;
 
     // the constant pool
     private final RiConstantPool constantPool;
@@ -152,12 +154,16 @@
         // 2. compute the block map, setup exception handlers and get the entrypoint(s)
         BlockMap blockMap = compilation.getBlockMap(rootMethod);
 
-        blockList = new Block[rootMethod.code().length];
-        for (int i = 0; i < blockMap.blocks.size(); i++) {
+        blockList = new ArrayList<Block>(blockMap.blocks);
+        blockFromBci = new Block[rootMethod.code().length];
+        for (int i = 0; i < blockList.size(); i++) {
             int blockID = ir.nextBlockNumber();
             assert blockID == i;
-            Block block = blockMap.blocks.get(i);
-            blockList[block.startBci] = block;
+            Block block = blockList.get(i);
+            if (block.startBci >= 0) {
+                blockFromBci[block.startBci] = block;
+            }
+//            System.out.println("block " + blockID + " @ " + block.startBci);
         }
 
         // 1. create the start block
@@ -171,7 +177,7 @@
         if (handlers != null && handlers.length > 0) {
             exceptionHandlers = new ArrayList<ExceptionHandler>(handlers.length);
             for (RiExceptionHandler ch : handlers) {
-                Block entry = blockList[ch.handlerBCI()];
+                Block entry = blockFromBci[ch.handlerBCI()];
                 // entry == null means that the exception handler is unreachable according to the BlockMap conservative analysis
                 if (entry != null) {
                     ExceptionHandler h = new ExceptionHandler(ch);
@@ -182,7 +188,7 @@
             flags |= Flag.HasHandler.mask;
         }
 
-        mergeOrClone(startBlockBegin, frameState, false);
+        mergeOrClone(startBlock, frameState);
 
         // 3. setup internal state for appending instructions
         lastInstr = startBlockBegin;
@@ -203,6 +209,11 @@
             syncBlock.firstInstruction = syncHandler;
             markOnWorkList(syncBlock);
 
+            ExceptionBlock excBlock = new ExceptionBlock();
+            excBlock.startBci = -1;
+            excBlock.endBci = -1;
+            excBlock.blockID = ir.nextBlockNumber();
+            blockList.add(excBlock);
             ExceptionHandler h = new ExceptionHandler(new CiExceptionHandler(0, rootMethod.code().length, -1, 0, null));
             h.setEntryBlock(syncBlock);
             addExceptionHandler(h);
@@ -214,13 +225,30 @@
         // 5. SKIPPED: look for intrinsics
 
         // 6B.1 do the normal parsing
-        addToWorkList(blockList[0]);
+        addToWorkList(blockFromBci[0]);
         iterateAllBlocks();
 
         if (syncBlock != null && syncHandler.stateBefore() != null) {
             // generate unlocking code if the exception handler is reachable
             fillSyncHandler(rootMethodSynchronizedObject, syncBlock);
         }
+
+//        for (Node n : graph.getNodes()) {
+//            if (n instanceof FrameState) {
+//                boolean delete = false;
+//                if (n.usages().size() == 0 && n.predecessors().size() == 0) {
+//                    delete = true;
+//                }
+//                if (n.predecessors().size() == 0 && n.usages().size() == 1 && n.usages().get(0) instanceof BlockBegin) {
+//                    n.usages().get(0).inputs().replace(n, null);
+//                    delete = true;
+//                }
+//                if (delete) {
+//                    n.delete();
+//                    System.out.println("deleted framestate");
+//                }
+//            }
+//        }
     }
 
     private Block nextBlock(int bci) {
@@ -260,51 +288,46 @@
     }
 
     public void mergeOrClone(Block target, FrameStateAccess newState) {
-        assert target.firstInstruction instanceof BlockBegin;
-        if (target.isLoopHeader) {
-            mergeOrClone(target.firstInstruction, newState, true);
-        } else {
-            mergeOrClone(target.firstInstruction, newState, false);
-        }
-    }
-
+        Instruction first = target.firstInstruction;
+        int bci = target.startBci;
+        boolean loopHeader = target.isLoopHeader;
 
-    private void mergeOrClone(Instruction first, FrameStateAccess stateAfter, boolean loopHeader) {
-        mergeOrClone(first, stateAfter, loopHeader, false);
-    }
-
-    private void mergeOrClone(Instruction first, FrameStateAccess stateAfter, boolean loopHeader, boolean blockAppended) {
-        if (first instanceof BlockBegin) {
-            BlockBegin block = (BlockBegin) first;
-            FrameState existingState = block.stateBefore();
+        FrameState existingState;
+        if (first instanceof Placeholder) {
+            existingState = ((Placeholder) first).stateBefore();
+        } else {
+            assert first instanceof BlockBegin;
+            existingState = ((BlockBegin) first).stateBefore();
+        }
 
-            if (existingState == null) {
-                // copy state because it is modified
-                FrameState duplicate = stateAfter.duplicate(block.bci());
-
-                // if the block is a loop header, insert all necessary phis
-                if (loopHeader) {
-                    insertLoopPhis(block, duplicate);
-                }
+        if (existingState == null) {
+            // copy state because it is modified
+            FrameState duplicate = newState.duplicate(bci);
 
-                block.setStateBefore(duplicate);
+            // if the block is a loop header, insert all necessary phis
+            if (loopHeader) {
+                assert first instanceof BlockBegin;
+                insertLoopPhis((BlockBegin) first, duplicate);
+                ((BlockBegin) first).setStateBefore(duplicate);
             } else {
-                if (!C1XOptions.AssumeVerifiedBytecode && !existingState.isCompatibleWith(stateAfter)) {
-                    // stacks or locks do not match--bytecodes would not verify
-                    throw new CiBailout("stack or locks do not match");
+                if (first instanceof Placeholder) {
+                    ((Placeholder) first).setStateBefore(duplicate);
+                } else {
+                    ((BlockBegin) first).setStateBefore(duplicate);
                 }
-
-                assert existingState.localsSize() == stateAfter.localsSize();
-                assert existingState.stackSize() == stateAfter.stackSize();
-
-                existingState.merge(block, stateAfter, blockAppended);
             }
         } else {
-            assert false;
-        }
+
+            if (!C1XOptions.AssumeVerifiedBytecode && !existingState.isCompatibleWith(newState)) {
+                // stacks or locks do not match--bytecodes would not verify
+                throw new CiBailout("stack or locks do not match");
+            }
 
+            assert existingState.localsSize() == newState.localsSize();
+            assert existingState.stackSize() == newState.stackSize();
 
-
+            existingState.merge((BlockBegin) first, newState);
+        }
 
         for (int j = 0; j < frameState.localsSize() + frameState.stackSize(); ++j) {
             if (frameState.valueAt(j) != null) {
@@ -356,79 +379,38 @@
             return;
         }
 
-        ArrayList<ExceptionHandler> exceptionHandlers = new ArrayList<ExceptionHandler>();
-
         assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci";
 
+        ExceptionHandler firstHandler = null;
         // join with all potential exception handlers
         if (this.exceptionHandlers != null) {
             for (ExceptionHandler handler : this.exceptionHandlers) {
                 // if the handler covers this bytecode index, add it to the list
                 if (handler.covers(bci)) {
-                    ExceptionHandler newHandler = addExceptionHandler(handler, frameState);
-                    exceptionHandlers.add(newHandler);
-
-                    // stop when reaching catch all
-                    if (handler.isCatchAll()) {
-                        break;
-                    }
+                    firstHandler = new ExceptionHandler(handler);
+                    break;
                 }
             }
         }
 
-        if (!exceptionHandlers.isEmpty()) {
-            Instruction successor;
-
-            ArrayList<BlockBegin> newBlocks = new ArrayList<BlockBegin>();
+        if (firstHandler != null) {
+            compilation.setHasExceptionHandlers();
 
-            int current = exceptionHandlers.size() - 1;
-            if (exceptionHandlers.get(current).isCatchAll()) {
-                successor = createTarget(exceptionHandlers.get(current).entryBlock(), null);
-                current--;
-            } else {
-                if (unwindBlock == null) {
-                    unwindBlock = new BlockBegin(bci, ir.nextBlockNumber(), false, graph);
-                    Unwind unwind = new Unwind(null, graph);
-                    unwindBlock.appendNext(unwind);
-                }
-                successor = unwindBlock;
-            }
-
-            for (; current >= 0; current--) {
-                ExceptionHandler handler = exceptionHandlers.get(current);
-
-                BlockBegin newSucc = null;
-                for (Node pred : successor.predecessors()) {
-                    if (pred instanceof ExceptionDispatch) {
-                        ExceptionDispatch dispatch = (ExceptionDispatch) pred;
-                        if (dispatch.handler().handler == handler.handler) {
-                            newSucc = dispatch.begin();
-                            break;
-                        }
+            Block dispatchBlock = null;
+            for (Block block : blockList) {
+                if (block instanceof ExceptionBlock) {
+                    ExceptionBlock excBlock = (ExceptionBlock) block;
+                    if (excBlock.handler == firstHandler.handler) {
+                        dispatchBlock = block;
+                        break;
                     }
                 }
-                if (newSucc != null) {
-                    successor = newSucc;
-                } else {
-                    BlockBegin dispatchEntry = new BlockBegin(handler.handlerBCI(), ir.nextBlockNumber(), false, graph);
-
-                    if (handler.handler.catchType().isResolved()) {
-                        Instruction entry = createTarget(handler.entryBlock(), null);
-                        ExceptionDispatch end = new ExceptionDispatch(null, entry, null, handler, null, graph);
-                        end.setBlockSuccessor(0, successor);
-                        dispatchEntry.appendNext(end);
-                    } else {
-                        Deoptimize deopt = new Deoptimize(graph);
-                        dispatchEntry.appendNext(deopt);
-                        Goto end = new Goto(successor, null, graph);
-                        deopt.appendNext(end);
-                    }
-
-                    newBlocks.add(dispatchEntry);
-                    successor = dispatchEntry;
-                }
             }
-
+            // if there's no dispatch block then the catch block needs to be a catch all
+            if (dispatchBlock == null) {
+                assert firstHandler.isCatchAll();
+                dispatchBlock = firstHandler.entryBlock();
+            }
             FrameState entryState = frameState.duplicateWithEmptyStack(bci);
 
             BlockBegin entry = new BlockBegin(bci, ir.nextBlockNumber(), false, graph);
@@ -436,6 +418,8 @@
             ExceptionObject exception = new ExceptionObject(graph);
             entry.appendNext(exception);
             FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, exception);
+
+            Instruction successor = createTarget(dispatchBlock, stateWithException);
             BlockEnd end = new Goto(successor, stateWithException, graph);
             exception.appendNext(end);
 
@@ -444,67 +428,9 @@
             } else {
                 ((Throw) x).setExceptionEdge(entry);
             }
-
-            updateDispatchChain(end.blockSuccessor(0), stateWithException, bci);
         }
     }
 
-    private void updateDispatchChain(BlockBegin dispatchEntry, FrameStateAccess state, int bci) {
-        FrameState oldState = dispatchEntry.stateBefore();
-        if (oldState != null && dispatchEntry.predecessors().size() == 1) {
-            dispatchEntry.setStateBefore(null);
-        }
-        mergeOrClone(dispatchEntry, state, false, true);
-        FrameState mergedState = dispatchEntry.stateBefore();
-
-        if (dispatchEntry.next() instanceof ExceptionDispatch) {
-            // ordinary dispatch handler
-            ExceptionDispatch dispatch = (ExceptionDispatch) dispatchEntry.next();
-            dispatch.setStateAfter(mergedState.duplicate(bci));
-            dispatch.setException(mergedState.stackAt(0));
-            dispatch.catchSuccessor().setStateBefore(mergedState.duplicate(bci));
-            updateDispatchChain(dispatch.otherSuccessor(), mergedState, bci);
-        } else if (dispatchEntry.next() instanceof Deoptimize) {
-            // deoptimizing handler
-            dispatchEntry.end().setStateAfter(mergedState.duplicate(bci));
-            updateDispatchChain(dispatchEntry.end().blockSuccessor(0), mergedState, bci);
-        } else if (dispatchEntry.next() instanceof Unwind) {
-            // unwind handler
-            Unwind unwind = (Unwind) dispatchEntry.next();
-            unwind.setStateAfter(mergedState.duplicate(bci));
-            unwind.setException(mergedState.stackAt(0));
-        } else {
-            // synchronization or default exception handler, nothing to do
-        }
-    }
-
-    /**
-     * Adds an exception handler to the {@linkplain BlockBegin#exceptionHandlerBlocks() list}
-     * of exception handlers for the {@link #curBlock current block}.
-     */
-    private ExceptionHandler addExceptionHandler(ExceptionHandler handler, FrameStateAccess curState) {
-        compilation.setHasExceptionHandlers();
-
-        BlockMap.Block entry = handler.entryBlock();
-
-        // clone exception handler
-        ExceptionHandler newHandler = new ExceptionHandler(handler);
-
-        // fill in exception handler subgraph lazily
-        if (!isVisited(entry)) {
-            if (handler.handlerBCI() != Instruction.SYNCHRONIZATION_ENTRY_BCI) {
-                addToWorkList(entry);
-            }
-        } else {
-            // This will occur for exception handlers that cover themselves. This code
-            // pattern is generated by javac for synchronized blocks. See the following
-            // for why this change to javac was made:
-            //
-            //   http://www.cs.arizona.edu/projects/sumatra/hallofshame/java-async-race.html
-        }
-        return newHandler;
-    }
-
     private void genLoadConstant(int cpi) {
         Object con = constantPool().lookupConstant(cpi);
 
@@ -1124,28 +1050,20 @@
         return x;
     }
 
-    private Instruction blockAtOrNull(int bci) {
-        return blockList[bci] != null ? blockList[bci].firstInstruction : null;
-    }
-
-    private Instruction blockAt(int bci) {
-        Instruction result = blockAtOrNull(bci);
-        assert result != null : "Expected a block to begin at " + bci;
-        return result;
-    }
-
     private Instruction createTargetAt(int bci, FrameStateAccess stateAfter) {
-        return createTarget(blockList[bci], stateAfter);
+        return createTarget(blockFromBci[bci], stateAfter);
     }
 
     private Instruction createTarget(Block block, FrameStateAccess stateAfter) {
+        assert block != null && stateAfter != null;
         if (block.firstInstruction == null) {
-            BlockBegin blockBegin = new BlockBegin(block.startBci, block.blockID, block.isLoopHeader, graph);
-            block.firstInstruction = blockBegin;
+//            if (block.isLoopHeader) {
+                block.firstInstruction = new BlockBegin(block.startBci, block.blockID, block.isLoopHeader, graph);
+//            } else {
+//                block.firstInstruction = new Placeholder(graph);
+//            }
         }
-        if (stateAfter != null) {
-            mergeOrClone(block, stateAfter);
-        }
+        mergeOrClone(block, stateAfter);
         addToWorkList(block);
         return block.firstInstruction;
     }
@@ -1209,7 +1127,43 @@
                 lastInstr = block.firstInstruction;
                 assert block.firstInstruction.next() == null;
 
-                iterateBytecodesForBlock(block);
+                if (block instanceof ExceptionBlock) {
+                    createExceptionDispatch((ExceptionBlock) block);
+                } else {
+                    iterateBytecodesForBlock(block);
+                }
+            }
+        }
+    }
+
+    private void createExceptionDispatch(ExceptionBlock block) {
+        if (block.handler == null) {
+            assert frameState.stackSize() == 1 : "only exception object expected on stack, actual size: " + frameState.stackSize();
+            if (Modifier.isSynchronized(method().accessFlags())) {
+                // unlock before exiting the method
+                int lockNumber = frameState.locksSize() - 1;
+                MonitorAddress lockAddress = null;
+                if (compilation.runtime.sizeOfBasicObjectLock() != 0) {
+                    lockAddress = new MonitorAddress(lockNumber, graph);
+                    append(lockAddress);
+                }
+                append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, graph));
+                frameState.unlock();
+            }
+            append(new Unwind(frameState.apop(), graph));
+        } else {
+            assert frameState.stackSize() == 1;
+
+            if (block.handler.catchType().isResolved()) {
+                Instruction catchSuccessor = createTarget(block.handlerBlock, frameState);
+                Instruction nextDispatch = createTarget(block.next, frameState);
+                append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), frameState.duplicate(bci()), graph));
+            } else {
+                Deoptimize deopt = new Deoptimize(graph);
+                deopt.setMessage("unresolved " + block.handler.catchType().name());
+                append(deopt);
+                Instruction nextDispatch = createTarget(block.next, frameState);
+                append(new Goto(nextDispatch, frameState.duplicate(bci()), graph));
             }
         }
     }
@@ -1225,7 +1179,7 @@
 
         int bci = block.startBci;
         while (bci < endBCI) {
-            Block nextBlock = blockList[bci];
+            Block nextBlock = blockFromBci[bci];
             if (nextBlock != null && nextBlock != block) {
                 // we fell through to the next block, add a goto and break
                 Instruction next = createTarget(nextBlock, frameState);
@@ -1263,8 +1217,7 @@
         // connect to begin and set state
         // NOTE that inlining may have changed the block we are parsing
         assert end != null : "end should exist after iterating over bytecodes";
-        FrameState stateAtEnd = frameState.create(bci());
-        end.setStateAfter(stateAtEnd);
+        end.setStateAfter(frameState.create(bci()));
         return end;
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Tue May 24 10:27:15 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Tue May 24 12:07:17 2011 +0200
@@ -36,9 +36,6 @@
 /**
  * This class implements the overall container for the HIR (high-level IR) graph
  * and directs its construction, optimization, and finalization.
- *
- * @author Thomas Wuerthinger
- * @author Ben L. Titzer
  */
 public class IR {
 
@@ -158,8 +155,9 @@
                     lirBlock.blockPredecessors().add(valueToBlock.get(bb.predAt(i).block()));
                 }
 
-                for (int i = 0; i < bb.numberOfSux(); ++i) {
-                    lirBlock.blockSuccessors().add(valueToBlock.get(bb.suxAt(i)));
+                BlockEnd end = bb.end();
+                for (int i = 0; i < end.blockSuccessorCount(); ++i) {
+                    lirBlock.blockSuccessors().add(valueToBlock.get(end.blockSuccessor(i)));
                 }
 
                 Instruction first = bb;
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java	Tue May 24 10:27:15 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java	Tue May 24 12:07:17 2011 +0200
@@ -97,19 +97,6 @@
     }
 
     /**
-     * Gets the list of predecessors of this block.
-     * @return the predecessor list
-     */
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public List<Instruction> blockPredecessors() {
-        if (predecessors().size() == 1 && predecessors().get(0) == graph().start()) {
-            return Collections.EMPTY_LIST;
-        } else {
-            return (List) Collections.unmodifiableList(predecessors());
-        }
-    }
-
-    /**
      * Gets the linear scan number of this block.
      * @return the linear scan number
      */
@@ -147,10 +134,8 @@
             Instruction inst = this;
             ArrayList<BlockBegin> excBlocks = new ArrayList<BlockBegin>();
             while (inst != null) {
-                if (inst instanceof Invoke) {
-                    excBlocks.add(((Invoke) inst).exceptionEdge());
-                } else if (inst instanceof Throw) {
-                    excBlocks.add(((Throw) inst).exceptionEdge());
+                if (inst instanceof ExceptionEdgeInstruction) {
+                    excBlocks.add(((ExceptionEdgeInstruction) inst).exceptionEdge());
                 }
                 inst = inst.next();
             }
@@ -202,40 +187,6 @@
         return builder.toString();
     }
 
-    /**
-     * Get the number of successors.
-     * @return the number of successors
-     */
-    public int numberOfSux() {
-        return end().blockSuccessorCount();
-    }
-
-    /**
-     * Get the successor at a certain position.
-     * @param i the position
-     * @return the successor
-     */
-    public BlockBegin suxAt(int i) {
-        return end().blockSuccessor(i);
-    }
-
-    /**
-     * Get the number of predecessors.
-     * @return the number of predecessors
-     */
-    public int numberOfPreds() {
-        // ignore the graph root
-        if (predecessors().size() == 1 && predecessors().get(0) == graph().start()) {
-            return 0;
-        } else {
-            return predecessors().size();
-        }
-    }
-
-    public Instruction predAt(int j) {
-        return (Instruction) predecessors().get(j);
-    }
-
     public void printWithoutPhis(LogStream out) {
         // print block id
         BlockEnd end = end();
@@ -397,13 +348,14 @@
      * Iterates over all successors of this block: successors of the end node and exception handler.
      */
     public void allSuccessorsDo(boolean backwards, BlockClosure closure) {
+        BlockEnd end = end();
         if (backwards) {
-            for (int i = numberOfSux() - 1; i >= 0; i--) {
-                closure.apply(suxAt(i));
+            for (int i = end.blockSuccessorCount() - 1; i >= 0; i--) {
+                closure.apply(end.blockSuccessor(i));
             }
         } else {
-            for (int i = 0; i < numberOfSux(); i++) {
-                closure.apply(suxAt(i));
+            for (int i = 0; i < end.blockSuccessorCount(); i++) {
+                closure.apply(end.blockSuccessor(i));
             }
         }
         for (Instruction x = next(); x != null; x = x.next()) {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/ComputeLinearScanOrder.java	Tue May 24 10:27:15 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ComputeLinearScanOrder.java	Tue May 24 12:07:17 2011 +0200
@@ -177,8 +177,9 @@
 
     private int computeWeight(BlockBegin cur) {
         BlockBegin singleSux = null;
-        if (cur.numberOfSux() == 1) {
-            singleSux = cur.suxAt(0);
+        BlockEnd end = cur.end();
+        if (end.blockSuccessorCount() == 1) {
+            singleSux = end.blockSuccessor(0);
         }
 
         // limit loop-depth to 15 bit (only for security reason, it will never be so big)
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Deoptimize.java	Tue May 24 10:27:15 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Deoptimize.java	Tue May 24 12:07:17 2011 +0200
@@ -26,25 +26,25 @@
 import com.sun.c1x.debug.*;
 import com.sun.cri.ci.*;
 
-
-/**
- *
- */
 public class Deoptimize extends Instruction {
 
     private static final int INPUT_COUNT = 0;
     private static final int SUCCESSOR_COUNT = 0;
 
-    /**
-     * @param kind
-     * @param inputCount
-     * @param successorCount
-     * @param graph
-     */
+    private String message;
+
     public Deoptimize(Graph graph) {
         super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public String message() {
+        return message;
+    }
+
     @Override
     public void accept(ValueVisitor v) {
         v.visitDeoptimize(this);
@@ -55,4 +55,9 @@
         out.print("deoptimize");
     }
 
+    @Override
+    public String shortName() {
+        return "Deopt " + message;
+    }
+
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/ExceptionDispatch.java	Tue May 24 10:27:15 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ExceptionDispatch.java	Tue May 24 12:07:17 2011 +0200
@@ -26,6 +26,7 @@
 import com.sun.c1x.debug.*;
 import com.sun.c1x.value.*;
 import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
 
 /**
  * This instruction takes an exception object and has two successors:
@@ -59,21 +60,21 @@
         return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n);
     }
 
-    private final ExceptionHandler handler;
+    private final RiType catchType;
 
     /**
      * Constructs a new ExceptionDispatch instruction.
      */
-    public ExceptionDispatch(Value exception, Instruction catchSuccessor, Instruction otherSuccessor, ExceptionHandler handler, FrameState stateAfter, Graph graph) {
+    public ExceptionDispatch(Value exception, Instruction catchSuccessor, Instruction otherSuccessor, RiType catchType, FrameState stateAfter, Graph graph) {
         super(CiKind.Int, stateAfter, 2, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         setException(exception);
         setBlockSuccessor(0, otherSuccessor);
         setBlockSuccessor(1, catchSuccessor);
-        this.handler = handler;
+        this.catchType = catchType;
     }
 
-    public ExceptionHandler handler() {
-        return handler;
+    public RiType catchType() {
+        return catchType;
     }
 
     /**
@@ -113,7 +114,7 @@
         print(' ').
         print("instanceof").
         print(' ').
-        print(handler.handler.catchType().name()).
+        print(catchType().name()).
         print(" then B").
         print(blockSuccessors().get(1).blockID).
         print(" else B").
@@ -122,7 +123,7 @@
 
     @Override
     public String shortName() {
-        return "Dispatch " + handler.handler.catchType().name();
+        return "Dispatch " + catchType().name();
     }
 
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java	Tue May 24 10:27:15 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java	Tue May 24 12:07:17 2011 +0200
@@ -111,6 +111,36 @@
         return next;
     }
 
+    /**
+     * Gets the list of predecessors of this block.
+     * @return the predecessor list
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public List<Instruction> blockPredecessors() {
+        if (predecessors().size() == 1 && predecessors().get(0) == graph().start()) {
+            return Collections.EMPTY_LIST;
+        } else {
+            return (List) Collections.unmodifiableList(predecessors());
+        }
+    }
+
+    /**
+     * Get the number of predecessors.
+     * @return the number of predecessors
+     */
+    public int numberOfPreds() {
+        // ignore the graph root
+        if (predecessors().size() == 1 && predecessors().get(0) == graph().start()) {
+            return 0;
+        } else {
+            return predecessors().size();
+        }
+    }
+
+    public Instruction predAt(int j) {
+        return (Instruction) predecessors().get(j);
+    }
+
     @Override
     public BlockBegin block() {
         Instruction cur = this;
--- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java	Tue May 24 10:27:15 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java	Tue May 24 12:07:17 2011 +0200
@@ -517,7 +517,7 @@
     public void visitExceptionDispatch(ExceptionDispatch x) {
         // TODO ls: this needs some more work...
 
-        RiType riType = x.handler().handler.catchType();
+        RiType riType = x.catchType();
         assert riType.isResolved();
 
         XirArgument obj = toXirArgument(x.exception());
--- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java	Tue May 24 10:27:15 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java	Tue May 24 12:07:17 2011 +0200
@@ -325,7 +325,7 @@
         }
     }
 
-    public void merge(BlockBegin block, FrameStateAccess other, boolean blockAppended) {
+    public void merge(BlockBegin block, FrameStateAccess other) {
         checkSize(other);
         for (int i = 0; i < valuesSize(); i++) {
             Value x = valueAt(i);
@@ -354,9 +354,6 @@
                     Phi originalPhi = phi;
                     if (phi.valueCount() == 0) {
                         int size = block.predecessors().size();
-                        if (blockAppended) {
-                            size--;
-                        }
                         for (int j = 0; j < size; ++j) {
                             phi = phi.addInput(x);
                         }
@@ -372,7 +369,7 @@
                         }
                     }
 
-                    assert phi.valueCount() == block.predecessors().size() + (blockAppended ? 0 : 1) : "valueCount=" + phi.valueCount() + " predSize= " + block.predecessors().size();
+                    assert phi.valueCount() == block.predecessors().size() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.predecessors().size();
                }
             }
         }