Mercurial > hg > graal-jvmci-8
diff graal/GraalCompiler/src/com/sun/c1x/alloc/LinearScan.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 | 6ab73784566a |
children | 4272b7af2d17 |
line wrap: on
line diff
--- 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<LIRInstruction> 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<LIRInstruction> 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();