diff graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java @ 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 056e392d63d4
children 93fd92c9f8b0
line wrap: on
line diff
--- 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;
     }