Mercurial > hg > truffle
diff graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java @ 2707:7ed72769d51a
exception handling related changes:
* changed blockPredecessors to list of Instructions, instead of Blocks
* removed explicit predecessor management in BlockBegin, now using predecessors from Graph structure
* replaced generated LIR exception entries with exception dispatch chains in IR
* added Unwind and ExceptionDispatch instructions
* removed ExceptionEntry flag in BlockBegin and all code depending on it
* removed exceptionHandler list from Instruction, replaced by exception Edge on Invoke and Throw
* replaced list of ExceptionHandlers with single exception edge in debug info
misc:
* changed GraphvizPrinter layout (smaller ports on large nodes)
* removed defunct run config
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Wed, 18 May 2011 18:09:20 +0200 |
parents | e0e89714e2f1 |
children | 4272b7af2d17 |
line wrap: on
line diff
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Wed May 18 18:09:20 2011 +0200 @@ -111,7 +111,7 @@ private final Graph graph; - private final List<BlockBegin> newExceptionHandlers = new ArrayList<BlockBegin>(); + private BlockBegin unwindBlock; /** * Creates a new, initialized, {@code GraphBuilder} instance for a given compilation. @@ -150,7 +150,7 @@ // 1. create the start block ir.startBlock = new BlockBegin(0, ir.nextBlockNumber(), graph); BlockBegin startBlock = ir.startBlock; -// graph.root().setStart(startBlock); + graph.root().setStart(startBlock); // 2. compute the block map, setup exception handlers and get the entrypoint(s) BlockMap blockMap = compilation.getBlockMap(rootMethod); @@ -159,9 +159,6 @@ for (int i = 0; i < blockMap.blocks.size(); i++) { BlockMap.Block block = blockMap.blocks.get(i); BlockBegin blockBegin = new BlockBegin(block.startBci, ir.nextBlockNumber(), graph); - if (block.isExceptionEntry) { - blockBegin.setBlockFlag(BlockBegin.BlockFlag.ExceptionEntry); - } if (block.isLoopHeader) { blockBegin.setBlockFlag(BlockBegin.BlockFlag.ParserLoopHeader); } @@ -204,7 +201,6 @@ // 4A.3 setup an exception handler to unlock the root method synchronized object syncHandler = new BlockBegin(Instruction.SYNCHRONIZATION_ENTRY_BCI, ir.nextBlockNumber(), graph); - syncHandler.setExceptionEntry(); syncHandler.setBlockFlag(BlockBegin.BlockFlag.IsOnWorkList); syncHandler.setBlockFlag(BlockBegin.BlockFlag.DefaultExceptionHandler); @@ -262,69 +258,148 @@ frameState.storeLocal(index, frameState.pop(kind)); } - List<ExceptionHandler> handleException(Instruction x, int bci) { + private void handleException(Instruction x, int bci) { if (!hasHandler()) { - return ExceptionHandler.ZERO_HANDLERS; + return; } ArrayList<ExceptionHandler> exceptionHandlers = new ArrayList<ExceptionHandler>(); - FrameState state = frameState.create(bci); assert bci == Instruction.SYNCHRONIZATION_ENTRY_BCI || bci == bci() : "invalid bci"; // 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)) { - // if the handler covers this bytecode index, add it to the list - if (addExceptionHandler(exceptionHandlers, handler, state)) { - // if the handler was a default handler, we are done - return exceptionHandlers; + ExceptionHandler newHandler = addExceptionHandler(handler, frameState); + exceptionHandlers.add(newHandler); + + // stop when reaching catch all + if (handler.isCatchAll()) { + break; } } } } - return exceptionHandlers; + if (!exceptionHandlers.isEmpty()) { + BlockBegin successor; + + ArrayList<BlockBegin> newBlocks = new ArrayList<BlockBegin>(); + + int current = exceptionHandlers.size() - 1; + if (exceptionHandlers.get(current).isCatchAll()) { + successor = exceptionHandlers.get(current).entryBlock(); + current--; + } else { + if (unwindBlock == null) { + unwindBlock = new BlockBegin(bci, ir.nextBlockNumber(), graph); + Unwind unwind = new Unwind(null, false, graph); + unwindBlock.appendNext(unwind, bci); + unwindBlock.setEnd(unwind); + } + successor = unwindBlock; + } + + for (; current >= 0; current--) { + ExceptionHandler handler = exceptionHandlers.get(current); + + BlockBegin newSucc = null; + for (Instruction pred : successor.blockPredecessors()) { + if (pred instanceof ExceptionDispatch) { + ExceptionDispatch dispatch = (ExceptionDispatch) pred; + if (dispatch.handler().handler == handler.handler) { + newSucc = dispatch.begin(); + break; + } + } + } + if (newSucc != null) { + successor = newSucc; + } else { + BlockBegin dispatchEntry = new BlockBegin(handler.handlerBCI(), ir.nextBlockNumber(), graph); + if (handler.handler.catchType().isResolved()) { + ExceptionDispatch end = new ExceptionDispatch(null, handler.entryBlock(), null, handler, null, false, graph); + end.setBlockSuccessor(0, successor); + dispatchEntry.appendNext(end, handler.handlerBCI()); + dispatchEntry.setEnd(end); + } else { + Deoptimize deopt = new Deoptimize(graph, null); + dispatchEntry.appendNext(deopt, bci); + Goto end = new Goto(successor, null, false, graph); + deopt.appendNext(end, bci); + dispatchEntry.setEnd(end); + } + newBlocks.add(dispatchEntry); + successor = dispatchEntry; + } + } + + FrameState entryState = frameState.duplicateWithEmptyStack(bci); + + BlockBegin entry = new BlockBegin(bci, ir.nextBlockNumber(), graph); + entry.setStateBefore(entryState); + ExceptionObject exception = new ExceptionObject(graph); + entry.appendNext(exception, bci); + FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, exception); + BlockEnd end = new Goto(successor, stateWithException, false, graph); + exception.appendNext(end, bci); + entry.setEnd(end); + + if (x instanceof Invoke) { + ((Invoke) x).setExceptionEdge(entry); + } 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); + oldState.delete(); + } + dispatchEntry.mergeOrClone(state, null); + 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 + Deoptimize deopt = (Deoptimize) dispatchEntry.next(); + deopt.setStateBefore(mergedState.duplicate(bci)); + 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}. - * - * @param exceptionHandlers - * @param handler - * @param curScopeData - * @param curState the current state with empty stack - * @param scopeCount - * @return {@code true} if handler catches all exceptions (i.e. {@code handler.isCatchAll() == true}) */ - private boolean addExceptionHandler(ArrayList<ExceptionHandler> exceptionHandlers, ExceptionHandler handler, FrameState curState) { + private ExceptionHandler addExceptionHandler(ExceptionHandler handler, FrameStateAccess curState) { compilation.setHasExceptionHandlers(); BlockBegin entry = handler.entryBlock(); - FrameState entryState = entry.stateBefore(); - - assert entry.bci() == handler.handler.handlerBCI(); - assert entryState == null || curState.locksSize() == entryState.locksSize() : "locks do not match : cur:" + curState.locksSize() + " entry:" + entryState.locksSize(); - - // exception handler starts with an empty expression stack - curState = curState.duplicateWithEmptyStack(); - - entry.mergeOrClone(curState, method()); - - // add current state for correct handling of phi functions - int phiOperand = entry.addExceptionState(curState); - - // add entry to the list of exception handlers of this block - curBlock.addExceptionHandler(entry); - - newExceptionHandlers.add(entry); // clone exception handler ExceptionHandler newHandler = new ExceptionHandler(handler); - newHandler.setPhiOperand(phiOperand); - exceptionHandlers.add(newHandler); // fill in exception handler subgraph lazily if (!entry.wasVisited()) { @@ -336,9 +411,7 @@ // // http://www.cs.arizona.edu/projects/sumatra/hallofshame/java-async-race.html } - - // stop when reaching catch all - return handler.isCatchAll(); + return newHandler; } private void genLoadConstant(int cpi) { @@ -973,7 +1046,7 @@ if (x instanceof Invoke || x instanceof Throw) { // connect the instruction to any exception handlers - x.setExceptionHandlers(handleException(x, bci)); + handleException(x, bci); } return x; @@ -1011,7 +1084,6 @@ frameState.initializeFrom(syncHandler.stateBefore()); int bci = Instruction.SYNCHRONIZATION_ENTRY_BCI; - Value exception = appendWithoutOptimization(new ExceptionObject(graph), bci); assert lock != null; assert frameState.locksSize() > 0 && frameState.lockAt(frameState.locksSize() - 1) == lock; @@ -1024,7 +1096,6 @@ // exit the monitor genMonitorExit(lock, Instruction.SYNCHRONIZATION_ENTRY_BCI); - frameState.apush(exception); genThrow(bci); BlockEnd end = (BlockEnd) lastInstr; curBlock.setEnd(end); @@ -1039,6 +1110,13 @@ private void iterateAllBlocks() { BlockBegin b; while ((b = removeFromWorkList()) != null) { + + // remove blocks that have no predecessors by the time it their bytecodes are parsed + if (b.blockPredecessors().size() == 0) { + b.setWasVisited(true); + continue; + } + if (!b.wasVisited()) { b.setWasVisited(true); // now parse the block @@ -1058,7 +1136,6 @@ BlockBegin block = curBlock; BlockEnd end = null; - boolean pushException = block.isExceptionEntry() && block.next() == null; int prevBCI = bci; int endBCI = stream.endBCI(); boolean blockStart = true; @@ -1082,12 +1159,6 @@ // read the opcode int opcode = stream.currentBC(); - // push an exception object onto the stack if we are parsing an exception handler - if (pushException) { - frameState.apush(append(new ExceptionObject(graph))); - pushException = false; - } - traceState(); traceInstruction(bci, stream, opcode, blockStart); processBytecode(bci, stream, opcode); @@ -1121,14 +1192,6 @@ end.setStateAfter(stateAtEnd); curBlock.setEnd(end); - for (BlockBegin entry : newExceptionHandlers) { - // add back-edge from exception handler entry to this block - if (!entry.blockPredecessors().contains(curBlock.end())) { - entry.addPredecessor(curBlock.end()); - } - } - newExceptionHandlers.clear(); - // propagate the state for (BlockBegin succ : end.blockSuccessors()) { assert succ.blockPredecessors().contains(curBlock.end());