# HG changeset patch # User Lukas Stadler # Date 1305734960 -7200 # Node ID 7ed72769d51a8fd67d696c47f89f05bb6ca79165 # Parent 0ea5f12e873ac7f567574b1d2c13ab56f2442b52 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 diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java --- a/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/C1XCompilation.java Wed May 18 18:09:20 2011 +0200 @@ -266,9 +266,6 @@ // generate code for slow cases lirAssembler.emitLocalStubs(); - // generate exception adapters - lirAssembler.emitExceptionEntries(); - // generate deoptimization stubs ArrayList deoptimizationStubs = lirGenerator.deoptimizationStubs(); if (deoptimizationStubs != null) { diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/alloc/ControlFlowOptimizer.java --- a/graal/GraalCompiler/src/com/sun/c1x/alloc/ControlFlowOptimizer.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/ControlFlowOptimizer.java Wed May 18 18:09:20 2011 +0200 @@ -101,9 +101,7 @@ // must always end with an unconditional branch to this successor private boolean canDeleteBlock(BlockBegin block) { if (block.numberOfSux() != 1 || - block.numberOfExceptionHandlers() != 0 || block == ir.startBlock || - block.isExceptionEntry() || block.suxAt(0) == block) { return false; } @@ -138,8 +136,8 @@ } // update the block references in any branching LIR instructions - for (BlockEnd pred : block.blockPredecessors()) { - for (LIRInstruction instr : pred.begin().lir().instructionsList()) { + for (Instruction pred : block.blockPredecessors()) { + for (LIRInstruction instr : pred.block().lir().instructionsList()) { if (instr instanceof LIRBranch) { ((LIRBranch) instr).substitute(block, newTarget); } else if (instr instanceof LIRTableSwitch) { @@ -228,7 +226,7 @@ CiValue returnOpr = ((LIROp1) curLastOp).operand(); for (int j = block.numberOfPreds() - 1; j >= 0; j--) { - BlockBegin pred = block.predAt(j).begin(); + BlockBegin pred = block.predAt(j).block(); List predInstructions = pred.lir().instructionsList(); LIRInstruction predLastOp = predInstructions.get(predInstructions.size() - 1); @@ -263,8 +261,8 @@ assert code.contains(sux) : "missing successor from: " + block + "to: " + sux; } - for (BlockEnd pred : block.blockPredecessors()) { - assert code.contains(pred.begin()) : "missing predecessor from: " + block + "to: " + pred.begin(); + for (Instruction pred : block.blockPredecessors()) { + assert code.contains(pred.block()) : "missing predecessor from: " + block + "to: " + pred.block(); } } diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/alloc/EdgeMoveOptimizer.java --- a/graal/GraalCompiler/src/com/sun/c1x/alloc/EdgeMoveOptimizer.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/EdgeMoveOptimizer.java Wed May 18 18:09:20 2011 +0200 @@ -66,7 +66,7 @@ for (int i = blockList.size() - 1; i >= 1; i--) { BlockBegin block = blockList.get(i); - if (block.numberOfPreds() > 1 && !block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) { + if (block.numberOfPreds() > 1) { optimizer.optimizeMovesAtBlockEnd(block); } if (block.numberOfSux() == 2) { @@ -122,11 +122,10 @@ int numPreds = block.numberOfPreds(); assert numPreds > 1 : "do not call otherwise"; - assert !block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry) : "exception handlers not allowed"; // setup a list with the LIR instructions of all predecessors for (int i = 0; i < numPreds; i++) { - BlockBegin pred = block.predAt(i).begin(); + BlockBegin pred = block.predAt(i).block(); List predInstructions = pred.lir().instructionsList(); if (pred.numberOfSux() != 1) { @@ -231,8 +230,7 @@ // the same blocks. return; } - assert sux.predAt(0).begin() == block : "invalid control flow"; - assert !sux.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry) : "exception handlers not allowed"; + assert sux.predAt(0).block() == block : "invalid control flow"; // ignore the label at the beginning of the block List seq = suxInstructions.subList(1, suxInstructions.size()); diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java --- a/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.java Wed May 18 18:09:20 2011 +0200 @@ -28,18 +28,18 @@ import java.util.*; import com.sun.c1x.*; -import com.sun.c1x.alloc.Interval.*; +import com.sun.c1x.alloc.Interval.RegisterBinding; +import com.sun.c1x.alloc.Interval.RegisterPriority; +import com.sun.c1x.alloc.Interval.SpillState; import com.sun.c1x.debug.*; import com.sun.c1x.gen.*; import com.sun.c1x.graph.*; import com.sun.c1x.ir.*; -import com.sun.c1x.ir.BlockBegin.BlockFlag; import com.sun.c1x.lir.*; import com.sun.c1x.lir.LIRInstruction.OperandMode; import com.sun.c1x.observer.*; import com.sun.c1x.util.*; import com.sun.c1x.value.*; -import com.sun.c1x.value.FrameState.PhiProcedure; import com.sun.c1x.value.FrameState.ValueProcedure; import com.sun.cri.ci.*; import com.sun.cri.ri.*; @@ -599,17 +599,6 @@ final CiBitMap liveGen = new CiBitMap(liveSize); final CiBitMap liveKill = new CiBitMap(liveSize); - if (block.isExceptionEntry()) { - // Phi functions at the begin of an exception handler are - // implicitly defined (= killed) at the beginning of the block. - block.stateBefore().forEachLivePhi(block, new PhiProcedure() { - public boolean doPhi(Phi phi) { - liveKill.set(operandNumber(phi.operand())); - return true; - } - }); - } - List instructions = block.lir().instructionsList(); int numInst = instructions.size(); @@ -773,8 +762,7 @@ // liveOut(block) is the union of liveIn(sux), for successors sux of block int n = block.numberOfSux(); - int e = block.numberOfExceptionHandlers(); - if (n + e > 0) { + if (n > 0) { // block has successors if (n > 0) { liveOut.setFrom(block.suxAt(0).lirBlock.liveIn); @@ -784,9 +772,6 @@ } else { liveOut.clearAll(); } - for (int j = 0; j < e; j++) { - liveOut.setUnion(block.exceptionHandlerAt(j).lirBlock.liveIn); - } if (!lirBlock.liveOut.isSame(liveOut)) { // A change occurred. Swap the old and new live out sets to avoid copying. @@ -1282,19 +1267,19 @@ } // end of instruction iteration // (tw) Make sure that no spill store optimization is applied for phi instructions that flow into exception handlers. - if (block.isExceptionEntry()) { - FrameState stateBefore = block.stateBefore(); - stateBefore.forEachLivePhi(block, new PhiProcedure() { - @Override - public boolean doPhi(Phi phi) { - Interval interval = intervalFor(phi.operand()); - if (interval != null) { - interval.setSpillState(SpillState.NoOptimization); - } - return true; - } - }); - } +// if (block.isExceptionEntry()) { +// FrameState stateBefore = block.stateBefore(); +// stateBefore.forEachLivePhi(block, new PhiProcedure() { +// @Override +// public boolean doPhi(Phi phi) { +// Interval interval = intervalFor(phi.operand()); +// if (interval != null) { +// interval.setSpillState(SpillState.NoOptimization); +// } +// return true; +// } +// }); +// } } // end of block iteration @@ -1596,7 +1581,7 @@ // may have be more than one predecessor but it will be guaranteed // that all predecessors will be the same. for (int i = 0; i < toBlock.numberOfPreds(); i++) { - assert fromBlock == toBlock.predAt(i).begin() : "all critical edges must be broken"; + assert fromBlock == toBlock.predAt(i).block() : "all critical edges must be broken"; } } @@ -1619,7 +1604,7 @@ BlockBegin block = blockAt(i); // check if block has only one predecessor and only one successor - if (block.numberOfPreds() == 1 && block.numberOfSux() == 1 && block.numberOfExceptionHandlers() == 0 && !block.isExceptionEntry()) { + if (block.numberOfPreds() == 1 && block.numberOfSux() == 1) { List instructions = block.lir().instructionsList(); assert instructions.get(0).code == LIROpcode.Label : "block must start with label"; assert instructions.get(instructions.size() - 1).code == LIROpcode.Branch : "block with successors must end with branch"; @@ -1627,7 +1612,7 @@ // check if block is empty (only label and branch) if (instructions.size() == 2) { - BlockBegin pred = block.predAt(0).begin(); + BlockBegin pred = block.predAt(0).block(); BlockBegin sux = block.suxAt(0); // prevent optimization of two consecutive blocks @@ -1676,191 +1661,6 @@ } } - void resolveExceptionEntry(BlockBegin block, CiValue operand, MoveResolver moveResolver) { - if (intervalFor(operand) == null) { - // if a phi function is never used, no interval is created . ignore this - return; - } - - Interval interval = intervalAtBlockBegin(block, operand); - CiValue location = interval.location(); - - if (location.isRegister() && interval.alwaysInMemory()) { - // the interval is split to get a short range that is located on the stack - // in the following two cases: - // * the interval started in memory (e.g. method parameter), but is currently in a register - // this is an optimization for exception handling that reduces the number of moves that - // are necessary for resolving the states when an exception uses this exception handler - // * the interval would be on the fpu stack at the begin of the exception handler - // this is not allowed because of the complicated fpu stack handling on Intel - - // range that will be spilled to memory - int fromOpId = block.firstLirInstructionId(); - int toOpId = fromOpId + 1; // short live range of length 1 - assert interval.from() <= fromOpId && interval.to() >= toOpId : "no split allowed between exception entry and first instruction"; - - if (interval.from() != fromOpId) { - // the part before fromOpId is unchanged - interval = interval.split(fromOpId, this); - interval.assignLocation(location); - } - assert interval.from() == fromOpId : "must be true now"; - - Interval spilledPart = interval; - if (interval.to() != toOpId) { - // the part after toOpId is unchanged - spilledPart = interval.splitFromStart(toOpId, this); - moveResolver.addMapping(spilledPart, interval); - } - assignSpillSlot(spilledPart); - - assert spilledPart.from() == fromOpId && spilledPart.to() == toOpId : "just checking"; - } - } - - void resolveExceptionEntry(final BlockBegin block, final MoveResolver moveResolver) { - assert block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry) : "should not call otherwise"; - assert moveResolver.checkEmpty(); - - // visit all registers where the liveIn bit is set - for (int operandNum = block.lirBlock.liveIn.nextSetBit(0); operandNum >= 0; operandNum = block.lirBlock.liveIn.nextSetBit(operandNum + 1)) { - resolveExceptionEntry(block, operands.operandFor(operandNum), moveResolver); - } - - // the liveIn bits are not set for phi functions of the xhandler entry, so iterate them separately - block.stateBefore().forEachLivePhi(block, new PhiProcedure() { - public boolean doPhi(Phi phi) { - resolveExceptionEntry(block, phi.operand(), moveResolver); - return true; - } - }); - - if (moveResolver.hasMappings()) { - // insert moves after first instruction - moveResolver.setInsertPosition(block.lir(), 0); - moveResolver.resolveAndAppendMoves(); - } - } - - void resolveExceptionEdge(ExceptionHandler handler, int throwingOpId, CiValue operand, Phi phi, MoveResolver moveResolver) { - if (intervalFor(operand) == null) { - // if a phi function is never used, no interval is created . ignore this - return; - } - - // the computation of toInterval is equal to resolveCollectMappings, - // but fromInterval is more complicated because of phi functions - BlockBegin toBlock = handler.entryBlock(); - Interval toInterval = intervalAtBlockBegin(toBlock, operand); - - if (phi != null) { - // phi function of the exception entry block - // no moves are created for this phi function in the LIRGenerator, so the - // interval at the throwing instruction must be searched using the operands - // of the phi function - Value fromValue = phi.inputAt(handler.phiOperand()); - Constant con = null; - if (fromValue instanceof Constant) { - con = (Constant) fromValue; - } - if (con != null && (con.operand().isIllegal() || con.operand().isConstant())) { - // unpinned constants may have no register, so add mapping from constant to interval - moveResolver.addMapping(con.asConstant(), toInterval); - } else { - // search split child at the throwing opId - Interval fromInterval = intervalAtOpId(fromValue.operand(), throwingOpId); - if (fromInterval != toInterval) { - moveResolver.addMapping(fromInterval, toInterval); - // with phi functions it can happen that the same fromValue is used in - // multiple mappings, so notify move-resolver that this is allowed - moveResolver.setMultipleReadsAllowed(); - } - } - } else { - // no phi function, so use regNum also for fromInterval - // search split child at the throwing opId - Interval fromInterval = intervalAtOpId(operand, throwingOpId); - if (fromInterval != toInterval) { - // optimization to reduce number of moves: when toInterval is on stack and - // the stack slot is known to be always correct, then no move is necessary - if (!fromInterval.alwaysInMemory() || fromInterval.spillSlot() != toInterval.location()) { - moveResolver.addMapping(fromInterval, toInterval); - } - } - } - } - - void resolveExceptionEdge(final ExceptionHandler handler, final int throwingOpId, final MoveResolver moveResolver) { - if (C1XOptions.TraceLinearScanLevel >= 4) { - TTY.println("resolving exception handler B%d: throwingOpId=%d", handler.entryBlock().blockID, throwingOpId); - } - - assert moveResolver.checkEmpty(); - assert handler.lirOpId() == -1 : "already processed this xhandler"; - handler.setLirOpId(throwingOpId); - assert handler.entryCode() == null : "code already present"; - - // visit all registers where the liveIn bit is set - BlockBegin block = handler.entryBlock(); - for (int operandNum = block.lirBlock.liveIn.nextSetBit(0); operandNum >= 0; operandNum = block.lirBlock.liveIn.nextSetBit(operandNum + 1)) { - resolveExceptionEdge(handler, throwingOpId, operands.operandFor(operandNum), null, moveResolver); - } - - // the liveIn bits are not set for phi functions of the xhandler entry, so iterate them separately - block.stateBefore().forEachLivePhi(block, new PhiProcedure() { - public boolean doPhi(Phi phi) { - resolveExceptionEdge(handler, throwingOpId, phi.operand(), phi, moveResolver); - return true; - } - }); - - if (moveResolver.hasMappings()) { - LIRList entryCode = new LIRList(gen); - moveResolver.setInsertPosition(entryCode, 0); - moveResolver.resolveAndAppendMoves(); - - entryCode.jump(handler.entryBlock()); - handler.setEntryCode(entryCode); - } - } - - void resolveExceptionHandlers() { - MoveResolver moveResolver = new MoveResolver(this); - //LIRVisitState visitor = new LIRVisitState(); - int numBlocks = blockCount(); - - int i; - for (i = 0; i < numBlocks; i++) { - BlockBegin block = blockAt(i); - if (block.checkBlockFlag(BlockFlag.ExceptionEntry)) { - resolveExceptionEntry(block, moveResolver); - } - } - - for (i = 0; i < numBlocks; i++) { - BlockBegin block = blockAt(i); - LIRList ops = block.lir(); - int numOps = ops.length(); - - // iterate all instructions of the block. skip the first because it is always a label - assert !ops.at(0).hasOperands() : "first operation must always be a label"; - for (int j = 1; j < numOps; j++) { - LIRInstruction op = ops.at(j); - int opId = op.id; - - if (opId != -1 && op.info != null) { - // visit operation to collect all operands - for (ExceptionHandler handler : op.exceptionEdges()) { - resolveExceptionEdge(handler, opId, moveResolver); - } - - } else if (C1XOptions.DetailedAsserts) { - assert op.exceptionEdges().size() == 0 : "missed exception handler"; - } - } - } - } - // * Phase 7: assign register numbers back to LIR // (includes computation of debug information and oop maps) @@ -2172,13 +1972,11 @@ if (op.info != null) { // exception handling - if (compilation.hasExceptionHandlers()) { - for (ExceptionHandler handler : op.exceptionEdges()) { - if (handler.entryCode() != null) { - assignLocations(handler.entryCode().instructionsList(), null); - } - } - } +// if (compilation.hasExceptionHandlers()) { +// if (op.exceptionEdge() != null && op.exceptionEdge().lir() != null) { +// assignLocations(op.exceptionEdge().lir().instructionsList(), iw); +// } +// } // compute reference map and debug information computeDebugInfo(iw, op); @@ -2252,9 +2050,6 @@ } resolveDataFlow(); - if (compilation.hasExceptionHandlers()) { - resolveExceptionHandlers(); - } if (C1XOptions.PrintTimers) { C1XTimers.RESOLUTION.stop(); diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/alloc/RegisterVerifier.java --- a/graal/GraalCompiler/src/com/sun/c1x/alloc/RegisterVerifier.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/alloc/RegisterVerifier.java Wed May 18 18:09:20 2011 +0200 @@ -134,18 +134,18 @@ } } - void processXhandler(ExceptionHandler xhandler, Interval[] inputState) { + void processXhandler(BlockBegin xhandler, Interval[] inputState) { if (C1XOptions.TraceLinearScanLevel >= 2) { - TTY.println("processXhandler B%d", xhandler.entryBlock().blockID); + TTY.println("processXhandler B%d", xhandler.blockID); } // must copy state because it is modified inputState = copy(inputState); - if (xhandler.entryCode() != null) { - processOperations(xhandler.entryCode(), inputState); + if (xhandler.lir() != null) { + processOperations(xhandler.lir(), inputState); } - processSuccessor(xhandler.entryBlock(), inputState); + processSuccessor(xhandler, inputState); } void processSuccessor(BlockBegin block, Interval[] inputState) { @@ -260,10 +260,8 @@ } // process xhandler before output and temp operands - List xhandlers = op.exceptionEdges(); - n = xhandlers.size(); - for (int k = 0; k < n; k++) { - processXhandler(xhandlers.get(k), inputState); + if (op.exceptionEdge() != null) { + processXhandler(op.exceptionEdge(), inputState); } // set temp operands (some operations use temp operands also as output operands, so can't set them null) diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/asm/ExceptionInfo.java --- a/graal/GraalCompiler/src/com/sun/c1x/asm/ExceptionInfo.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/asm/ExceptionInfo.java Wed May 18 18:09:20 2011 +0200 @@ -22,8 +22,6 @@ */ package com.sun.c1x.asm; -import java.util.*; - import com.sun.c1x.ir.*; /** @@ -33,12 +31,12 @@ public class ExceptionInfo { public final int codeOffset; - public final List exceptionHandlers; + public final BlockBegin exceptionEdge; public final int bci; - public ExceptionInfo(int pcOffset, List exceptionHandlers, int bci) { + public ExceptionInfo(int pcOffset, BlockBegin exceptionEdge, int bci) { this.codeOffset = pcOffset; - this.exceptionHandlers = exceptionHandlers; + this.exceptionEdge = exceptionEdge; this.bci = bci; } } diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/asm/TargetMethodAssembler.java --- a/graal/GraalCompiler/src/com/sun/c1x/asm/TargetMethodAssembler.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/asm/TargetMethodAssembler.java Wed May 18 18:09:20 2011 +0200 @@ -27,7 +27,6 @@ import com.oracle.max.asm.*; import com.sun.c1x.*; import com.sun.c1x.debug.*; -import com.sun.c1x.ir.*; import com.sun.c1x.lir.*; import com.sun.c1x.util.*; import com.sun.cri.ci.*; @@ -65,11 +64,7 @@ if (exceptionInfoList != null) { for (ExceptionInfo ei : exceptionInfoList) { int codeOffset = ei.codeOffset; - for (ExceptionHandler handler : ei.exceptionHandlers) { - int entryOffset = handler.entryCodeOffset(); - RiType caughtType = handler.handler.catchType(); - targetMethod.recordExceptionHandler(codeOffset, ei.bci, 0, entryOffset, handler.handlerBCI(), caughtType); - } + targetMethod.recordExceptionHandler(codeOffset, -1, 0, ei.exceptionEdge.lirBlock.blockEntryPco, -1, null); } } @@ -145,11 +140,11 @@ public void recordExceptionHandlers(int pcOffset, LIRDebugInfo info) { if (info != null) { - if (info.exceptionHandlers != null) { + if (info.exceptionEdge != null) { if (exceptionInfoList == null) { exceptionInfoList = new ArrayList(4); } - exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionHandlers, info.state.bci)); + exceptionInfoList.add(new ExceptionInfo(pcOffset, info.exceptionEdge, info.state.bci)); } } } diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/debug/CFGPrinter.java --- a/graal/GraalCompiler/src/com/sun/c1x/debug/CFGPrinter.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/debug/CFGPrinter.java Wed May 18 18:09:20 2011 +0200 @@ -124,7 +124,7 @@ * @param printHIR if {@code true} the HIR for each instruction in the block will be printed * @param printLIR if {@code true} the LIR for each instruction in the block will be printed */ - void printBlock(BlockBegin block, List successors, Iterable handlers, boolean printHIR, boolean printLIR) { + void printBlock(BlockBegin block, List successors, BlockBegin handler, boolean printHIR, boolean printLIR) { begin("block"); out.print("name \"B").print(block.blockID).println('"'); @@ -132,8 +132,8 @@ out.print("to_bci ").println(block.end() == null ? -1 : block.end().bci()); out.print("predecessors "); - for (BlockEnd pred : block.blockPredecessors()) { - out.print("\"B").print(pred.begin().blockID).print("\" "); + for (Instruction pred : block.blockPredecessors()) { + out.print("\"B").print(pred.block().blockID).print("\" "); } out.println(); @@ -144,15 +144,12 @@ out.println(); out.print("xhandlers"); - for (BlockBegin handler : handlers) { + if (handler != null) { out.print("\"B").print(handler.blockID).print("\" "); } out.println(); out.print("flags "); - if (block.isExceptionEntry()) { - out.print("\"ex\" "); - } if (block.isSubroutineEntry()) { out.print("\"sr\" "); } @@ -587,7 +584,7 @@ startBlock.iteratePreOrder(new BlockClosure() { public void apply(BlockBegin block) { List successors = block.end() != null ? block.end().blockSuccessors() : new ArrayList(0); - printBlock(block, successors, block.exceptionHandlerBlocks(), printHIR, printLIR); + printBlock(block, successors, block.exceptionEdge(), printHIR, printLIR); } }); end("cfg"); diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java --- a/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java Wed May 18 18:09:20 2011 +0200 @@ -394,7 +394,6 @@ @Override public void visitExceptionObject(ExceptionObject x) { - assert currentBlock.isExceptionEntry() : "ExceptionObject only allowed in exception handler block"; assert currentBlock.next() == x : "ExceptionObject must be first instruction of block"; // no moves are created for phi functions at the begin of exception @@ -1446,7 +1445,7 @@ } assert state != null; - return new LIRDebugInfo(state, x.exceptionHandlers()); + return new LIRDebugInfo(state, x.exceptionEdge()); } List visitInvokeArguments(CiCallingConvention cc, Invoke x, List pointerSlots) { @@ -1611,4 +1610,15 @@ public void visitFrameState(FrameState i) { // nothing to do for now } + + @Override + public void visitUnwind(Unwind x) { + // TODO ls: this needs some thorough testing... + CiValue operand = resultOperandFor(x.kind); + CiValue result = force(x.exception(), operand); + ArrayList args = new ArrayList(1); + args.add(result); + lir.callRuntime(CiRuntimeCall.UnwindException, CiValue.IllegalValue, args, null); + setNoResult(x); + } } diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/graph/BlockUtil.java --- a/graal/GraalCompiler/src/com/sun/c1x/graph/BlockUtil.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/BlockUtil.java Wed May 18 18:09:20 2011 +0200 @@ -22,12 +22,12 @@ */ package com.sun.c1x.graph; +import java.util.*; + import com.sun.c1x.ir.*; /** * The {@code BlockUtil} class contains a number of utilities for manipulating a CFG of basic blocks. - * - * @author Ben L. Titzer */ public class BlockUtil { @@ -36,11 +36,10 @@ * @param block the block to remove from the graph */ public static void disconnectFromGraph(BlockBegin block) { - for (BlockEnd p : block.blockPredecessors()) { - p.blockSuccessors().remove(block); + ArrayList preds = new ArrayList(block.blockPredecessors()); + for (Instruction p : preds) { + p.block().end().blockSuccessors().remove(block); } - for (BlockBegin s : block.end().blockSuccessors()) { - s.blockPredecessors().remove(block); - } + block.end().clearSuccessors(); } } diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java --- 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 newExceptionHandlers = new ArrayList(); + 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 handleException(Instruction x, int bci) { + private void handleException(Instruction x, int bci) { if (!hasHandler()) { - return ExceptionHandler.ZERO_HANDLERS; + return; } ArrayList exceptionHandlers = new ArrayList(); - 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 newBlocks = new ArrayList(); + + 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 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()); diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/graph/IR.java --- a/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java Wed May 18 18:09:20 2011 +0200 @@ -185,55 +185,16 @@ // link predecessor to new block source.end().substituteSuccessor(target, newSucc); - // The ordering needs to be the same, so remove the link that the - // set_end call above added and substitute the new_sux for this - // block. - target.removePredecessor(newSucc.end()); - - // the successor could be the target of a switch so it might have - // multiple copies of this predecessor, so substitute the new_sux - // for the first and delete the rest. - List list = target.blockPredecessors(); - int x = list.indexOf(source.end()); - list.set(x, newSucc.end()); - newSucc.addPredecessor(source.end()); - Iterator iterator = list.iterator(); - while (iterator.hasNext()) { - if (iterator.next() == source.end()) { - iterator.remove(); - newSucc.addPredecessor(source.end()); - } - } return newSucc; } public void replaceBlock(BlockBegin oldBlock, BlockBegin newBlock) { - assert !oldBlock.isExceptionEntry() : "cannot replace exception handler blocks (yet)"; - for (BlockBegin succ : oldBlock.end().blockSuccessors()) { - succ.removePredecessor(oldBlock.end()); - } - for (BlockEnd pred : oldBlock.blockPredecessors()) { + List predecessors = new ArrayList(oldBlock.blockPredecessors()); + for (Instruction pred : predecessors) { // substitute the new successor for this block in each predecessor - pred.substituteSuccessor(oldBlock, newBlock); - // and add each predecessor to the successor - newBlock.addPredecessor(pred); + pred.block().end().substituteSuccessor(oldBlock, newBlock); } - // this block is now disconnected; remove all its incoming and outgoing edges -// oldBlock.blockPredecessors().clear(); -// oldBlock.end().successors().clear(); - } - - /** - * Disconnects the specified block from all other blocks. - * @param block the block to remove from the graph - */ - public void disconnectFromGraph(BlockBegin block) { - for (BlockEnd p : block.blockPredecessors()) { - p.blockSuccessors().remove(block); - } - for (BlockBegin s : block.end().blockSuccessors()) { - s.blockPredecessors().remove(block); - } + oldBlock.end().clearSuccessors(); } public int nextBlockNumber() { diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/BlockBegin.java Wed May 18 18:09:20 2011 +0200 @@ -71,19 +71,7 @@ public void setEnd(BlockEnd end) { assert end != null; - BlockEnd old = this.end(); - if (old != end) { - if (old != null) { - // disconnect this block from its current successors - for (BlockBegin s : old.blockSuccessors()) { - s.blockPredecessors().remove(this.end()); - } - } - successors().set(super.successorCount() + SUCCESSOR_END, end); - for (BlockBegin s : end.blockSuccessors()) { - s.addPredecessor(end); - } - } + successors().set(super.successorCount() + SUCCESSOR_END, end); } private static final List NO_HANDLERS = Collections.emptyList(); @@ -93,7 +81,6 @@ */ public enum BlockFlag { StandardEntry, - ExceptionEntry, SubroutineEntry, BackwardBranchTarget, IsOnWorkList, @@ -117,19 +104,12 @@ */ private int blockFlags; - /** - * The {@link BlockBegin} nodes for which this node is a successor. - */ - private final List predecessors; - private int depthFirstNumber; private int linearScanNumber; private int loopDepth; private int loopIndex; private BlockBegin dominator; - private List exceptionHandlerBlocks; - private List exceptionHandlerStates; // LIR block public LIRBlock lirBlock; @@ -145,7 +125,6 @@ this.blockID = blockID; depthFirstNumber = -1; linearScanNumber = -1; - predecessors = new ArrayList(2); loopIndex = -1; setBCI(bci); } @@ -154,9 +133,13 @@ * Gets the list of predecessors of this block. * @return the predecessor list */ - public List blockPredecessors() { -// return Collections.unmodifiableList(predecessors); - return predecessors; + @SuppressWarnings({ "unchecked", "rawtypes" }) + public List blockPredecessors() { + if (predecessors().size() == 1 && predecessors().get(0) == graph().root()) { + return Collections.EMPTY_LIST; + } else { + return (List) Collections.unmodifiableList(predecessors()); + } } /** @@ -207,19 +190,6 @@ return loopIndex; } - /** - * Gets the exception handlers that cover one or more instructions of this basic block. - * - * @return the exception handlers - */ - public List exceptionHandlerBlocks() { - return exceptionHandlerBlocks == null ? NO_HANDLERS : exceptionHandlerBlocks; - } - - public List exceptionHandlerStates() { - return exceptionHandlerStates; - } - public void setDepthFirstNumber(int depthFirstNumber) { assert depthFirstNumber >= 0; this.depthFirstNumber = depthFirstNumber; @@ -288,10 +258,27 @@ BlockBegin block; while ((block = queue.poll()) != null) { closure.apply(block); - queueBlocks(queue, block.exceptionHandlerBlocks(), mark); + + Instruction inst = block; + ArrayList excBlocks = new ArrayList(); + while (inst != null) { + if (inst instanceof Invoke) { + excBlocks.add(((Invoke) inst).exceptionEdge()); + } else if (inst instanceof Throw) { + excBlocks.add(((Throw) inst).exceptionEdge()); + } + inst = inst.next(); + } + while (excBlocks.remove(null)) { + // nothing + } + if (excBlocks.size() > 0) { + queueBlocks(queue, excBlocks, mark); + } + queueBlocks(queue, block.end().blockSuccessors(), mark); if (predecessors) { - queueBlockEnds(queue, block.predecessors, mark); + queueBlockEnds(queue, block.blockPredecessors(), mark); } } } @@ -307,10 +294,10 @@ } } - private void queueBlockEnds(LinkedList queue, List list, IdentityHashMap mark) { + private void queueBlockEnds(LinkedList queue, List list, IdentityHashMap mark) { if (list != null) { - for (BlockEnd end : list) { - BlockBegin b = end.begin(); + for (Instruction end : list) { + BlockBegin b = end.block(); if (!mark.containsKey(b)) { queue.offer(b); mark.put(b, b); @@ -324,9 +311,27 @@ mark.put(this, this); closure.apply(this); BlockEnd e = end(); - if (exceptionHandlerBlocks != null) { - iterateReverse(mark, closure, exceptionHandlerBlocks); + + Instruction inst = this; + ArrayList excBlocks = new ArrayList(); + while (inst != null) { + if (inst instanceof Invoke) { + excBlocks.add(((Invoke) inst).exceptionEdge()); + } else if (inst instanceof Throw) { + excBlocks.add(((Throw) inst).exceptionEdge()); + } + inst = inst.next(); } + while (excBlocks.remove(null)) { + // nothing + } + if (excBlocks.size() > 0) { + iterateReverse(mark, closure, excBlocks); + } + +// if (exceptionHandlerBlocks != null) { +// iterateReverse(mark, closure, exceptionHandlerBlocks); +// } assert e != null : "block must have block end"; iterateReverse(mark, closure, e.blockSuccessors()); } @@ -338,58 +343,6 @@ } } - /** - * Adds an exception handler that covers one or more instructions in this block. - * - * @param handler the entry block for the exception handler to add - */ - public void addExceptionHandler(BlockBegin handler) { - assert handler != null && handler.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry); - if (exceptionHandlerBlocks == null) { - exceptionHandlerBlocks = new ArrayList(3); - exceptionHandlerBlocks.add(handler); - } else if (!exceptionHandlerBlocks.contains(handler)) { - exceptionHandlerBlocks.add(handler); - } - } - - /** - * Adds a frame state that merges into the exception handler whose entry is this block. - * - * @param state the frame state at an instruction that raises an exception that can be caught by the exception - * handler represented by this block - * @return the index of {@code state} in the list of frame states merging at this block (i.e. the frames states for - * all instruction throwing an exception caught by this exception handler) - */ - public int addExceptionState(FrameState state) { - assert checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry); - if (exceptionHandlerStates == null) { - exceptionHandlerStates = new ArrayList(4); - } - exceptionHandlerStates.add(state); - return exceptionHandlerStates.size() - 1; - } - - /** - * Add a predecessor to this block. - * @param pred the predecessor to add - */ - public void addPredecessor(BlockEnd pred) { - assert pred != null; - predecessors.add(pred); - } - - /** - * Removes all occurrences of the specified block from the predecessor list of this block. - * @param pred the predecessor to remove - */ - public void removePredecessor(BlockEnd pred) { - while (predecessors.remove(pred)) { - // the block may appear multiple times in the list - // XXX: this is not very efficient, consider Util.removeAllFromList - } - } - @Override public void accept(ValueVisitor v) { v.visitBlockBegin(this); @@ -409,7 +362,7 @@ FrameState duplicate = newState.duplicate(bci()); assert duplicate.bci == bci() : "duplicate.bci=" + duplicate.bci + " my bci=" + bci(); - if (C1XOptions.UseStackMapTableLiveness) { + if (C1XOptions.UseStackMapTableLiveness && method != null) { // if a liveness map is available, use it to invalidate dead locals CiBitMap[] livenessMap = method.livenessMap(); if (livenessMap != null && bci() >= 0) { @@ -489,14 +442,6 @@ setBlockFlag(BlockFlag.CriticalEdgeSplit, value); } - public boolean isExceptionEntry() { - return checkBlockFlag(BlockFlag.ExceptionEntry); - } - - public void setExceptionEntry() { - setBlockFlag(BlockFlag.ExceptionEntry); - } - public boolean isSubroutineEntry() { return checkBlockFlag(BlockFlag.SubroutineEntry); } @@ -556,7 +501,6 @@ public void copyBlockFlags(BlockBegin other) { copyBlockFlag(other, BlockBegin.BlockFlag.ParserLoopHeader); copyBlockFlag(other, BlockBegin.BlockFlag.SubroutineEntry); - copyBlockFlag(other, BlockBegin.BlockFlag.ExceptionEntry); copyBlockFlag(other, BlockBegin.BlockFlag.WasVisited); } @@ -619,8 +563,12 @@ * @return the number of predecessors */ public int numberOfPreds() { -// assert predecessors.size() == predecessors().size(); - return predecessors.size(); + // ignore the graph root + if (predecessors().size() == 1 && predecessors().get(0) == graph().root()) { + return 0; + } else { + return predecessors().size(); + } } /** @@ -645,25 +593,16 @@ return lirBlock; } - public int exceptionHandlerPco() { - return lirBlock == null ? 0 : lirBlock.exceptionHandlerPCO; - } - - public void setExceptionHandlerPco(int codeOffset) { - lirBlock().exceptionHandlerPCO = codeOffset; + public int blockEntryPco() { + return lirBlock == null ? 0 : lirBlock.blockEntryPco; } - public int numberOfExceptionHandlers() { - return exceptionHandlerBlocks == null ? 0 : exceptionHandlerBlocks.size(); + public void setBlockEntryPco(int codeOffset) { + lirBlock().blockEntryPco = codeOffset; } - public BlockBegin exceptionHandlerAt(int i) { - return exceptionHandlerBlocks.get(i); - } - - public BlockEnd predAt(int j) { -// assert predecessors.get(j) == predecessors().get(j); - return predecessors.get(j); + public Instruction predAt(int j) { + return (Instruction) predecessors().get(j); } public int firstLirInstructionId() { @@ -682,9 +621,8 @@ lirBlock.lastLirInstructionID = lastLirInstructionId; } - public boolean isPredecessor(BlockEnd block) { -// assert predecessors.contains(block) == predecessors().contains(block); - return predecessors.contains(block); + public boolean isPredecessor(Instruction block) { + return predecessors().contains(block); } public void printWithoutPhis(LogStream out) { @@ -694,9 +632,6 @@ // print flags StringBuilder sb = new StringBuilder(8); - if (isExceptionEntry()) { - sb.append('E'); - } if (isSubroutineEntry()) { sb.append('s'); } @@ -723,14 +658,6 @@ out.print(" B").print(successor.blockID); } } - // print exception handlers - if (!exceptionHandlers().isEmpty()) { - out.print(" (xhandlers"); - for (BlockBegin handler : exceptionHandlerBlocks()) { - out.print(" B").print(handler.blockID); - } - out.print(')'); - } // print dominator block if (dominator() != null) { @@ -740,8 +667,8 @@ // print predecessors if (!blockPredecessors().isEmpty()) { out.print(" pred:"); - for (BlockEnd pred : blockPredecessors()) { - out.print(" B").print(pred.begin().blockID); + for (Instruction pred : blockPredecessors()) { + out.print(" B").print(pred.block().blockID); } } } @@ -874,5 +801,34 @@ return "BlockBegin #" + blockID; } + /** + * Iterates over all successors of this block: successors of the end node and exception handler. + */ + public void allSuccessorsDo(boolean backwards, BlockClosure closure) { + if (backwards) { + for (int i = numberOfSux() - 1; i >= 0; i--) { + closure.apply(suxAt(i)); + } + } else { + for (int i = 0; i < numberOfSux(); i++) { + closure.apply(suxAt(i)); + } + } + for (Instruction x = next(); x != null; x = x.next()) { + if (x instanceof Invoke && ((Invoke) x).exceptionEdge() != null) { + closure.apply(((Invoke) x).exceptionEdge()); + } else if (x instanceof Throw && ((Throw) x).exceptionEdge() != null) { + closure.apply(((Throw) x).exceptionEdge()); + } + } + } + + public void verifyPredecessors() { + for (int i = 0; i < numberOfPreds(); i++) { + predAt(i); + } + + } + } diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java Wed May 18 18:09:20 2011 +0200 @@ -181,10 +181,16 @@ * Gets this block end's list of successors. * @return the successor list */ - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "rawtypes"}) public List blockSuccessors() { List list = (List) successors().subList(super.successorCount() + SUCCESSOR_COUNT, super.successorCount() + blockSuccessorCount + SUCCESSOR_COUNT); return Collections.unmodifiableList(list); } + public void clearSuccessors() { + for (int i = 0; i < blockSuccessorCount(); i++) { + setBlockSuccessor(i, null); + } + } + } diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/ir/ComputeLinearScanOrder.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/ComputeLinearScanOrder.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ComputeLinearScanOrder.java Wed May 18 18:09:20 2011 +0200 @@ -140,7 +140,7 @@ * 3. Number loop header blocks. * 4. Create a list with all loop end blocks. */ - private void countEdges(BlockBegin cur, BlockBegin parent) { + private void countEdges(final BlockBegin cur, BlockBegin parent) { if (C1XOptions.TraceLinearScanLevel >= 3) { TTY.println("Counting edges for block B%d%s", cur.blockID, parent == null ? "" : " coming from B" + parent.blockID); } @@ -158,15 +158,6 @@ parent.setBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd); - // When a loop header is also the start of an exception handler, then the backward branch is - // an exception edge. Because such edges are usually critical edges which cannot be split, the - // loop must be excluded here from processing. - if (cur.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) { - // Make sure that dominators are correct in this weird situation - iterativeDominators = true; - return; - } - loopEndBlocks.add(parent); return; } @@ -186,13 +177,11 @@ setActive(cur); // recursive call for all successors - int i; - for (i = cur.numberOfSux() - 1; i >= 0; i--) { - countEdges(cur.suxAt(i), cur); - } - for (i = cur.numberOfExceptionHandlers() - 1; i >= 0; i--) { - countEdges(cur.exceptionHandlerAt(i), cur); - } + cur.allSuccessorsDo(true, new BlockClosure() { + public void apply(BlockBegin block) { + countEdges(block, cur); + } + }); clearActive(cur); @@ -250,7 +239,7 @@ // recursive processing of all predecessors ends when start block of loop is reached if (cur != loopStart) { for (int j = cur.numberOfPreds() - 1; j >= 0; j--) { - BlockBegin pred = cur.predAt(j).begin(); + BlockBegin pred = cur.predAt(j).block(); if (!isBlockInLoop(loopIdx, pred)) { // this predecessor has not been processed yet, so add it to work list @@ -319,12 +308,11 @@ cur.setLoopIndex(minLoopIdx); // append all unvisited successors to work list - for (i = cur.numberOfSux() - 1; i >= 0; i--) { - workList.add(cur.suxAt(i)); - } - for (i = cur.numberOfExceptionHandlers() - 1; i >= 0; i--) { - workList.add(cur.exceptionHandlerAt(i)); - } + cur.allSuccessorsDo(true, new BlockClosure() { + public void apply(BlockBegin block) { + workList.add(block); + } + }); } } while (!workList.isEmpty()); } @@ -352,12 +340,7 @@ if (C1XOptions.TraceLinearScanLevel >= 4) { TTY.println("DOM: initializing dominator of B%d to B%d", cur.blockID, parent.blockID); } - if (cur.isExceptionEntry()) { - assert parent.dominator() != null; - cur.setDominator(parent.dominator()); - } else { - cur.setDominator(parent); - } + cur.setDominator(parent); } else if (!(cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) && parent.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd))) { if (C1XOptions.TraceLinearScanLevel >= 4) { @@ -412,10 +395,10 @@ } curBit--; - // exceptions handlers are added as late as possible - if (!cur.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) { - weight |= (1 << curBit); - } +// // exceptions handlers are added as late as possible +// if (!cur.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) { +// weight |= (1 << curBit); +// } curBit--; // guarantee that weight is > 0 @@ -505,27 +488,17 @@ } do { - BlockBegin cur = workList.remove(workList.size() - 1); + final BlockBegin cur = workList.remove(workList.size() - 1); appendBlock(cur); - int i; - int numSux = cur.numberOfSux(); - // changed loop order to get "intuitive" order of if- and else-blocks - for (i = 0; i < numSux; i++) { - BlockBegin sux = cur.suxAt(i); - computeDominator(sux, cur); - if (readyForProcessing(sux)) { - sortIntoWorkList(sux); + cur.allSuccessorsDo(false, new BlockClosure() { + public void apply(BlockBegin block) { + computeDominator(block, cur); + if (readyForProcessing(block)) { + sortIntoWorkList(block); + } } - } - numSux = cur.numberOfExceptionHandlers(); - for (i = 0; i < numSux; i++) { - BlockBegin sux = cur.exceptionHandlerAt(i); - computeDominator(sux, cur); - if (readyForProcessing(sux)) { - sortIntoWorkList(sux); - } - } + }); } while (workList.size() > 0); } @@ -539,17 +512,11 @@ BlockBegin block = linearScanOrder.get(i); assert block.numberOfPreds() > 0; - BlockBegin dominator = block.predAt(0).begin(); - if (block.isExceptionEntry()) { - dominator = dominator.dominator(); - } + BlockBegin dominator = block.predAt(0).block(); int numPreds = block.numberOfPreds(); for (int j = 1; j < numPreds; j++) { - BlockBegin curPred = block.predAt(j).begin(); - if (block.isExceptionEntry()) { - curPred = curPred.dominator(); - } + BlockBegin curPred = block.predAt(j).block(); dominator = commonDominator(dominator, curPred); } @@ -601,7 +568,6 @@ for (BlockBegin cur : linearScanOrder) { TTY.print(String.format("%4d: B%02d loop: %2d depth: %2d", cur.linearScanNumber(), cur.blockID, cur.loopIndex(), cur.loopDepth())); - TTY.print(cur.isExceptionEntry() ? " ex" : " "); TTY.print(cur.isCriticalEdgeSplit() ? " ce" : " "); TTY.print(cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) ? " lh" : " "); TTY.print(cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd) ? " le" : " "); @@ -615,7 +581,7 @@ if (cur.numberOfPreds() > 0) { TTY.print(" preds: "); for (int j = 0; j < cur.numberOfPreds(); j++) { - BlockBegin pred = cur.predAt(j).begin(); + BlockBegin pred = cur.predAt(j).block(); TTY.print("B%d ", pred.blockID); } } @@ -626,13 +592,6 @@ TTY.print("B%d ", sux.blockID); } } - if (cur.numberOfExceptionHandlers() > 0) { - TTY.print(" ex: "); - for (int j = 0; j < cur.numberOfExceptionHandlers(); j++) { - BlockBegin ex = cur.exceptionHandlerAt(j); - TTY.print("B%d ", ex.blockID); - } - } TTY.println(); } } @@ -666,8 +625,8 @@ } } - for (BlockEnd pred : cur.blockPredecessors()) { - BlockBegin begin = pred.begin(); + for (Instruction pred : cur.blockPredecessors()) { + BlockBegin begin = pred.block(); assert begin.linearScanNumber() >= 0 && begin.linearScanNumber() == linearScanOrder.indexOf(begin) : "incorrect linearScanNumber"; if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) { assert cur.linearScanNumber() > begin.linearScanNumber() : "invalid order"; @@ -685,7 +644,7 @@ } else { assert cur.dominator() != null : "all but first block must have dominator"; } - assert cur.numberOfPreds() != 1 || cur.dominator() == cur.predAt(0).begin() || cur.isExceptionEntry() : "Single predecessor must also be dominator"; + assert cur.numberOfPreds() != 1 || cur.dominator() == cur.predAt(0).block() : "Single predecessor must also be dominator"; } // check that all loops are continuous diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/ir/ExceptionDispatch.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ExceptionDispatch.java Wed May 18 18:09:20 2011 +0200 @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.c1x.ir; + +import com.oracle.graal.graph.*; +import com.sun.c1x.debug.*; +import com.sun.c1x.value.*; +import com.sun.cri.ci.*; + +/** + * This instruction takes an exception object and has two successors: + * The catchSuccessor is called whenever the exception matches the given type, otherwise otherSuccessor is called. + */ +public final class ExceptionDispatch extends BlockEnd { + + private static final int INPUT_COUNT = 1; + private static final int INPUT_EXCEPTION = 0; + + private static final int SUCCESSOR_COUNT = 0; + + @Override + protected int inputCount() { + return super.inputCount() + INPUT_COUNT; + } + + @Override + protected int successorCount() { + return super.successorCount() + SUCCESSOR_COUNT; + } + + /** + * The instruction producing the exception object. + */ + public Value exception() { + return (Value) inputs().get(super.inputCount() + INPUT_EXCEPTION); + } + + public Value setException(Value n) { + return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n); + } + + private final ExceptionHandler handler; + + /** + * Constructs a new ExceptionDispatch instruction. + */ + public ExceptionDispatch(Value exception, BlockBegin catchSuccessor, BlockBegin otherSuccessor, ExceptionHandler handler, FrameState stateAfter, boolean isSafepoint, Graph graph) { + super(CiKind.Int, stateAfter, isSafepoint, 2, INPUT_COUNT, SUCCESSOR_COUNT, graph); + setException(exception); + setBlockSuccessor(0, otherSuccessor); + setBlockSuccessor(1, catchSuccessor); + this.handler = handler; + } + + public ExceptionHandler handler() { + return handler; + } + + /** + * Gets the block corresponding to the catch block. + * @return the true successor + */ + public BlockBegin catchSuccessor() { + return blockSuccessor(1); + } + + /** + * Gets the block corresponding to the rest of the dispatch chain. + * @return the false successor + */ + public BlockBegin otherSuccessor() { + return blockSuccessor(0); + } + + /** + * Gets the block corresponding to the specified outcome of the branch. + * @param istrue {@code true} if the true successor is requested, {@code false} otherwise + * @return the corresponding successor + */ + public BlockBegin successor(boolean istrue) { + return blockSuccessor(istrue ? 1 : 0); + } + + /** + * Swaps the successor blocks to this if and negates the condition (e.g. == goes to !=) + * @see Condition#negate() + */ + public void swapSuccessors() { + BlockBegin t = blockSuccessor(0); + BlockBegin f = blockSuccessor(1); + setBlockSuccessor(0, f); + setBlockSuccessor(1, t); + } + + @Override + public void accept(ValueVisitor v) { + v.visitExceptionDispatch(this); + } + + @Override + public void print(LogStream out) { + out.print("exception_dispatch "). + print(exception()). + print(' '). + print("instanceof"). + print(' '). + print(handler.handler.catchType().name()). + print(" then B"). + print(blockSuccessors().get(1).blockID). + print(" else B"). + print(blockSuccessors().get(0).blockID); + if (isSafepoint()) { + out.print(" (safepoint)"); + } + } + + @Override + public String shortName() { + return "Dispatch " + handler.handler.catchType().name(); + } + + +} diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java Wed May 18 18:09:20 2011 +0200 @@ -79,11 +79,6 @@ */ private int bci; - /** - * List of associated exception handlers. - */ - private List exceptionHandlers = ExceptionHandler.ZERO_HANDLERS; - private boolean isAppended = false; /** @@ -185,22 +180,6 @@ } /** - * Gets the list of exception handlers associated with this instruction. - * @return the list of exception handlers for this instruction - */ - public final List exceptionHandlers() { - return exceptionHandlers; - } - - /** - * Sets the list of exception handlers for this instruction. - * @param exceptionHandlers the exception handlers - */ - public final void setExceptionHandlers(List exceptionHandlers) { - this.exceptionHandlers = exceptionHandlers; - } - - /** * Compute the value number of this Instruction. Local and global value numbering * optimizations use a hash map, and the value number provides a hash code. * If the instruction cannot be value numbered, then this method should return @@ -247,4 +226,8 @@ public FrameState stateAfter() { return null; } + + public BlockBegin exceptionEdge() { + return null; + } } diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/ir/Invoke.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Invoke.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Invoke.java Wed May 18 18:09:20 2011 +0200 @@ -36,7 +36,8 @@ private final int argumentCount; - private static final int SUCCESSOR_COUNT = 0; + private static final int SUCCESSOR_COUNT = 1; + private static final int SUCCESSOR_EXCEPTION_EDGE = 0; @Override protected int inputCount() { @@ -65,6 +66,18 @@ return argumentCount; } + /** + * The entry to the exception dispatch chain for this invoke. + */ + @Override + public BlockBegin exceptionEdge() { + return (BlockBegin) successors().get(super.successorCount() + SUCCESSOR_EXCEPTION_EDGE); + } + + public BlockBegin setExceptionEdge(BlockBegin n) { + return (BlockBegin) successors().set(super.successorCount() + SUCCESSOR_EXCEPTION_EDGE, n); + } + public final int opcode; public final RiMethod target; public final RiType returnType; diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java Wed May 18 18:09:20 2011 +0200 @@ -116,13 +116,7 @@ * @return the instruction that produced the value in the i'th predecessor */ public Value inputAt(int i) { - FrameState state; - if (block().isExceptionEntry()) { - state = block().exceptionHandlerStates().get(i); - } else { - state = block().blockPredecessors().get(i).stateAfter(); - } - return inputIn(state); + return inputIn(block().blockPredecessors().get(i).stateAfter()); } /** @@ -143,11 +137,7 @@ * @return the number of inputs in this phi */ public int phiInputCount() { - if (block().isExceptionEntry()) { - return block().exceptionHandlerStates().size(); - } else { - return block().blockPredecessors().size(); - } + return block().blockPredecessors().size(); } @Override @@ -170,7 +160,7 @@ @Override public String shortName() { - return "Phi: " + index; + return "Phi: " + index + " (" + phiInputCount() + ")"; } diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/StateSplit.java Wed May 18 18:09:20 2011 +0200 @@ -32,11 +32,11 @@ */ public abstract class StateSplit extends Instruction { - private static final int INPUT_COUNT = 2; - private static final int INPUT_STATE_AFTER = 0; - private static final int INPUT_STATE_BEFORE = 1; + private static final int INPUT_COUNT = 1; + private static final int INPUT_STATE_BEFORE = 0; - private static final int SUCCESSOR_COUNT = 0; + private static final int SUCCESSOR_COUNT = 1; + private static final int SUCCESSOR_STATE_AFTER = 0; @Override protected int inputCount() { @@ -51,22 +51,6 @@ /** * The state for this instruction. */ - @Override - public FrameState stateAfter() { - return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_AFTER); - } - - public FrameState setStateAfter(FrameState n) { - if (n != null && this instanceof BlockBegin) { - Exception e = new Exception(); - e.printStackTrace(); - } - return (FrameState) inputs().set(super.inputCount() + INPUT_STATE_AFTER, n); - } - - /** - * The state for this instruction. - */ public FrameState stateBefore() { return (FrameState) inputs().get(super.inputCount() + INPUT_STATE_BEFORE); } @@ -76,6 +60,18 @@ } /** + * The state for this instruction. + */ + @Override + public FrameState stateAfter() { + return (FrameState) successors().get(super.successorCount() + SUCCESSOR_STATE_AFTER); + } + + public FrameState setStateAfter(FrameState n) { + return (FrameState) successors().set(super.successorCount() + SUCCESSOR_STATE_AFTER, n); + } + + /** * Creates a new state split with the specified value type. * @param kind the type of the value that this instruction produces * @param inputCount diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/ir/Throw.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Throw.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Throw.java Wed May 18 18:09:20 2011 +0200 @@ -36,7 +36,8 @@ private static final int INPUT_EXCEPTION = 0; private static final int INPUT_STATE_BEFORE = 1; - private static final int SUCCESSOR_COUNT = 0; + private static final int SUCCESSOR_COUNT = 1; + private static final int SUCCESSOR_EXCEPTION_EDGE = 0; @Override protected int inputCount() { @@ -71,6 +72,19 @@ } /** + * The entry to the exception dispatch chain for this throw. + * TODO ls: this needs more cleanup - throw should either unwind or jump to the exception dispatch chain + */ + @Override + public BlockBegin exceptionEdge() { + return (BlockBegin) successors().get(super.successorCount() + SUCCESSOR_EXCEPTION_EDGE); + } + + public BlockBegin setExceptionEdge(BlockBegin n) { + return (BlockBegin) successors().set(super.successorCount() + SUCCESSOR_EXCEPTION_EDGE, n); + } + + /** * Creates a new Throw instruction. * @param exception the instruction that generates the exception to throw * @param stateAfter the state before the exception is thrown but after the exception object has been popped diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/ir/Unwind.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Unwind.java Wed May 18 18:09:20 2011 +0200 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.c1x.ir; + +import com.oracle.graal.graph.*; +import com.sun.c1x.debug.*; +import com.sun.cri.ci.*; + +/** + * Unwind takes an exception object, destroys the current stack frame and passes the exception object to the system's exception dispatch code. + */ +public final class Unwind extends BlockEnd { + + private static final int INPUT_COUNT = 1; + private static final int INPUT_EXCEPTION = 0; + + private static final int SUCCESSOR_COUNT = 0; + + @Override + protected int inputCount() { + return super.inputCount() + INPUT_COUNT; + } + + @Override + protected int successorCount() { + return super.successorCount() + SUCCESSOR_COUNT; + } + + /** + * The instruction that produces the exception object. + */ + public Value exception() { + return (Value) inputs().get(super.inputCount() + INPUT_EXCEPTION); + } + + public Value setException(Value n) { + assert n == null || n.kind == CiKind.Object; + return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n); + } + + public Unwind(Value exception, boolean isSafepoint, Graph graph) { + super(CiKind.Object, null, isSafepoint, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph); + setException(exception); + } + + @Override + public void accept(ValueVisitor v) { + v.visitUnwind(this); + } + + @Override + public void print(LogStream out) { + out.print(kind.typeChar).print("unwind ").print(exception()); + } +} diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java Wed May 18 18:09:20 2011 +0200 @@ -68,4 +68,6 @@ public abstract void visitTableSwitch(TableSwitch i); public abstract void visitThrow(Throw i); public abstract void visitDeoptimize(Deoptimize deoptimize); + public abstract void visitExceptionDispatch(ExceptionDispatch exceptionDispatch); + public abstract void visitUnwind(Unwind unwind); } diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/lir/LIRAssembler.java --- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRAssembler.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRAssembler.java Wed May 18 18:09:20 2011 +0200 @@ -96,35 +96,6 @@ public abstract void emitTraps(); - public void emitExceptionEntries() { - if (tasm.exceptionInfoList == null) { - return; - } - for (ExceptionInfo ilist : tasm.exceptionInfoList) { - List handlers = ilist.exceptionHandlers; - - for (ExceptionHandler handler : handlers) { - assert handler.lirOpId() != -1 : "handler not processed by LinearScan"; - assert handler.entryCode() == null || handler.entryCode().instructionsList().get(handler.entryCode().instructionsList().size() - 1).code == LIROpcode.Branch : "last operation must be branch"; - - if (handler.entryCodeOffset() == -1) { - // entry code not emitted yet - if (handler.entryCode() != null && handler.entryCode().instructionsList().size() > 1) { - handler.setEntryCodeOffset(codePos()); - if (C1XOptions.CommentedAssembly) { - tasm.blockComment("Exception adapter block"); - } - emitLirList(handler.entryCode()); - } else { - handler.setEntryCodeOffset(handler.entryBlock().exceptionHandlerPco()); - } - - assert handler.entryCodeOffset() != -1 : "must be set now"; - } - } - } - } - public void emitCode(List hir) { if (C1XOptions.PrintLIR && !TTY.isSuppressed()) { LIRList.printLIR(hir); @@ -142,12 +113,7 @@ emitAlignment(); } - // if this block is the start of an exception handler, record the - // PC offset of the first instruction for later construction of - // the ExceptionHandlerTable - if (block.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) { - block.setExceptionHandlerPco(codePos()); - } + block.setBlockEntryPco(codePos()); if (C1XOptions.PrintLIRWithAssembly) { block.printWithoutPhis(TTY.out()); diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/lir/LIRBlock.java --- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRBlock.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRBlock.java Wed May 18 18:09:20 2011 +0200 @@ -28,8 +28,6 @@ /** * The {@code LIRBlock} class definition. - * - * @author Ben L. Titzer */ public final class LIRBlock { @@ -70,7 +68,7 @@ public int firstLirInstructionID; public int lastLirInstructionID; - public int exceptionHandlerPCO; + public int blockEntryPco; public LIRList lir() { return lir; diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/lir/LIRDebugInfo.java --- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRDebugInfo.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRDebugInfo.java Wed May 18 18:09:20 2011 +0200 @@ -31,10 +31,6 @@ /** * This class represents debugging and deoptimization information attached to a LIR instruction. - * - * @author Marcelo Cintra - * @author Thomas Wuerthinger - * @author Ben L. Titzer */ public class LIRDebugInfo { @@ -43,27 +39,18 @@ } public final FrameState state; - public final List exceptionHandlers; + public final BlockBegin exceptionEdge; public CiDebugInfo debugInfo; - public LIRDebugInfo(FrameState state, List exceptionHandlers) { + public LIRDebugInfo(FrameState state, BlockBegin exceptionEdge) { assert state != null; this.state = state; - this.exceptionHandlers = exceptionHandlers; + this.exceptionEdge = exceptionEdge; } private LIRDebugInfo(LIRDebugInfo info) { this.state = info.state; - - // deep copy of exception handlers - if (info.exceptionHandlers != null) { - this.exceptionHandlers = new ArrayList(info.exceptionHandlers.size()); - for (ExceptionHandler h : info.exceptionHandlers) { - this.exceptionHandlers.add(new ExceptionHandler(h)); - } - } else { - this.exceptionHandlers = null; - } + this.exceptionEdge = info.exceptionEdge; } public LIRDebugInfo copy() { diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/lir/LIRInstruction.java --- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRInstruction.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRInstruction.java Wed May 18 18:09:20 2011 +0200 @@ -483,12 +483,8 @@ } } - public final List exceptionEdges() { - if (info != null && info.exceptionHandlers != null) { - return info.exceptionHandlers; - } - - return Collections.emptyList(); + public final BlockBegin exceptionEdge() { + return info.exceptionEdge; } @Override diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/lir/LIRList.java --- a/graal/GraalCompiler/src/com/sun/c1x/lir/LIRList.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/lir/LIRList.java Wed May 18 18:09:20 2011 +0200 @@ -411,9 +411,6 @@ TTY.print("B%d ", x.blockID); // print flags - if (x.checkBlockFlag(BlockBegin.BlockFlag.ExceptionEntry)) { - TTY.print("ex "); - } if (x.checkBlockFlag(BlockBegin.BlockFlag.SubroutineEntry)) { TTY.print("jsr "); } @@ -434,7 +431,7 @@ if (x.numberOfPreds() > 0) { TTY.print("preds: "); for (int i = 0; i < x.numberOfPreds(); i++) { - TTY.print("B%d ", x.predAt(i).begin().blockID); + TTY.print("B%d ", x.predAt(i).block().blockID); } } @@ -445,14 +442,6 @@ } } - // print exception handlers - if (x.numberOfExceptionHandlers() > 0) { - TTY.print("xhandler: "); - for (int i = 0; i < x.numberOfExceptionHandlers(); i++) { - TTY.print("B%d ", x.exceptionHandlerAt(i).blockID); - } - } - TTY.println(); } diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/opt/InstructionSubstituter.java --- a/graal/GraalCompiler/src/com/sun/c1x/opt/InstructionSubstituter.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/opt/InstructionSubstituter.java Wed May 18 18:09:20 2011 +0200 @@ -42,11 +42,6 @@ public void apply(BlockBegin block) { Instruction last = null; - if (block.exceptionHandlerStates() != null) { - for (FrameState s : block.exceptionHandlerStates()) { - s.inputValuesDo(this); - } - } for (Instruction n = block; n != null; n = last.next()) { n.allValuesDo(this); if (n.subst != null && last != null) { diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java --- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java Wed May 18 18:09:20 2011 +0200 @@ -33,6 +33,9 @@ import com.sun.c1x.util.*; import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; +import com.sun.cri.ri.*; +import com.sun.cri.ri.RiType.*; +import com.sun.cri.xir.*; /** * This class implements the X86-specific portion of the LIR generator. @@ -518,4 +521,23 @@ assert x.defaultSuccessor() == x.falseSuccessor() : "wrong destination above"; lir.jump(x.defaultSuccessor()); } + + @Override + public void visitExceptionDispatch(ExceptionDispatch x) { + // TODO ls: this needs some more work... + + RiType riType = x.handler().handler.catchType(); + assert riType.isResolved(); + + XirArgument obj = toXirArgument(x.exception()); + XirArgument clazz = toXirArgument(riType.getEncoding(Representation.ObjectHub)); + XirSnippet snippet = xir.genInstanceOf(site(x), obj, clazz, riType); + CiValue result = emitXir(snippet, x, stateFor(x), null, true); + + lir.cmp(Condition.EQ, result, CiConstant.TRUE); + lir.branch(Condition.EQ, CiKind.Boolean, x.catchSuccessor()); + + lir.jump(x.otherSuccessor()); + } + } diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java --- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java Wed May 18 18:09:20 2011 +0200 @@ -105,7 +105,8 @@ /** * Gets a copy of this frame state without the stack. */ - public FrameState duplicateWithEmptyStack() { + @Override + public FrameState duplicateWithEmptyStack(int bci) { FrameState other = new FrameState(bci, localsSize, 0, locksSize(), graph()); for (int i = 0; i < localsSize; i++) { other.inputs().set(i, localAt(i)); diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/value/FrameStateAccess.java --- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateAccess.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateAccess.java Wed May 18 18:09:20 2011 +0200 @@ -42,4 +42,6 @@ Value stackAt(int i); + FrameState duplicateWithEmptyStack(int bci); + } diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java --- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java Wed May 18 18:09:20 2011 +0200 @@ -95,6 +95,11 @@ return new FrameState(bci, locals, stack, stackIndex, locks, graph); } + @Override + public FrameState duplicateWithEmptyStack(int bci) { + return new FrameState(bci, locals, new Value[0], 0, locks, graph); + } + /** * Pushes an instruction onto the stack with the expected type. * @param kind the type expected for this instruction diff -r 0ea5f12e873a -r 7ed72769d51a graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java --- a/graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java Fri May 13 17:09:20 2011 -0700 +++ b/graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java Wed May 18 18:09:20 2011 +0200 @@ -25,7 +25,6 @@ import java.awt.Color; import java.io.OutputStream; import java.io.PrintStream; -import java.util.HashMap; import java.util.HashSet; import com.oracle.graal.graph.Graph; @@ -130,49 +129,54 @@ } private void printNode(String name, String label, int ninputs, int nsuccessors) { + int minWidth = Math.min(label.length() / 3, 10); + minWidth = Math.max(minWidth, Math.max(ninputs + 1, nsuccessors + 1)); out.println(name + " [shape=plaintext,"); - out.println(" label=< "); - out.println(" "); - } + private void printPort(String name, String color) { + out.print(" "); + } - out.println("
"); - out.println(" "); - out.println("
"); - out.println("
"); + out.println(" label=<
"); - if ((ninputs == 1 && nsuccessors == 1) || (ninputs == 0 && nsuccessors == 0)) { - out.println(" "); - } + printPort("predecessors", "rosybrown1"); - for (int i = 0; i < nsuccessors - ninputs; i++) { - out.println(" "); + for (int i = 1; i < minWidth - ninputs; i++) { + printEmptyPort(); } for (int i = 0; i < ninputs; i++) { - out.println(" "); + printPort("in" + i, "lightgrey"); } label = label.replace("&", "&"); label = label.replace("<", "<"); label = label.replace(">", ">"); label = label.replace("\"", """); - out.println("
" + label + "
"); + out.println(" "); for (int i = 0; i < nsuccessors; i++) { - out.println(" "); + printPort("succ" + i, "rosybrown1"); + } + + for (int i = 1; i < minWidth - nsuccessors; i++) { + printEmptyPort(); } - for (int i = 0; i < ninputs - nsuccessors; i++) { - out.println(" "); - } + printPort("usages", "lightgrey"); + + out.println("
" + label + "
>]; "); + } - if ((ninputs == 1 && nsuccessors == 1) || (ninputs == 0 && nsuccessors == 0)) { - out.println("
"); - out.println("
>]; "); + private void printEmptyPort() { + out.print("
"); } private void printControlEdge(int from, int fromPort, int to) { - out.println("n" + from + ":succ" + fromPort + " -> n" + to + ":predecessors:n [color=red, weight=10];"); + out.println("n" + from + ":succ" + fromPort + " -> n" + to + ":predecessors:n [color=red, weight=2];"); } private void printDataEdge(int from, int fromPort, int to) { diff -r 0ea5f12e873a -r 7ed72769d51a graal/hotspot/hotspot Default.launch --- a/graal/hotspot/hotspot Default.launch Fri May 13 17:09:20 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -