# HG changeset patch # User Thomas Wuerthinger # Date 1328416836 -3600 # Node ID ab7c258e1cefb541d423bb6c9b7c1db0a54dc4d7 # Parent 5d9c4796912d459ea573fdd2573cb570db9a516c# Parent 0312460af9fc052223bd5522ee685fa29a601e96 Merge. diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/xir/RiXirGenerator.java Sun Feb 05 05:40:36 2012 +0100 @@ -77,11 +77,11 @@ XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type); - XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type); + XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact); - XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type); + XirSnippet genInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact); - XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type); + XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument receiver, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type, RiResolvedType[] hints, boolean hintsExact); XirSnippet genArrayLoad(XirSite site, XirArgument array, XirArgument index, CiKind elementKind, RiType elementType); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java Sun Feb 05 05:40:36 2012 +0100 @@ -28,6 +28,7 @@ import com.oracle.max.criutils.*; import com.oracle.max.graal.alloc.util.*; import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; @@ -50,7 +51,7 @@ assert trace("==== start assign registers ===="); for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) { - LIRBlock block = lir.linearScanOrder().get(i); + Block block = lir.linearScanOrder().get(i); assert trace("start block %s", block); assert block.phis == null : "Register assignment must run after phi functions have been replaced by moves"; @@ -60,8 +61,8 @@ // Put all values live at the end of the block into the reference map. locationsForBlockEnd(block).forEachLocation(setReferenceProc); - for (int j = block.lir().size() - 1; j >= 0; j--) { - LIRInstruction op = block.lir().get(j); + for (int j = block.lir.size() - 1; j >= 0; j--) { + LIRInstruction op = block.lir.get(j); assert trace(" op %d %s", op.id(), op); op.forEachOutput(defProc); @@ -120,7 +121,7 @@ return value; } - protected abstract LocationMap locationsForBlockEnd(LIRBlock block); + protected abstract LocationMap locationsForBlockEnd(Block block); private static boolean trace(String format, Object...args) { if (GraalOptions.TraceRegisterAllocation) { diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java Sun Feb 05 05:40:36 2012 +0100 @@ -32,10 +32,10 @@ import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.alloc.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; -import com.oracle.max.graal.compiler.schedule.*; public class DataFlowAnalysis { private final LIR lir; @@ -52,7 +52,7 @@ } - private List blocks() { + private List blocks() { return lir.linearScanOrder(); } @@ -67,21 +67,21 @@ private int[] definitions; private BitSet[] blockLiveIn; - private LIRBlock[] opIdBlock; + private Block[] opIdBlock; private Object[] opIdKilledValues; public BitSet liveIn(Block block) { - return blockLiveIn[block.blockID()]; + return blockLiveIn[block.getId()]; } private void setLiveIn(Block block, BitSet liveIn) { - blockLiveIn[block.blockID()] = liveIn; + blockLiveIn[block.getId()] = liveIn; } - private LIRBlock blockOf(int opId) { + private Block blockOf(int opId) { return opIdBlock[opId >> 1]; } - private void setBlockOf(int opId, LIRBlock block) { + private void setBlockOf(int opId, Block block) { opIdBlock[opId >> 1] = block; } @@ -121,22 +121,20 @@ ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return setDef(value); } }; int numInstructions = 0; - for (LIRBlock block : blocks()) { - numInstructions += block.lir().size(); + for (Block block : blocks()) { + numInstructions += block.lir.size(); } - opIdBlock = new LIRBlock[numInstructions]; + opIdBlock = new Block[numInstructions]; opIdKilledValues = new Object[numInstructions << 1]; definitions = new int[numVariables()]; curOpId = 0; - for (LIRBlock block : blocks()) { - block.setFirstLirInstructionId(curOpId); - + for (Block block : blocks()) { if (block.phis != null) { block.phis.forEachOutput(defProc); } - for (LIRInstruction op : block.lir()) { + for (LIRInstruction op : block.lir) { op.setId(curOpId); setBlockOf(curOpId, block); @@ -145,7 +143,6 @@ curOpId += 2; // numbering of lirOps by two } - block.setLastLirInstructionId(curOpId - 2); } assert curOpId == numInstructions << 1; } @@ -175,11 +172,11 @@ assert trace("==== start backward data flow analysis ===="); for (int i = blocks().size() - 1; i >= 0; i--) { - LIRBlock block = blocks().get(i); - assert trace("start block %s loop %d depth %d", block, block.loopIndex(), block.loopDepth()); + Block block = blocks().get(i); + assert trace("start block %s loop %s", block, block.getLoop()); variableLive = new BitSet(); - for (LIRBlock sux : block.getLIRSuccessors()) { + for (Block sux : block.getSuccessors()) { BitSet suxLive = liveIn(sux); if (suxLive != null) { assert trace(" sux %s suxLive: %s", sux, suxLive); @@ -187,7 +184,7 @@ } if (sux.phis != null) { - curOpId = block.lastLirInstructionId(); + curOpId = block.getLastLirInstructionId(); assert trace(" phis %d variableLive: %s", curOpId, variableLive); sux.phis.forEachInput(block, phiInputProc); } @@ -195,8 +192,8 @@ assert registerLive.isEmpty() : "no fixed register must be alive before processing a block"; - for (int j = block.lir().size() - 1; j >= 0; j--) { - LIRInstruction op = block.lir().get(j); + for (int j = block.lir.size() - 1; j >= 0; j--) { + LIRInstruction op = block.lir.get(j); curOpId = op.id(); assert trace(" op %d %s variableLive: %s registerLive: %s", curOpId, op, variableLive, registerLive); @@ -208,7 +205,7 @@ } if (block.phis != null) { - curOpId = block.firstLirInstructionId(); + curOpId = block.getFirstLirInstructionId(); assert trace(" phis %d variableLive: %s registerLive: %s", curOpId, variableLive, registerLive); block.phis.forEachOutput(outputProc); } @@ -221,7 +218,7 @@ assert trace(" loop header, propagating live set to loop blocks variableLive: %s", variableLive); // All variables that are live at the beginning of a loop are also live the whole loop. // This is guaranteed by the SSA form. - for (Block loop : block.loopBlocks) { + for (Block loop : block.getLoop().blocks) { BitSet loopLiveIn = liveIn(loop); assert loopLiveIn != null : "All loop blocks must have been processed before the loop header"; loopLiveIn.or(variableLive); @@ -292,13 +289,13 @@ int defOpId = definitions[asVariable(value).index]; assert defOpId > 0 && defOpId <= opId; - LIRBlock defBlock = blockOf(defOpId); - LIRBlock useBlock = blockOf(opId); + Block defBlock = blockOf(defOpId); + Block useBlock = blockOf(opId); - if (useBlock.loopDepth() > 0 && useBlock.loopIndex() != defBlock.loopIndex()) { + if (useBlock.getLoop() != null && useBlock.getLoop() != defBlock.getLoop()) { // This is a value defined outside of the loop it is currently used in. Therefore, it is live the whole loop // and is not killed by the current instruction. - assert trace(" no kill because use in loop %d, definition in loop %d", useBlock.loopIndex(), defBlock.loopIndex()); + assert trace(" no kill because use in %s, definition in %s", useBlock.getLoop(), defBlock.getLoop()); return; } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java Sun Feb 05 05:40:36 2012 +0100 @@ -32,12 +32,12 @@ import com.oracle.max.criutils.*; import com.oracle.max.graal.alloc.util.*; import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; -import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.debug.*; @@ -85,12 +85,12 @@ } @Override - protected LocationMap locationsForBlockBegin(LIRBlock block) { + protected LocationMap locationsForBlockBegin(Block block) { return beginLocationsFor(block); } @Override - protected LocationMap locationsForBlockEnd(LIRBlock block) { + protected LocationMap locationsForBlockEnd(Block block) { return endLocationsFor(block); } } @@ -101,7 +101,7 @@ } @Override - protected LocationMap locationsForBlockEnd(LIRBlock block) { + protected LocationMap locationsForBlockEnd(Block block) { return endLocationsFor(block); } } @@ -119,19 +119,19 @@ private final LocationMap[] blockBeginLocations; private LocationMap beginLocationsFor(Block block) { - return blockBeginLocations[block.blockID()]; + return blockBeginLocations[block.getId()]; } private void setBeginLocationsFor(Block block, LocationMap locations) { - blockBeginLocations[block.blockID()] = locations; + blockBeginLocations[block.getId()] = locations; } private final LocationMap[] blockEndLocations; private LocationMap endLocationsFor(Block block) { - return blockEndLocations[block.blockID()]; + return blockEndLocations[block.getId()]; } private void setEndLocationsFor(Block block, LocationMap locations) { - blockEndLocations[block.blockID()] = locations; + blockEndLocations[block.getId()] = locations; } private final int[] variableLastUse; @@ -150,7 +150,7 @@ private CiValue[] curOutRegisterState; private BitSet curLiveIn; private int curOpId; - private LIRBlock curPhiBlock; + private Block curPhiBlock; private LocationMap canonicalSpillLocations; @@ -191,12 +191,12 @@ canonicalSpillLocations = new LocationMap(lir.numVariables()); curInRegisterState = new CiValue[maxRegisterNum()]; curOutRegisterState = new CiValue[maxRegisterNum()]; - for (LIRBlock block : lir.linearScanOrder()) { - assert trace("start block %s loop %d depth %d", block, block.loopIndex(), block.loopDepth()); + for (Block block : lir.linearScanOrder()) { + assert trace("start block %s %s", block, block.getLoop()); Arrays.fill(curOutRegisterState, null); - if (block.dominator() != null) { - LocationMap dominatorState = endLocationsFor(block.dominator()); + if (block.getDominator() != null) { + LocationMap dominatorState = endLocationsFor(block.getDominator()); curLocations = new LocationMap(dominatorState); // Clear out all variables that are not live at the begin of this block curLiveIn = dataFlow.liveIn(block); @@ -210,7 +210,7 @@ if (block.phis != null) { assert trace(" phis"); curPhiBlock = block; - curOpId = block.firstLirInstructionId(); + curOpId = block.getFirstLirInstructionId(); block.phis.forEachOutput(defProc); curOpId = -1; curPhiBlock = null; @@ -218,8 +218,8 @@ setBeginLocationsFor(block, new LocationMap(curLocations)); - for (int opIdx = 0; opIdx < block.lir().size(); opIdx++) { - LIRInstruction op = block.lir().get(opIdx); + for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) { + LIRInstruction op = block.lir.get(opIdx); curOpId = op.id(); assert trace(" op %d %s", op.id(), op); @@ -234,7 +234,7 @@ op.forEachInput(recordUseProc); op.forEachAlive(recordUseProc); - moveResolver.init(block.lir(), opIdx); + moveResolver.init(block.lir, opIdx); // Process Alive before Input because they are more restricted and the same variable can be Alive and Input. op.forEachAlive(useProc); op.forEachInput(useProc); @@ -263,11 +263,11 @@ curOpId = -1; } - for (LIRBlock sux : block.getLIRSuccessors()) { + for (Block sux : block.getSuccessors()) { if (sux.phis != null) { assert trace(" phis of successor %s", sux); System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length); - curOpId = block.lastLirInstructionId() + 1; + curOpId = block.getLastLirInstructionId() + 1; sux.phis.forEachInput(block, useProc); curOpId = -1; } @@ -463,6 +463,9 @@ } if (bestSpillCandidate == null) { + if (curPhiBlock != null) { + return selectSpillSlot(variable, mode); + } // This should not happen as long as all LIR instructions have fulfillable register constraints. But be safe in product mode and bail out. assert false; throw new CiBailout("No register available"); @@ -554,7 +557,7 @@ return loc; } - private boolean checkInputState(final LIRBlock block) { + private boolean checkInputState(final Block block) { final BitSet liveState = new BitSet(); curLocations.forEachLocation(new ValueProcedure() { @Override diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java Sun Feb 05 05:40:36 2012 +0100 @@ -30,6 +30,7 @@ import com.oracle.max.criutils.*; import com.oracle.max.graal.alloc.util.*; import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; @@ -46,7 +47,7 @@ this.dataFlow = dataFlow; } - private LIRBlock curToBlock; + private Block curToBlock; private LocationMap curFromLocations; public void execute() { @@ -54,10 +55,10 @@ PhiValueProcedure phiMappingProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue input, CiValue output) { return phiMapping(input, output); } }; assert trace("==== start resolve data flow ===="); - for (LIRBlock toBlock : lir.linearScanOrder()) { + for (Block toBlock : lir.linearScanOrder()) { curToBlock = toBlock; - for (LIRBlock fromBlock : toBlock.getLIRPredecessors()) { + for (Block fromBlock : toBlock.getPredecessors()) { assert trace("start edge %s -> %s", fromBlock, toBlock); findInsertPos(fromBlock, toBlock); @@ -98,18 +99,18 @@ return input; } - private void findInsertPos(LIRBlock fromBlock, LIRBlock toBlock) { + private void findInsertPos(Block fromBlock, Block toBlock) { assert fromBlock.getSuccessors().contains(toBlock) && toBlock.getPredecessors().contains(fromBlock); if (fromBlock.numberOfSux() == 1) { - List instructions = fromBlock.lir(); + List instructions = fromBlock.lir; LIRInstruction instr = instructions.get(instructions.size() - 1); assert instr instanceof StandardOp.JumpOp : "block does not end with an unconditional jump"; moveResolver.init(instructions, instructions.size() - 1); assert trace(" insert at end of %s before %d", fromBlock, instructions.size() - 1); } else if (toBlock.numberOfPreds() == 1) { - moveResolver.init(toBlock.lir(), 1); + moveResolver.init(toBlock.lir, 1); assert trace(" insert at beginning of %s before %d", toBlock, 1); } else { @@ -117,8 +118,8 @@ } } - protected abstract LocationMap locationsForBlockBegin(LIRBlock block); - protected abstract LocationMap locationsForBlockEnd(LIRBlock block); + protected abstract LocationMap locationsForBlockBegin(Block block); + protected abstract LocationMap locationsForBlockEnd(Block block); private static boolean trace(String format, Object...args) { diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java Sun Feb 05 05:40:36 2012 +0100 @@ -32,12 +32,12 @@ import com.oracle.max.criutils.*; import com.oracle.max.graal.alloc.util.*; import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; -import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.debug.*; @@ -80,13 +80,13 @@ } @Override - protected LocationMap locationsForBlockBegin(LIRBlock block) { - assert block.numberOfPreds() > 0 && block.dominator() != null; - return locationsFor(block.dominator()); + protected LocationMap locationsForBlockBegin(Block block) { + assert block.numberOfPreds() > 0 && block.getDominator() != null; + return locationsFor(block.getDominator()); } @Override - protected LocationMap locationsForBlockEnd(LIRBlock block) { + protected LocationMap locationsForBlockEnd(Block block) { return locationsFor(block); } } @@ -97,7 +97,7 @@ } @Override - protected LocationMap locationsForBlockEnd(LIRBlock block) { + protected LocationMap locationsForBlockEnd(Block block) { return locationsFor(block); } } @@ -115,10 +115,10 @@ private final LocationMap[] blockLocations; private LocationMap locationsFor(Block block) { - return blockLocations[block.blockID()]; + return blockLocations[block.getId()]; } private void setLocationsFor(Block block, LocationMap locations) { - blockLocations[block.blockID()] = locations; + blockLocations[block.getId()] = locations; } private MoveResolver moveResolver; @@ -168,12 +168,12 @@ curInRegisterState = new Object[maxRegisterNum()]; curOutRegisterState = new Object[maxRegisterNum()]; curRegisterLocations = new LocationMap(lir.numVariables()); - for (LIRBlock block : lir.linearScanOrder()) { - assert trace("start block %s loop %d depth %d", block, block.loopIndex(), block.loopDepth()); + for (Block block : lir.linearScanOrder()) { + assert trace("start block %s %s", block, block.getLoop()); assert checkEmpty(curOutRegisterState); - if (block.dominator() != null) { - LocationMap dominatorState = locationsFor(block.dominator()); + if (block.getDominator() != null) { + LocationMap dominatorState = locationsFor(block.getDominator()); curStackLocations = new LocationMap(dominatorState); // Clear out all variables that are not live at the begin of this block curLiveIn = dataFlow.liveIn(block); @@ -189,8 +189,8 @@ block.phis.forEachOutput(defSlotProc); } - for (int opIdx = 0; opIdx < block.lir().size(); opIdx++) { - LIRInstruction op = block.lir().get(opIdx); + for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) { + LIRInstruction op = block.lir.get(opIdx); curInstruction = op; assert trace(" op %d %s", op.id(), op); @@ -202,7 +202,7 @@ op.forEachTemp(blockProc); op.forEachOutput(blockProc); - moveResolver.init(block.lir(), opIdx); + moveResolver.init(block.lir, opIdx); // Process Alive before Input because they are more restricted and the same variable can be Alive and Input. op.forEachAlive(loadProc); op.forEachInput(loadProc); @@ -212,7 +212,7 @@ dataFlow.forEachKilled(op, false, killBeginProc); assert !op.hasCall() || checkNoCallerSavedRegister() : "caller saved register in use accross call site"; - moveResolver.init(block.lir(), opIdx + 1); + moveResolver.init(block.lir, opIdx + 1); op.forEachTemp(spillProc); op.forEachOutput(spillProc); moveResolver.resolve(); @@ -225,7 +225,7 @@ } assert checkEmpty(curOutRegisterState); - for (LIRBlock sux : block.getLIRSuccessors()) { + for (Block sux : block.getSuccessors()) { if (sux.phis != null) { assert trace(" phis of successor %s", sux); sux.phis.forEachInput(block, useSlotProc); @@ -434,7 +434,7 @@ return loc; } - private boolean checkInputState(final LIRBlock block) { + private boolean checkInputState(final Block block) { final BitSet liveState = new BitSet(); curStackLocations.forEachLocation(new ValueProcedure() { @Override diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/IntervalPrinter.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/IntervalPrinter.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/IntervalPrinter.java Sun Feb 05 05:40:36 2012 +0100 @@ -30,6 +30,7 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.graal.alloc.simple.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; @@ -126,11 +127,11 @@ public Interval[] execute() { ValueProcedure varProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return var(value); } }; - for (LIRBlock block : lir.linearScanOrder()) { + for (Block block : lir.linearScanOrder()) { if (block.phis != null) { block.phis.forEachOutput(varProc); } - for (LIRInstruction op : block.lir()) { + for (LIRInstruction op : block.lir) { op.forEachOutput(varProc); } } @@ -142,29 +143,29 @@ intervals.put("st", new Interval(-1, "st", "", "st", "hasState")); for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) { - LIRBlock block = lir.linearScanOrder().get(i); + Block block = lir.linearScanOrder().get(i); - curOpId = block.lastLirInstructionId() + 2; - for (LIRBlock sux : block.getLIRSuccessors()) { + curOpId = block.getLastLirInstructionId() + 2; + for (Block sux : block.getSuccessors()) { BitSet suxIn = dataFlow.liveIn(sux); for (int idx = suxIn.nextSetBit(0); idx >= 0; idx = suxIn.nextSetBit(idx + 1)) { if (blockEndLocations != null) { - out(blockEndLocations[block.blockID()].get(variables[idx])); + out(blockEndLocations[block.getId()].get(variables[idx])); } else { out(variables[idx]); } } } - curOpId = block.lastLirInstructionId() + 1; - for (LIRBlock sux : block.getLIRSuccessors()) { + curOpId = block.getLastLirInstructionId() + 1; + for (Block sux : block.getSuccessors()) { if (sux.phis != null) { sux.phis.forEachInput(block, useProc); } } - for (int j = block.lir().size() - 1; j >= 0; j--) { - LIRInstruction op = block.lir().get(j); + for (int j = block.lir.size() - 1; j >= 0; j--) { + LIRInstruction op = block.lir.get(j); if (op.id() >= 0) { curOpId = op.id(); } else { @@ -188,13 +189,13 @@ } if (block.phis != null) { - curOpId = block.firstLirInstructionId() + 1; + curOpId = block.getFirstLirInstructionId() + 1; block.phis.forEachOutput(defProc); } for (Interval interval : intervals.values()) { if (interval.lastTo != 0) { - interval.ranges.add(new Range(block.firstLirInstructionId(), interval.lastTo)); + interval.ranges.add(new Range(block.getFirstLirInstructionId(), interval.lastTo)); interval.lastTo = 0; } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java Sun Feb 05 05:40:36 2012 +0100 @@ -30,6 +30,7 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.lir.LIRInstruction.*; import com.oracle.max.graal.compiler.util.*; @@ -40,7 +41,7 @@ /** * All blocks that must be processed. */ - private final List workList; + private final List workList; /** * Saved information of previous check. @@ -51,18 +52,18 @@ */ private final Map[] blockStates; - private void addToWorkList(LIRBlock block) { + private void addToWorkList(Block block) { if (!workList.contains(block)) { workList.add(block); } } - private Map stateFor(LIRBlock block) { - return blockStates[block.blockID()]; + private Map stateFor(Block block) { + return blockStates[block.getId()]; } - private void setStateFor(LIRBlock block, Map savedState) { - blockStates[block.blockID()] = savedState; + private void setStateFor(Block block, Map savedState) { + blockStates[block.getId()] = savedState; } private static Map copy(Map inputState) { @@ -71,7 +72,7 @@ public static boolean verify(LIR lir, FrameMap frameMap) { RegisterVerifier verifier = new RegisterVerifier(lir, frameMap); - verifier.verify(lir.startBlock()); + verifier.verify(lir.cfg.getStartBlock()); return true; } @@ -84,7 +85,7 @@ private Map curInputState; - private void verify(LIRBlock startBlock) { + private void verify(Block startBlock) { ValueProcedure useProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { return use(value, flags); } }; ValueProcedure tempProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return temp(value); } }; ValueProcedure outputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return output(value); } }; @@ -95,15 +96,15 @@ assert trace("==== start verify register allocation ===="); do { - LIRBlock block = workList.remove(0); + Block block = workList.remove(0); assert block.phis == null : "phi functions must have been resolved with moves"; // Must copy state because it is modified. curInputState = copy(stateFor(block)); - assert trace("start block %s loop %d depth %d", block, block.loopIndex(), block.loopDepth()); + assert trace("start block %s %s", block, block.getLoop()); assert traceState(); - for (LIRInstruction op : block.lir()) { + for (LIRInstruction op : block.lir) { assert trace(" op %d %s", op.id(), op); op.forEachInput(useProc); @@ -116,7 +117,7 @@ op.forEachOutput(outputProc); } - for (LIRBlock succ : block.getLIRSuccessors()) { + for (Block succ : block.getSuccessors()) { processSuccessor(succ); } @@ -125,7 +126,7 @@ assert trace("==== end verify register allocation ===="); } - private void processSuccessor(LIRBlock succ) { + private void processSuccessor(Block succ) { Map savedState = stateFor(succ); if (savedState == null) { // Block was not processed before, so set initial inputState. diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java Sun Feb 05 05:40:36 2012 +0100 @@ -33,6 +33,7 @@ import com.oracle.max.graal.alloc.simple.*; import com.oracle.max.graal.compiler.alloc.*; import com.oracle.max.graal.compiler.asm.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.phases.*; @@ -41,7 +42,6 @@ import com.oracle.max.graal.compiler.target.*; import com.oracle.max.graal.cri.*; import com.oracle.max.graal.debug.*; -import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; public class GraalCompiler { @@ -181,24 +181,17 @@ new ReadEliminationPhase().apply(graph); } } - new RemovePlaceholderPhase().apply(graph); new DeadCodeEliminationPhase().apply(graph); plan.runPhases(PhasePosition.MID_LEVEL, graph); plan.runPhases(PhasePosition.LOW_LEVEL, graph); - final IdentifyBlocksPhase schedule = new IdentifyBlocksPhase(true, LIRBlock.FACTORY); + final SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph); - final List blocks = schedule.getBlocks(); - final NodeMap valueToBlock = new NodeMap<>(graph); - for (Block b : blocks) { - for (Node i : b.getInstructions()) { - valueToBlock.set(i, (LIRBlock) b); - } - } - final LIRBlock startBlock = valueToBlock.get(graph.start()); + final Block[] blocks = schedule.getCFG().getBlocks(); + final Block startBlock = schedule.getCFG().getStartBlock(); assert startBlock != null; assert startBlock.numberOfPreds() == 0; @@ -206,16 +199,16 @@ @Override public LIR call() { - ComputeLinearScanOrder clso = new ComputeLinearScanOrder(blocks.size(), schedule.loopCount(), startBlock); - List linearScanOrder = clso.linearScanOrder(); - List codeEmittingOrder = clso.codeEmittingOrder(); + ComputeLinearScanOrder clso = new ComputeLinearScanOrder(blocks.length, schedule.getCFG().getLoops().length, startBlock); + List linearScanOrder = clso.linearScanOrder(); + List codeEmittingOrder = clso.codeEmittingOrder(); int z = 0; - for (LIRBlock b : linearScanOrder) { - b.setLinearScanNumber(z++); + for (Block b : linearScanOrder) { + b.linearScanNumber = z++; } - LIR lir = new LIR(startBlock, linearScanOrder, codeEmittingOrder, valueToBlock, schedule.loopCount()); + LIR lir = new LIR(schedule.getCFG(), schedule.getNodesFor(), linearScanOrder, codeEmittingOrder); Debug.dump(lir, "After linear scan order"); return lir; @@ -229,11 +222,11 @@ Debug.scope("LIRGen", new Runnable() { public void run() { - for (LIRBlock b : lir.linearScanOrder()) { + for (Block b : lir.linearScanOrder()) { lirGenerator.doBlock(b); } - for (LIRBlock b : lir.linearScanOrder()) { + for (Block b : lir.linearScanOrder()) { if (b.phis != null) { b.phis.fillInputs(lirGenerator); } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java Sun Feb 05 05:40:36 2012 +0100 @@ -126,6 +126,7 @@ public static int MatureInvocationCount = 100; public static boolean GenSafepoints = true; public static boolean GenLoopSafepoints = true; + public static boolean UseInstanceOfHints = true; public static boolean GenAssertionCode = ____; public static boolean AlignCallsForPatching = true; diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ComputeLinearScanOrder.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ComputeLinearScanOrder.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ComputeLinearScanOrder.java Sun Feb 05 05:40:36 2012 +0100 @@ -27,22 +27,22 @@ import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.graph.*; public final class ComputeLinearScanOrder { private int numBlocks; // total number of blocks (smaller than maxBlockId) - List linearScanOrder; // the resulting list of blocks in correct order - List codeEmittingOrder; + List linearScanOrder; // the resulting list of blocks in correct order + List codeEmittingOrder; final BitMap visitedBlocks; // used for recursive processing of blocks final BitMap activeBlocks; // used for recursive processing of blocks final BitMap dominatorBlocks; // temporary BitMap used for computation of dominator final int[] forwardBranches; // number of incoming forward branches for each block - final List workList; // temporary list (used in markLoops and computeOrder) - final LIRBlock[] loopHeaders; + final List workList; // temporary list (used in markLoops and computeOrder) + final Block[] loopHeaders; // accessors for visitedBlocks and activeBlocks void initVisited() { @@ -50,45 +50,45 @@ visitedBlocks.clearAll(); } - boolean isVisited(LIRBlock b) { - return visitedBlocks.get(b.blockID()); + boolean isVisited(Block b) { + return visitedBlocks.get(b.getId()); } - boolean isActive(LIRBlock b) { - return activeBlocks.get(b.blockID()); + boolean isActive(Block b) { + return activeBlocks.get(b.getId()); } - void setVisited(LIRBlock b) { + void setVisited(Block b) { assert !isVisited(b) : "already set"; - visitedBlocks.set(b.blockID()); + visitedBlocks.set(b.getId()); } - void setActive(LIRBlock b) { + void setActive(Block b) { assert !isActive(b) : "already set"; - activeBlocks.set(b.blockID()); + activeBlocks.set(b.getId()); } - void clearActive(LIRBlock b) { + void clearActive(Block b) { assert isActive(b) : "not already"; - activeBlocks.clear(b.blockID()); + activeBlocks.clear(b.getId()); } // accessors for forwardBranches - void incForwardBranches(LIRBlock b) { - forwardBranches[b.blockID()]++; + void incForwardBranches(Block b) { + forwardBranches[b.getId()]++; } - int decForwardBranches(LIRBlock b) { - return --forwardBranches[b.blockID()]; + int decForwardBranches(Block b) { + return --forwardBranches[b.getId()]; } // accessors for final result - public List linearScanOrder() { + public List linearScanOrder() { return linearScanOrder; } - public ComputeLinearScanOrder(int maxBlockId, int loopCount, LIRBlock startBlock) { - loopHeaders = new LIRBlock[loopCount]; + public ComputeLinearScanOrder(int maxBlockId, int loopCount, Block startBlock) { + loopHeaders = new Block[loopCount]; visitedBlocks = new BitMap(maxBlockId); activeBlocks = new BitMap(maxBlockId); @@ -98,7 +98,6 @@ countEdges(startBlock, null); computeOrder(startBlock); - printBlocks(); } /** @@ -109,9 +108,9 @@ * 3. Number loop header blocks. * 4. Create a list with all loop end blocks. */ - void countEdges(LIRBlock cur, LIRBlock parent) { + void countEdges(Block cur, Block parent) { if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("Counting edges for block B%d%s", cur.blockID(), parent == null ? "" : " coming from B" + parent.blockID()); + TTY.println("Counting edges for block B%d%s", cur.getId(), parent == null ? "" : " coming from B" + parent.getId()); } if (isActive(cur)) { @@ -141,14 +140,14 @@ clearActive(cur); if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("Finished counting edges for block B%d", cur.blockID()); + TTY.println("Finished counting edges for block B%d", cur.getId()); } } - static int computeWeight(LIRBlock cur) { + static int computeWeight(Block cur) { // limit loop-depth to 15 bit (only for security reason, it will never be so big) - int weight = (cur.loopDepth() & 0x7FFF) << 16; + int weight = (cur.getLoopDepth() & 0x7FFF) << 16; int curBit = 15; @@ -200,7 +199,7 @@ return weight; } - private boolean readyForProcessing(LIRBlock cur) { + private boolean readyForProcessing(Block cur) { // Discount the edge just traveled. // When the number drops to zero, all forward branches were processed if (decForwardBranches(cur) != 0) { @@ -212,13 +211,13 @@ return true; } - private void sortIntoWorkList(LIRBlock cur) { + private void sortIntoWorkList(Block cur) { assert !workList.contains(cur) : "block already in work list"; int curWeight = computeWeight(cur); // the linearScanNumber is used to cache the weight of a block - cur.setLinearScanNumber(curWeight); + cur.linearScanNumber = curWeight; if (GraalOptions.StressLinearScan) { workList.add(0, cur); @@ -228,35 +227,35 @@ workList.add(null); // provide space for new element int insertIdx = workList.size() - 1; - while (insertIdx > 0 && workList.get(insertIdx - 1).linearScanNumber() > curWeight) { + while (insertIdx > 0 && workList.get(insertIdx - 1).linearScanNumber > curWeight) { workList.set(insertIdx, workList.get(insertIdx - 1)); insertIdx--; } workList.set(insertIdx, cur); if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("Sorted B%d into worklist. new worklist:", cur.blockID()); + TTY.println("Sorted B%d into worklist. new worklist:", cur.getId()); for (int i = 0; i < workList.size(); i++) { - TTY.println(String.format("%8d B%02d weight:%6x", i, workList.get(i).blockID(), workList.get(i).linearScanNumber())); + TTY.println(String.format("%8d B%02d weight:%6x", i, workList.get(i).getId(), workList.get(i).linearScanNumber)); } } for (int i = 0; i < workList.size(); i++) { - assert workList.get(i).linearScanNumber() > 0 : "weight not set"; - assert i == 0 || workList.get(i - 1).linearScanNumber() <= workList.get(i).linearScanNumber() : "incorrect order in worklist"; + assert workList.get(i).linearScanNumber > 0 : "weight not set"; + assert i == 0 || workList.get(i - 1).linearScanNumber <= workList.get(i).linearScanNumber : "incorrect order in worklist"; } } - private void appendBlock(LIRBlock cur) { + private void appendBlock(Block cur) { if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println("appending block B%d (weight 0x%06x) to linear-scan order", cur.blockID(), cur.linearScanNumber()); + TTY.println("appending block B%d (weight 0x%06x) to linear-scan order", cur.getId(), cur.linearScanNumber); } assert !linearScanOrder.contains(cur) : "cannot add the same block twice"; // currently, the linear scan order and code emit order are equal. // therefore the linearScanNumber and the weight of a block must also // be equal. - cur.setLinearScanNumber(linearScanOrder.size()); + cur.linearScanNumber = linearScanOrder.size(); linearScanOrder.add(cur); if (cur.isLoopEnd() && cur.isLoopHeader()) { @@ -266,24 +265,24 @@ codeEmittingOrder.add(cur); if (cur.isLoopEnd() && GraalOptions.OptReorderLoops) { - LIRBlock loopHeader = loopHeaders[cur.loopIndex()]; + Block loopHeader = loopHeaders[cur.getLoop().index]; assert loopHeader != null; codeEmittingOrder.add(loopHeader); for (int i = 0; i < loopHeader.numberOfSux(); i++) { - LIRBlock succ = loopHeader.suxAt(i); - if (succ.loopDepth() == loopHeader.loopDepth()) { - succ.setAlign(true); + Block succ = loopHeader.suxAt(i); + if (succ.getLoopDepth() == loopHeader.getLoopDepth()) { + succ.align = true; } } } } else { - loopHeaders[cur.loopIndex()] = cur; + loopHeaders[cur.getLoop().index] = cur; } } } - private void computeOrder(LIRBlock startBlock) { + private void computeOrder(Block startBlock) { if (GraalOptions.TraceLinearScanLevel >= 3) { TTY.println("----- computing final block order"); } @@ -300,14 +299,14 @@ sortIntoWorkList(startBlock); do { - LIRBlock cur = workList.remove(workList.size() - 1); + Block 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++) { - LIRBlock sux = cur.suxAt(i); + Block sux = cur.suxAt(i); if (readyForProcessing(sux)) { sortIntoWorkList(sux); } @@ -315,46 +314,7 @@ } while (workList.size() > 0); } - public void printBlocks() { - if (GraalOptions.TraceLinearScanLevel >= 2) { - TTY.println("----- loop information:"); - for (LIRBlock cur : linearScanOrder) { - TTY.print(String.format("%4d: B%02d: ", cur.linearScanNumber(), cur.blockID())); - TTY.println(String.format(" . loopIndex: %2d, loopDepth: %2d", cur.loopIndex(), cur.loopDepth())); - } - } - - if (GraalOptions.TraceLinearScanLevel >= 1) { - TTY.println("----- linear-scan block order:"); - for (LIRBlock cur : linearScanOrder) { - TTY.print(String.format("%4d: B%02d loop: %2d depth: %2d", cur.linearScanNumber(), cur.blockID(), cur.loopIndex(), cur.loopDepth())); - - TTY.print(cur.isLoopHeader() ? " lh" : " "); - TTY.print(cur.isLoopEnd() ? " le" : " "); - - TTY.print(" dom: null "); - - - if (cur.numberOfPreds() > 0) { - TTY.print(" preds: "); - for (int j = 0; j < cur.numberOfPreds(); j++) { - LIRBlock pred = cur.predAt(j); - TTY.print("B%d ", pred.blockID()); - } - } - if (cur.numberOfSux() > 0) { - TTY.print(" sux: "); - for (int j = 0; j < cur.numberOfSux(); j++) { - LIRBlock sux = cur.suxAt(j); - TTY.print("B%d ", sux.blockID()); - } - } - TTY.println(); - } - } - } - - public List codeEmittingOrder() { + public List codeEmittingOrder() { return codeEmittingOrder; } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Sun Feb 05 05:40:36 2012 +0100 @@ -24,8 +24,8 @@ import java.util.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.debug.*; @@ -40,7 +40,7 @@ */ public static void optimize(LIR ir) { ControlFlowOptimizer optimizer = new ControlFlowOptimizer(ir); - List code = ir.codeEmittingOrder(); + List code = ir.codeEmittingOrder(); //optimizer.reorderShortLoops(code); optimizer.deleteEmptyBlocks(code); ControlFlowOptimizer.deleteUnnecessaryJumps(code); @@ -90,37 +90,48 @@ // only blocks with exactly one successor can be deleted. Such blocks // must always end with an unconditional branch to its successor - private boolean canDeleteBlock(LIRBlock block) { + private boolean canDeleteBlock(Block block) { if (block.numberOfSux() != 1 || - block == ir.startBlock() || + block == ir.cfg.getStartBlock() || block.suxAt(0) == block) { return false; } - List instructions = block.lir(); + List instructions = block.lir; assert instructions.size() >= 2 : "block must have label and branch"; assert instructions.get(0) instanceof StandardOp.LabelOp : "first instruction must always be a label"; assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "last instruction must always be a branch"; - assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == block.suxAt(0).label() : "branch target must be the successor"; + assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == ((StandardOp.LabelOp) block.suxAt(0).lir.get(0)).getLabel() : "branch target must be the successor"; // block must have exactly one successor return instructions.size() == 2 && instructions.get(instructions.size() - 1).info == null; } - private void deleteEmptyBlocks(List code) { + private void deleteEmptyBlocks(List code) { int oldPos = 0; int newPos = 0; int numBlocks = code.size(); assert verify(code); while (oldPos < numBlocks) { - LIRBlock block = code.get(oldPos); + Block block = code.get(oldPos); if (canDeleteBlock(block)) { // adjust successor and predecessor lists - block.replaceWith(block.suxAt(0)); + Block other = block.suxAt(0); + for (Block pred : block.getPredecessors()) { + Util.replaceAllInList(block, other, pred.getSuccessors()); + } + for (int i = 0; i < other.getPredecessors().size(); i++) { + if (other.getPredecessors().get(i) == block) { + other.getPredecessors().remove(i); + other.getPredecessors().addAll(i, block.getPredecessors()); + } + } + block.getSuccessors().clear(); + block.getPredecessors().clear(); Debug.metric("BlocksDeleted").increment(); } else { // adjust position of this block in the block list if blocks before @@ -138,18 +149,18 @@ assert verify(code); } - private static void deleteUnnecessaryJumps(List code) { + private static void deleteUnnecessaryJumps(List code) { // skip the last block because there a branch is always necessary for (int i = code.size() - 2; i >= 0; i--) { - LIRBlock block = code.get(i); - List instructions = block.lir(); + Block block = code.get(i); + List instructions = block.lir; LIRInstruction lastOp = instructions.get(instructions.size() - 1); if (lastOp instanceof StandardOp.JumpOp) { StandardOp.JumpOp lastJump = (StandardOp.JumpOp) lastOp; if (lastOp.info == null) { - if (lastJump.destination().label() == code.get(i + 1).label()) { + if (lastJump.destination().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel()) { // delete last branch instruction Util.truncate(instructions, instructions.size() - 1); @@ -158,7 +169,7 @@ if (prevOp instanceof StandardOp.BranchOp) { StandardOp.BranchOp prevBranch = (StandardOp.BranchOp) prevOp; - if (prevBranch.destination().label() == code.get(i + 1).label && prevOp.info == null) { + if (prevBranch.destination().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel() && prevOp.info == null) { // eliminate a conditional branch to the immediate successor prevBranch.negate(lastJump.destination()); Util.truncate(instructions, instructions.size() - 1); @@ -212,8 +223,8 @@ } */ - private static boolean verify(List code) { - for (LIRBlock block : code) { + private static boolean verify(List code) { + for (Block block : code) { for (Block sux : block.getSuccessors()) { assert code.contains(sux) : "missing successor from: " + block + "to: " + sux; } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java Sun Feb 05 05:40:36 2012 +0100 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.lir.StandardOp.*; @@ -54,12 +55,12 @@ * * @param blockList a list of blocks whose moves should be optimized */ - public static void optimize(List blockList) { + public static void optimize(List blockList) { EdgeMoveOptimizer optimizer = new EdgeMoveOptimizer(); // ignore the first block in the list (index 0 is not processed) for (int i = blockList.size() - 1; i >= 1; i--) { - LIRBlock block = blockList.get(i); + Block block = blockList.get(i); if (block.numberOfPreds() > 1) { optimizer.optimizeMovesAtBlockEnd(block); @@ -104,10 +105,12 @@ * Moves the longest {@linkplain #same common} subsequence at the end all * predecessors of {@code block} to the start of {@code block}. */ - private void optimizeMovesAtBlockEnd(LIRBlock block) { - if (block.isPredecessor(block)) { - // currently we can't handle this correctly. - return; + private void optimizeMovesAtBlockEnd(Block block) { + for (Block pred : block.getPredecessors()) { + if (pred == block) { + // currently we can't handle this correctly. + return; + } } // clear all internal data structures @@ -117,11 +120,10 @@ assert numPreds > 1 : "do not call otherwise"; // setup a list with the LIR instructions of all predecessors - for (int i = 0; i < numPreds; i++) { - LIRBlock pred = block.predAt(i); + for (Block pred : block.getPredecessors()) { assert pred != null; - assert pred.lir() != null; - List predInstructions = pred.lir(); + assert pred.lir != null; + List predInstructions = pred.lir; if (pred.numberOfSux() != 1) { // this can happen with switch-statements where multiple edges are between @@ -162,7 +164,7 @@ } // insert the instruction at the beginning of the current block - block.lir().add(1, op); + block.lir.add(1, op); // delete the instruction at the end of all predecessors for (int i = 0; i < numPreds; i++) { @@ -177,12 +179,12 @@ * successors of {@code block} to the end of {@code block} just prior to the * branch instruction ending {@code block}. */ - private void optimizeMovesAtBlockBegin(LIRBlock block) { + private void optimizeMovesAtBlockBegin(Block block) { edgeInstructionSeqences.clear(); int numSux = block.numberOfSux(); - List instructions = block.lir(); + List instructions = block.lir; assert numSux == 2 : "method should not be called otherwise"; @@ -212,8 +214,8 @@ // setup a list with the lir-instructions of all successors for (int i = 0; i < numSux; i++) { - LIRBlock sux = block.suxAt(i); - List suxInstructions = sux.lir(); + Block sux = block.suxAt(i); + List suxInstructions = sux.lir; assert suxInstructions.get(0) instanceof StandardOp.LabelOp : "block must start with label"; @@ -247,7 +249,7 @@ } // insert instruction at end of current block - block.lir().add(insertIdx, op); + block.lir.add(insertIdx, op); insertIdx++; // delete the instructions at the beginning of all successors diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Sun Feb 05 05:40:36 2012 +0100 @@ -35,15 +35,16 @@ import com.oracle.max.graal.compiler.alloc.Interval.RegisterBinding; import com.oracle.max.graal.compiler.alloc.Interval.RegisterPriority; import com.oracle.max.graal.compiler.alloc.Interval.SpillState; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; +import com.oracle.max.graal.compiler.lir.StandardOp.MoveOp; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.debug.*; import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.compiler.lir.StandardOp.*; /** * An implementation of the linear scan register allocator algorithm described @@ -62,10 +63,43 @@ private static final int INITIAL_SPLIT_INTERVALS_CAPACITY = 32; + public static class BlockData { + /** + * Bit map specifying which {@linkplain OperandPool operands} are live upon entry to this block. + * These are values used in this block or any of its successors where such value are not defined + * in this block. + * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}. + */ + public BitMap liveIn; + + /** + * Bit map specifying which {@linkplain OperandPool operands} are live upon exit from this block. + * These are values used in a successor block that are either defined in this block or were live + * upon entry to this block. + * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}. + */ + public BitMap liveOut; + + /** + * Bit map specifying which {@linkplain OperandPool operands} are used (before being defined) in this block. + * That is, these are the values that are live upon entry to the block. + * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}. + */ + public BitMap liveGen; + + /** + * Bit map specifying which {@linkplain OperandPool operands} are defined/overwritten in this block. + * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}. + */ + public BitMap liveKill; + } + + public final BlockMap blockData; + /** * List of blocks in linear-scan order. This is only correct as long as the CFG does not change. */ - final LIRBlock[] sortedBlocks; + final Block[] sortedBlocks; /** * Map from {@linkplain #operandNumber(CiValue) operand numbers} to intervals. @@ -96,10 +130,10 @@ /** * Map from an instruction {@linkplain LIRInstruction#id id} to the {@linkplain - * LIRBlock block} containing the instruction. Entries should be retrieved with + * Block block} containing the instruction. Entries should be retrieved with * {@link #blockForId(int)} as the id is not simply an index into this array. */ - LIRBlock[] opIdToBlockMap; + Block[] opIdToBlockMap; /** * Bit set for each variable that is contained in each loop. @@ -126,12 +160,13 @@ this.ir = ir; this.gen = gen; this.frameMap = frameMap; - this.sortedBlocks = ir.linearScanOrder().toArray(new LIRBlock[ir.linearScanOrder().size()]); + this.sortedBlocks = ir.linearScanOrder().toArray(new Block[ir.linearScanOrder().size()]); this.registerAttributes = frameMap.registerConfig.getAttributesMap(); this.registers = target.arch.registers; this.firstVariableNumber = registers.length; this.variables = new ArrayList<>(ir.numVariables() * 3 / 2); + this.blockData = new BlockMap<>(ir.cfg); } public static boolean isVariableOrRegister(CiValue value) { @@ -269,13 +304,13 @@ return sortedBlocks.length; } - LIRBlock blockAt(int index) { + Block blockAt(int index) { assert sortedBlocks[index] == ir.linearScanOrder().get(index) : "invalid cached block list"; return sortedBlocks[index]; } /** - * Gets the size of the {@link LIRBlock#liveIn} and {@link LIRBlock#liveOut} sets for a basic block. These sets do + * Gets the size of the {@link Block#liveIn} and {@link Block#liveOut} sets for a basic block. These sets do * not include any operands allocated as a result of creating {@linkplain #createDerivedInterval(Interval) derived * intervals}. */ @@ -284,7 +319,7 @@ } int numLoops() { - return ir.numLoops(); + return ir.cfg.getLoops().length; } boolean isIntervalInLoop(int interval, int loop) { @@ -333,7 +368,7 @@ * @param opId an instruction {@linkplain LIRInstruction#id id} * @return the block containing the instruction denoted by {@code opId} */ - LIRBlock blockForId(int opId) { + Block blockForId(int opId) { assert opIdToBlockMap.length > 0 && opId >= 0 && opId <= maxOpId() + 1 : "opId out of range"; return opIdToBlockMap[opIdToIndex(opId)]; } @@ -394,8 +429,8 @@ void changeSpillState(Interval interval, int spillPos) { switch (interval.spillState()) { case NoSpillStore: { - int defLoopDepth = blockForId(interval.spillDefinitionPos()).loopDepth(); - int spillLoopDepth = blockForId(spillPos).loopDepth(); + int defLoopDepth = blockForId(interval.spillDefinitionPos()).getLoopDepth(); + int spillLoopDepth = blockForId(spillPos).getLoopDepth(); if (defLoopDepth < spillLoopDepth) { // the loop depth of the spilling position is higher then the loop depth @@ -457,8 +492,8 @@ LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer(); int numBlocks = blockCount(); for (int i = 0; i < numBlocks; i++) { - LIRBlock block = blockAt(i); - List instructions = block.lir(); + Block block = blockAt(i); + List instructions = block.lir; int numInst = instructions.size(); // iterate all instructions of the block. skip the first because it is always a label @@ -490,7 +525,7 @@ while (interval != Interval.EndMarker && interval.spillDefinitionPos() == opId) { if (!insertionBuffer.initialized()) { // prepare insertion buffer (appended when all instructions of the block are processed) - insertionBuffer.init(block.lir()); + insertionBuffer.init(block.lir); } CiValue fromLocation = interval.location(); @@ -565,20 +600,21 @@ int numBlocks = blockCount(); int numInstructions = 0; for (int i = 0; i < numBlocks; i++) { - numInstructions += blockAt(i).lir().size(); + numInstructions += blockAt(i).lir.size(); } // initialize with correct length opIdToInstructionMap = new LIRInstruction[numInstructions]; - opIdToBlockMap = new LIRBlock[numInstructions]; + opIdToBlockMap = new Block[numInstructions]; int opId = 0; int index = 0; for (int i = 0; i < numBlocks; i++) { - LIRBlock block = blockAt(i); - block.setFirstLirInstructionId(opId); - List instructions = block.lir(); + Block block = blockAt(i); + blockData.put(block, new BlockData()); + + List instructions = block.lir; int numInst = instructions.size(); for (int j = 0; j < numInst; j++) { @@ -595,7 +631,6 @@ index++; opId += 2; // numbering of lirOps by two } - block.setLastLirInstructionId((opId - 2)); } assert index == numInstructions : "must match"; assert (index << 1) == opId : "must match: " + (index << 1); @@ -609,7 +644,7 @@ } /** - * Computes local live sets (i.e. {@link LIRBlock#liveGen} and {@link LIRBlock#liveKill}) separately for each block. + * Computes local live sets (i.e. {@link Block#liveGen} and {@link Block#liveKill}) separately for each block. */ void computeLocalLiveSets() { int numBlocks = blockCount(); @@ -619,11 +654,11 @@ // iterate all blocks for (int i = 0; i < numBlocks; i++) { - final LIRBlock block = blockAt(i); + final Block block = blockAt(i); final BitMap liveGen = new BitMap(liveSize); final BitMap liveKill = new BitMap(liveSize); - List instructions = block.lir(); + List instructions = block.lir; int numInst = instructions.size(); // iterate all instructions of the block. skip the first because it is always a label @@ -642,8 +677,8 @@ TTY.println(" Setting liveGen for operand %d at instruction %d", operandNum, op.id()); } } - if (block.loopIndex() >= 0) { - intervalInLoop.setBit(operandNum, block.loopIndex()); + if (block.getLoop() != null) { + intervalInLoop.setBit(operandNum, block.getLoop().index); } } @@ -672,8 +707,8 @@ if (isVariable(operand)) { int varNum = operandNumber(operand); liveKill.set(varNum); - if (block.loopIndex() >= 0) { - intervalInLoop.setBit(varNum, block.loopIndex()); + if (block.getLoop() != null) { + intervalInLoop.setBit(varNum, block.getLoop().index); } } @@ -695,14 +730,14 @@ op.forEachOutput(defProc); } // end of instruction iteration - block.liveGen = liveGen; - block.liveKill = liveKill; - block.liveIn = new BitMap(liveSize); - block.liveOut = new BitMap(liveSize); + blockData.get(block).liveGen = liveGen; + blockData.get(block).liveKill = liveKill; + blockData.get(block).liveIn = new BitMap(liveSize); + blockData.get(block).liveOut = new BitMap(liveSize); if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println("liveGen B%d %s", block.blockID(), block.liveGen); - TTY.println("liveKill B%d %s", block.blockID(), block.liveKill); + TTY.println("liveGen B%d %s", block.getId(), blockData.get(block).liveGen); + TTY.println("liveKill B%d %s", block.getId(), blockData.get(block).liveKill); } } // end of block iteration } @@ -718,13 +753,13 @@ } } - private void verifyInput(LIRBlock block, BitMap liveKill, CiValue operand) { + private void verifyInput(Block block, BitMap liveKill, CiValue operand) { // fixed intervals are never live at block boundaries, so // they need not be processed in live sets. // this is checked by these assertions to be sure about it. // the entry block may have incoming // values in registers, which is ok. - if (isRegister(operand) && block != ir.startBlock()) { + if (isRegister(operand) && block != ir.cfg.getStartBlock()) { if (isProcessed(operand)) { assert liveKill.get(operandNumber(operand)) : "using fixed register that is not defined in this block"; } @@ -732,8 +767,8 @@ } /** - * Performs a backward dataflow analysis to compute global live sets (i.e. {@link LIRBlock#liveIn} and - * {@link LIRBlock#liveOut}) for each block. + * Performs a backward dataflow analysis to compute global live sets (i.e. {@link Block#liveIn} and + * {@link Block#liveOut}) for each block. */ void computeGlobalLiveSets() { int numBlocks = blockCount(); @@ -749,7 +784,7 @@ // iterate all blocks in reverse order for (int i = numBlocks - 1; i >= 0; i--) { - LIRBlock block = blockAt(i); + Block block = blockAt(i); changeOccurredInBlock = false; @@ -758,18 +793,18 @@ if (n > 0) { // block has successors if (n > 0) { - liveOut.setFrom(block.suxAt(0).liveIn); + liveOut.setFrom(blockData.get(block.suxAt(0)).liveIn); for (int j = 1; j < n; j++) { - liveOut.setUnion(block.suxAt(j).liveIn); + liveOut.setUnion(blockData.get(block.suxAt(j)).liveIn); } } else { liveOut.clearAll(); } - if (!block.liveOut.isSame(liveOut)) { + if (!blockData.get(block).liveOut.isSame(liveOut)) { // A change occurred. Swap the old and new live out sets to avoid copying. - BitMap temp = block.liveOut; - block.liveOut = liveOut; + BitMap temp = blockData.get(block).liveOut; + blockData.get(block).liveOut = liveOut; liveOut = temp; changeOccurred = true; @@ -780,10 +815,10 @@ if (iterationCount == 0 || changeOccurredInBlock) { // liveIn(block) is the union of liveGen(block) with (liveOut(block) & !liveKill(block)) // note: liveIn has to be computed only in first iteration or if liveOut has changed! - BitMap liveIn = block.liveIn; - liveIn.setFrom(block.liveOut); - liveIn.setDifference(block.liveKill); - liveIn.setUnion(block.liveGen); + BitMap liveIn = blockData.get(block).liveIn; + liveIn.setFrom(blockData.get(block).liveOut); + liveIn.setDifference(blockData.get(block).liveKill); + liveIn.setUnion(blockData.get(block).liveGen); } if (GraalOptions.TraceLinearScanLevel >= 4) { @@ -802,15 +837,15 @@ } // check that the liveIn set of the first block is empty - LIRBlock startBlock = ir.startBlock(); - BitMap liveInArgs = new BitMap(startBlock.liveIn.size()); - if (!startBlock.liveIn.isSame(liveInArgs)) { + Block startBlock = ir.cfg.getStartBlock(); + BitMap liveInArgs = new BitMap(blockData.get(startBlock).liveIn.size()); + if (!blockData.get(startBlock).liveIn.isSame(liveInArgs)) { if (GraalOptions.DetailedAsserts) { reportFailure(numBlocks); } TTY.println("preds=" + startBlock.getPredecessors().size() + ", succs=" + startBlock.getSuccessors().size()); - TTY.println("startBlock-ID: " + startBlock.blockID()); + TTY.println("startBlock-ID: " + startBlock.getId()); // bailout of if this occurs in product mode. throw new CiBailout("liveIn set of first block must be empty"); @@ -821,19 +856,19 @@ TTY.println(method.toString()); TTY.println("Error: liveIn set of first block must be empty (when this fails, variables are used before they are defined)"); TTY.print("affected registers:"); - TTY.println(ir.startBlock().liveIn.toString()); + TTY.println(blockData.get(ir.cfg.getStartBlock()).liveIn.toString()); // print some additional information to simplify debugging - for (int operandNum = 0; operandNum < ir.startBlock().liveIn.size(); operandNum++) { - if (ir.startBlock().liveIn.get(operandNum)) { + for (int operandNum = 0; operandNum < blockData.get(ir.cfg.getStartBlock()).liveIn.size(); operandNum++) { + if (blockData.get(ir.cfg.getStartBlock()).liveIn.get(operandNum)) { CiValue operand = operandFor(operandNum); TTY.println(" var %d; operand=%s", operandNum, operand.toString()); for (int j = 0; j < numBlocks; j++) { - LIRBlock block = blockAt(j); - if (block.liveGen.get(operandNum)) { - TTY.println(" used in block B%d", block.blockID()); - for (LIRInstruction ins : block.lir()) { + Block block = blockAt(j); + if (blockData.get(block).liveGen.get(operandNum)) { + TTY.println(" used in block B%d", block.getId()); + for (LIRInstruction ins : block.lir) { TTY.println(ins.id() + ": " + ins.toString()); LIRDebugInfo info = ins.info; if (info != null) { @@ -847,9 +882,9 @@ } } } - if (block.liveKill.get(operandNum)) { - TTY.println(" defined in block B%d", block.blockID()); - for (LIRInstruction ins : block.lir()) { + if (blockData.get(block).liveKill.get(operandNum)) { + TTY.println(" defined in block B%d", block.getId()); + for (LIRInstruction ins : block.lir) { TTY.println(ins.id() + ": " + ins.toString()); } } @@ -862,21 +897,21 @@ // check that fixed intervals are not live at block boundaries // (live set must be empty at fixed intervals) for (int i = 0; i < numBlocks; i++) { - LIRBlock block = blockAt(i); + Block block = blockAt(i); for (int j = 0; j <= maxRegisterNumber(); j++) { - assert !block.liveIn.get(j) : "liveIn set of fixed register must be empty"; - assert !block.liveOut.get(j) : "liveOut set of fixed register must be empty"; - assert !block.liveGen.get(j) : "liveGen set of fixed register must be empty"; + assert !blockData.get(block).liveIn.get(j) : "liveIn set of fixed register must be empty"; + assert !blockData.get(block).liveOut.get(j) : "liveOut set of fixed register must be empty"; + assert !blockData.get(block).liveGen.get(j) : "liveGen set of fixed register must be empty"; } } } - private static void traceLiveness(boolean changeOccurredInBlock, int iterationCount, LIRBlock block) { + private void traceLiveness(boolean changeOccurredInBlock, int iterationCount, Block block) { char c = iterationCount == 0 || changeOccurredInBlock ? '*' : ' '; - TTY.print("(%d) liveIn%c B%d ", iterationCount, c, block.blockID()); - TTY.println(block.liveIn.toString()); - TTY.print("(%d) liveOut%c B%d ", iterationCount, c, block.blockID()); - TTY.println(block.liveOut.toString()); + TTY.print("(%d) liveIn%c B%d ", iterationCount, c, block.getId()); + TTY.println(blockData.get(block).liveIn.toString()); + TTY.print("(%d) liveOut%c B%d ", iterationCount, c, block.getId()); + TTY.println(blockData.get(block).liveOut.toString()); } void addUse(CiValue operand, int from, int to, RegisterPriority registerPriority, CiKind kind) { @@ -1067,16 +1102,16 @@ // iterate all blocks in reverse order for (int i = blockCount() - 1; i >= 0; i--) { - LIRBlock block = blockAt(i); - List instructions = block.lir(); - final int blockFrom = block.firstLirInstructionId(); - int blockTo = block.lastLirInstructionId(); + Block block = blockAt(i); + List instructions = block.lir; + final int blockFrom = block.getFirstLirInstructionId(); + int blockTo = block.getLastLirInstructionId(); assert blockFrom == instructions.get(0).id(); assert blockTo == instructions.get(instructions.size() - 1).id(); // Update intervals for operands live at the end of this block; - BitMap live = block.liveOut; + BitMap live = blockData.get(block).liveOut; for (int operandNum = live.nextSetBit(0); operandNum >= 0; operandNum = live.nextSetBit(operandNum + 1)) { assert live.get(operandNum) : "should not stop here otherwise"; CiValue operand = operandFor(operandNum); @@ -1090,7 +1125,7 @@ // interval is used anywhere inside this loop. It's possible // that the block was part of a non-natural loop, so it might // have an invalid loop index. - if (block.isLoopEnd() && block.loopIndex() != -1 && isIntervalInLoop(operandNum, block.loopIndex())) { + if (block.isLoopEnd() && block.getLoop() != null && isIntervalInLoop(operandNum, block.getLoop().index)) { intervalFor(operand).addUsePos(blockTo + 1, RegisterPriority.LiveAtLoopEnd); } } @@ -1365,18 +1400,18 @@ throw new CiBailout("LinearScan: interval is null"); } - Interval intervalAtBlockBegin(LIRBlock block, CiValue operand) { + Interval intervalAtBlockBegin(Block block, CiValue operand) { assert isVariable(operand) : "register number out of bounds"; assert intervalFor(operand) != null : "no interval found"; - return splitChildAtOpId(intervalFor(operand), block.firstLirInstructionId(), LIRInstruction.OperandMode.Output); + return splitChildAtOpId(intervalFor(operand), block.getFirstLirInstructionId(), LIRInstruction.OperandMode.Output); } - Interval intervalAtBlockEnd(LIRBlock block, CiValue operand) { + Interval intervalAtBlockEnd(Block block, CiValue operand) { assert isVariable(operand) : "register number out of bounds"; assert intervalFor(operand) != null : "no interval found"; - return splitChildAtOpId(intervalFor(operand), block.lastLirInstructionId() + 1, LIRInstruction.OperandMode.Output); + return splitChildAtOpId(intervalFor(operand), block.getLastLirInstructionId() + 1, LIRInstruction.OperandMode.Output); } Interval intervalAtOpId(CiValue operand, int opId) { @@ -1386,16 +1421,16 @@ return splitChildAtOpId(intervalFor(operand), opId, LIRInstruction.OperandMode.Input); } - void resolveCollectMappings(LIRBlock fromBlock, LIRBlock toBlock, MoveResolver moveResolver) { + void resolveCollectMappings(Block fromBlock, Block toBlock, MoveResolver moveResolver) { assert moveResolver.checkEmpty(); int numOperands = operandSize(); - BitMap liveAtEdge = toBlock.liveIn; + BitMap liveAtEdge = blockData.get(toBlock).liveIn; // visit all variables for which the liveAtEdge bit is set for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) { assert operandNum < numOperands : "live information set for not exisiting interval"; - assert fromBlock.liveOut.get(operandNum) && toBlock.liveIn.get(operandNum) : "interval not live at this edge"; + assert blockData.get(fromBlock).liveOut.get(operandNum) && blockData.get(toBlock).liveIn.get(operandNum) : "interval not live at this edge"; CiValue liveOperand = operandFor(operandNum); Interval fromInterval = intervalAtBlockEnd(fromBlock, liveOperand); @@ -1408,28 +1443,28 @@ } } - static void resolveFindInsertPos(LIRBlock fromBlock, LIRBlock toBlock, MoveResolver moveResolver) { + static void resolveFindInsertPos(Block fromBlock, Block toBlock, MoveResolver moveResolver) { if (fromBlock.numberOfSux() <= 1) { if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println("inserting moves at end of fromBlock B%d", fromBlock.blockID()); + TTY.println("inserting moves at end of fromBlock B%d", fromBlock.getId()); } - List instructions = fromBlock.lir(); + List instructions = fromBlock.lir; LIRInstruction instr = instructions.get(instructions.size() - 1); if (instr instanceof StandardOp.JumpOp) { // insert moves before branch - moveResolver.setInsertPosition(fromBlock.lir(), instructions.size() - 1); + moveResolver.setInsertPosition(fromBlock.lir, instructions.size() - 1); } else { - moveResolver.setInsertPosition(fromBlock.lir(), instructions.size()); + moveResolver.setInsertPosition(fromBlock.lir, instructions.size()); } } else { if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println("inserting moves at beginning of toBlock B%d", toBlock.blockID()); + TTY.println("inserting moves at beginning of toBlock B%d", toBlock.getId()); } if (GraalOptions.DetailedAsserts) { - assert fromBlock.lir().get(0) instanceof StandardOp.LabelOp : "block does not start with a label"; + assert fromBlock.lir.get(0) instanceof StandardOp.LabelOp : "block does not start with a label"; // because the number of predecessor edges matches the number of // successor edges, blocks which are reached by switch statements @@ -1440,7 +1475,7 @@ } } - moveResolver.setInsertPosition(toBlock.lir(), 1); + moveResolver.setInsertPosition(toBlock.lir, 1); } } @@ -1456,30 +1491,30 @@ int i; for (i = 0; i < numBlocks; i++) { - LIRBlock block = blockAt(i); + Block block = blockAt(i); // check if block has only one predecessor and only one successor if (block.numberOfPreds() == 1 && block.numberOfSux() == 1) { - List instructions = block.lir(); + List instructions = block.lir; assert instructions.get(0) instanceof StandardOp.LabelOp : "block must start with label"; assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "block with successor must end with unconditional jump"; // check if block is empty (only label and branch) if (instructions.size() == 2) { - LIRBlock pred = block.predAt(0); - LIRBlock sux = block.suxAt(0); + Block pred = block.predAt(0); + Block sux = block.suxAt(0); // prevent optimization of two consecutive blocks - if (!blockCompleted.get(pred.linearScanNumber()) && !blockCompleted.get(sux.linearScanNumber())) { + if (!blockCompleted.get(pred.linearScanNumber) && !blockCompleted.get(sux.linearScanNumber)) { if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.blockID(), pred.blockID(), sux.blockID()); + TTY.println(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.getId(), pred.getId(), sux.getId()); } - blockCompleted.set(block.linearScanNumber()); + blockCompleted.set(block.linearScanNumber); // directly resolve between pred and sux (without looking at the empty block between) resolveCollectMappings(pred, sux, moveResolver); if (moveResolver.hasMappings()) { - moveResolver.setInsertPosition(block.lir(), 1); + moveResolver.setInsertPosition(block.lir, 1); moveResolver.resolveAndAppendMoves(); } } @@ -1489,19 +1524,19 @@ for (i = 0; i < numBlocks; i++) { if (!blockCompleted.get(i)) { - LIRBlock fromBlock = blockAt(i); + Block fromBlock = blockAt(i); alreadyResolved.setFrom(blockCompleted); int numSux = fromBlock.numberOfSux(); for (int s = 0; s < numSux; s++) { - LIRBlock toBlock = fromBlock.suxAt(s); + Block toBlock = fromBlock.suxAt(s); // check for duplicate edges between the same blocks (can happen with switch blocks) - if (!alreadyResolved.get(toBlock.linearScanNumber())) { + if (!alreadyResolved.get(toBlock.linearScanNumber)) { if (GraalOptions.TraceLinearScanLevel >= 3) { - TTY.println(" processing edge between B%d and B%d", fromBlock.blockID(), toBlock.blockID()); + TTY.println(" processing edge between B%d and B%d", fromBlock.getId(), toBlock.getId()); } - alreadyResolved.set(toBlock.linearScanNumber()); + alreadyResolved.set(toBlock.linearScanNumber); // collect all intervals that have been split between fromBlock and toBlock resolveCollectMappings(fromBlock, toBlock, moveResolver); @@ -1580,14 +1615,14 @@ if (opId != -1) { if (GraalOptions.DetailedAsserts) { - LIRBlock block = blockForId(opId); - if (block.numberOfSux() <= 1 && opId == block.lastLirInstructionId()) { + Block block = blockForId(opId); + if (block.numberOfSux() <= 1 && opId == block.getLastLirInstructionId()) { // check if spill moves could have been appended at the end of this block, but // before the branch instruction. So the split child information for this branch would // be incorrect. - LIRInstruction instr = block.lir().get(block.lir().size() - 1); + LIRInstruction instr = block.lir.get(block.lir.size() - 1); if (instr instanceof StandardOp.JumpOp) { - if (block.liveOut.get(operandNumber(operand))) { + if (blockData.get(block).liveOut.get(operandNumber(operand))) { assert false : "can't get split child for the last branch of a block because the information would be incorrect (moves are inserted before the branch in resolveDataFlow)"; } } @@ -1687,17 +1722,17 @@ public CiValue doValue(CiValue operand) { int tempOpId = op.id(); OperandMode mode = OperandMode.Input; - LIRBlock block = blockForId(tempOpId); - if (block.numberOfSux() == 1 && tempOpId == block.lastLirInstructionId()) { + Block block = blockForId(tempOpId); + if (block.numberOfSux() == 1 && tempOpId == block.getLastLirInstructionId()) { // generating debug information for the last instruction of a block. // if this instruction is a branch, spill moves are inserted before this branch // and so the wrong operand would be returned (spill moves at block boundaries are not // considered in the live ranges of intervals) // Solution: use the first opId of the branch target block instead. - final LIRInstruction instr = block.lir().get(block.lir().size() - 1); + final LIRInstruction instr = block.lir.get(block.lir.size() - 1); if (instr instanceof StandardOp.JumpOp) { - if (block.liveOut.get(operandNumber(operand))) { - tempOpId = block.suxAt(0).firstLirInstructionId(); + if (blockData.get(block).liveOut.get(operandNumber(operand))) { + tempOpId = block.suxAt(0).getFirstLirInstructionId(); mode = OperandMode.Output; } } @@ -1774,8 +1809,8 @@ private void assignLocations() { IntervalWalker iw = initComputeOopMaps(); - for (LIRBlock block : sortedBlocks) { - assignLocations(block.lir(), iw); + for (Block block : sortedBlocks) { + assignLocations(block.lir, iw); } } @@ -1856,8 +1891,8 @@ TTY.println(); TTY.println("--- Basic Blocks ---"); for (i = 0; i < blockCount(); i++) { - LIRBlock block = blockAt(i); - TTY.print("B%d [%d, %d, %d, %d] ", block.blockID(), block.firstLirInstructionId(), block.lastLirInstructionId(), block.loopIndex(), block.loopDepth()); + Block block = blockAt(i); + TTY.print("B%d [%d, %d, %s] ", block.getId(), block.getFirstLirInstructionId(), block.getLastLirInstructionId(), block.getLoop()); } TTY.println(); TTY.println(); @@ -2017,9 +2052,9 @@ IntervalWalker iw = new IntervalWalker(this, fixedIntervals, otherIntervals); for (int i = 0; i < blockCount(); i++) { - LIRBlock block = blockAt(i); + Block block = blockAt(i); - List instructions = block.lir(); + List instructions = block.lir; for (int j = 0; j < instructions.size(); j++) { LIRInstruction op = instructions.get(j); @@ -2057,13 +2092,13 @@ int numBlocks = blockCount(); for (int i = 0; i < numBlocks; i++) { - LIRBlock block = blockAt(i); - BitMap liveAtEdge = block.liveIn; + Block block = blockAt(i); + BitMap liveAtEdge = blockData.get(block).liveIn; // visit all operands where the liveAtEdge bit is set for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) { if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println("checking interval %d of block B%d", operandNum, block.blockID()); + TTY.println("checking interval %d of block B%d", operandNum, block.getId()); } CiValue operand = operandFor(operandNum); assert isVariable(operand) : "value must have variable operand"; diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java Sun Feb 05 05:40:36 2012 +0100 @@ -35,6 +35,7 @@ import com.oracle.max.graal.compiler.alloc.Interval.RegisterPriority; import com.oracle.max.graal.compiler.alloc.Interval.SpillState; import com.oracle.max.graal.compiler.alloc.Interval.State; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.compiler.lir.StandardOp.*; @@ -60,11 +61,11 @@ return allocator.blockCount(); } - LIRBlock blockAt(int idx) { + Block blockAt(int idx) { return allocator.blockAt(idx); } - LIRBlock blockOfOpWithId(int opId) { + Block blockOfOpWithId(int opId) { return allocator.blockForId(opId); } @@ -231,7 +232,7 @@ // optimized away later in assignRegNums int opId = (operandId + 1) & ~1; - LIRBlock opBlock = allocator.blockForId(opId); + Block opBlock = allocator.blockForId(opId); assert opId > 0 && allocator.blockForId(opId - 2) == opBlock : "cannot insert move at block boundary"; // calculate index of instruction inside instruction list of current block @@ -239,7 +240,7 @@ // numbering of instructions is known. // When the block already contains spill moves, the index must be increased until the // correct index is reached. - List list = opBlock.lir(); + List list = opBlock.lir; int index = (opId - list.get(0).id()) >> 1; assert list.get(index).id() <= opId : "error in calculation"; @@ -251,13 +252,13 @@ assert list.get(index).id() == opId : "error in calculation"; // insert new instruction before instruction at position index - moveResolver.moveInsertPosition(opBlock.lir(), index); + moveResolver.moveInsertPosition(opBlock.lir, index); moveResolver.addMapping(srcIt, dstIt); } - int findOptimalSplitPos(LIRBlock minBlock, LIRBlock maxBlock, int maxSplitPos) { - int fromBlockNr = minBlock.linearScanNumber(); - int toBlockNr = maxBlock.linearScanNumber(); + int findOptimalSplitPos(Block minBlock, Block maxBlock, int maxSplitPos) { + int fromBlockNr = minBlock.linearScanNumber; + int toBlockNr = maxBlock.linearScanNumber; assert 0 <= fromBlockNr && fromBlockNr < blockCount() : "out of range"; assert 0 <= toBlockNr && toBlockNr < blockCount() : "out of range"; @@ -265,19 +266,19 @@ // Try to split at end of maxBlock. If this would be after // maxSplitPos, then use the begin of maxBlock - int optimalSplitPos = maxBlock.lastLirInstructionId() + 2; + int optimalSplitPos = maxBlock.getLastLirInstructionId() + 2; if (optimalSplitPos > maxSplitPos) { - optimalSplitPos = maxBlock.firstLirInstructionId(); + optimalSplitPos = maxBlock.getFirstLirInstructionId(); } - int minLoopDepth = maxBlock.loopDepth(); + int minLoopDepth = maxBlock.getLoopDepth(); for (int i = toBlockNr - 1; i >= fromBlockNr; i--) { - LIRBlock cur = blockAt(i); + Block cur = blockAt(i); - if (cur.loopDepth() < minLoopDepth) { + if (cur.getLoopDepth() < minLoopDepth) { // block with lower loop-depth found . split at the end of this block - minLoopDepth = cur.loopDepth(); - optimalSplitPos = cur.lastLirInstructionId() + 2; + minLoopDepth = cur.getLoopDepth(); + optimalSplitPos = cur.getLastLirInstructionId() + 2; } } assert optimalSplitPos > allocator.maxOpId() || allocator.isBlockBegin(optimalSplitPos) : "algorithm must move split pos to block boundary"; @@ -301,15 +302,15 @@ // reason for using minSplitPos - 1: when the minimal split pos is exactly at the // beginning of a block, then minSplitPos is also a possible split position. // Use the block before as minBlock, because then minBlock.lastLirInstructionId() + 2 == minSplitPos - LIRBlock minBlock = allocator.blockForId(minSplitPos - 1); + Block minBlock = allocator.blockForId(minSplitPos - 1); // reason for using maxSplitPos - 1: otherwise there would be an assert on failure // when an interval ends at the end of the last block of the method // (in this case, maxSplitPos == allocator().maxLirOpId() + 2, and there is no // block at this opId) - LIRBlock maxBlock = allocator.blockForId(maxSplitPos - 1); + Block maxBlock = allocator.blockForId(maxSplitPos - 1); - assert minBlock.linearScanNumber() <= maxBlock.linearScanNumber() : "invalid order"; + assert minBlock.linearScanNumber <= maxBlock.linearScanNumber : "invalid order"; if (minBlock == maxBlock) { // split position cannot be moved to block boundary : so split as late as possible if (GraalOptions.TraceLinearScanLevel >= 4) { @@ -331,13 +332,13 @@ } else { // seach optimal block boundary between minSplitPos and maxSplitPos if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println(" moving split pos to optimal block boundary between block B%d and B%d", minBlock.blockID(), maxBlock.blockID()); + TTY.println(" moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId()); } if (doLoopOptimization) { // Loop optimization: if a loop-end marker is found between min- and max-position : // then split before this loop - int loopEndPos = interval.nextUsageExact(RegisterPriority.LiveAtLoopEnd, minBlock.lastLirInstructionId() + 2); + int loopEndPos = interval.nextUsageExact(RegisterPriority.LiveAtLoopEnd, minBlock.getLastLirInstructionId() + 2); if (GraalOptions.TraceLinearScanLevel >= 4) { TTY.println(" loop optimization: loop end found at pos %d", loopEndPos); } @@ -349,15 +350,15 @@ // the max-position to this loop block. // Desired result: uses tagged as shouldHaveRegister inside a loop cause a reloading // of the interval (normally, only mustHaveRegister causes a reloading) - LIRBlock loopBlock = allocator.blockForId(loopEndPos); + Block loopBlock = allocator.blockForId(loopEndPos); if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println(" interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.blockID(), maxBlock.blockID(), loopBlock.blockID()); + TTY.println(" interval is used in loop that ends in block B%d, so trying to move maxBlock back from B%d to B%d", loopBlock.getId(), maxBlock.getId(), loopBlock.getId()); } assert loopBlock != minBlock : "loopBlock and minBlock must be different because block boundary is needed between"; - optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, loopBlock.lastLirInstructionId() + 2); - if (optimalSplitPos == loopBlock.lastLirInstructionId() + 2) { + optimalSplitPos = findOptimalSplitPos(minBlock, loopBlock, loopBlock.getLastLirInstructionId() + 2); + if (optimalSplitPos == loopBlock.getLastLirInstructionId() + 2) { optimalSplitPos = -1; if (GraalOptions.TraceLinearScanLevel >= 4) { TTY.println(" loop optimization not necessary"); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java Sun Feb 05 05:40:36 2012 +0100 @@ -29,6 +29,7 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.lir.LIRInstruction.*; import com.oracle.max.graal.compiler.util.*; @@ -38,7 +39,7 @@ final class RegisterVerifier { LinearScan allocator; - List workList; // all blocks that must be processed + List workList; // all blocks that must be processed ArrayMap savedStates; // saved information of previous check // simplified access to methods of LinearScan @@ -52,15 +53,15 @@ } // accessors - Interval[] stateForBlock(LIRBlock block) { - return savedStates.get(block.blockID()); + Interval[] stateForBlock(Block block) { + return savedStates.get(block.getId()); } - void setStateForBlock(LIRBlock block, Interval[] savedState) { - savedStates.put(block.blockID(), savedState); + void setStateForBlock(Block block, Interval[] savedState) { + savedStates.put(block.getId(), savedState); } - void addToWorkList(LIRBlock block) { + void addToWorkList(Block block) { if (!workList.contains(block)) { workList.add(block); } @@ -73,7 +74,7 @@ } - void verify(LIRBlock start) { + void verify(Block start) { // setup input registers (method arguments) for first block Interval[] inputState = new Interval[stateSize()]; setStateForBlock(start, inputState); @@ -81,17 +82,17 @@ // main loop for verification do { - LIRBlock block = workList.get(0); + Block block = workList.get(0); workList.remove(0); processBlock(block); } while (!workList.isEmpty()); } - private void processBlock(LIRBlock block) { + private void processBlock(Block block) { if (GraalOptions.TraceLinearScanLevel >= 2) { TTY.println(); - TTY.println("processBlock B%d", block.blockID()); + TTY.println("processBlock B%d", block.getId()); } // must copy state because it is modified @@ -112,16 +113,16 @@ } // process all operations of the block - processOperations(block.lir(), inputState); + processOperations(block.lir, inputState); // iterate all successors for (int i = 0; i < block.numberOfSux(); i++) { - LIRBlock succ = block.suxAt(i); + Block succ = block.suxAt(i); processSuccessor(succ, inputState); } } - private void processSuccessor(LIRBlock block, Interval[] inputState) { + private void processSuccessor(Block block, Interval[] inputState) { Interval[] savedState = stateForBlock(block); if (savedState != null) { @@ -141,7 +142,7 @@ savedState[i] = null; if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println("processSuccessor B%d: invalidating slot %d", block.blockID(), i); + TTY.println("processSuccessor B%d: invalidating slot %d", block.getId(), i); } } } @@ -150,12 +151,12 @@ if (savedStateCorrect) { // already processed block with correct inputState if (GraalOptions.TraceLinearScanLevel >= 2) { - TTY.println("processSuccessor B%d: previous visit already correct", block.blockID()); + TTY.println("processSuccessor B%d: previous visit already correct", block.getId()); } } else { // must re-visit this block if (GraalOptions.TraceLinearScanLevel >= 2) { - TTY.println("processSuccessor B%d: must re-visit because input state changed", block.blockID()); + TTY.println("processSuccessor B%d: must re-visit because input state changed", block.getId()); } addToWorkList(block); } @@ -163,7 +164,7 @@ } else { // block was not processed before, so set initial inputState if (GraalOptions.TraceLinearScanLevel >= 2) { - TTY.println("processSuccessor B%d: initial visit", block.blockID()); + TTY.println("processSuccessor B%d: initial visit", block.getId()); } setStateForBlock(block, copy(inputState)); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Block.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Block.java Sun Feb 05 05:40:36 2012 +0100 @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2009, 2012, 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.oracle.max.graal.compiler.cfg; + +import java.util.*; + +import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.nodes.*; +import com.oracle.max.graal.nodes.java.*; + +public class Block { + protected int id; + + protected BeginNode beginNode; + protected Node endNode; + protected Loop loop; + protected double probability; + + protected List predecessors; + protected List successors; + + protected Block dominator; + protected List dominated; + protected Block postdominator; + + // Fields that still need to be worked on, try to remove them later. + public FrameState lastState; + public List lir; + public boolean align; + public int linearScanNumber; + public LIRPhiMapping phis; + + public Block() { + id = -1; + } + + public int getId() { + assert id >= 0; + return id; + } + + public BeginNode getBeginNode() { + return beginNode; + } + + public Node getEndNode() { + return endNode; + } + + public Loop getLoop() { + return loop; + } + + public int getLoopDepth() { + return loop == null ? 0 : loop.depth; + } + + public boolean isLoopHeader() { + return getBeginNode() instanceof LoopBeginNode; + } + + public boolean isLoopEnd() { + return getEndNode() instanceof LoopEndNode; + } + + public boolean isExceptionEntry() { + return getBeginNode().next() instanceof ExceptionObjectNode; + } + + public List getPredecessors() { + return predecessors; + } + + public List getSuccessors() { + return successors; + } + + public Block getDominator() { + return dominator; + } + + public List getDominated() { + if (dominated == null) { + return Collections.emptyList(); + } + return dominated; + } + + public Block getPostdominator() { + return postdominator; + } + + private class NodeIterator implements Iterator { + private Node cur; + + public NodeIterator() { + cur = getBeginNode(); + } + + @Override + public boolean hasNext() { + return cur != null; + } + + @Override + public Node next() { + Node result = cur; + if (cur == getEndNode()) { + cur = null; + } else { + cur = ((FixedWithNextNode) cur).next(); + } + assert !(cur instanceof BeginNode); + return result; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + public Iterable getNodes() { + return new Iterable() { + @Override + public Iterator iterator() { + return new NodeIterator(); + } + }; + } + + public int getFirstLirInstructionId() { + int result = lir.get(0).id(); + assert result >= 0; + return result; + } + + public int getLastLirInstructionId() { + int result = lir.get(lir.size() - 1).id(); + assert result >= 0; + return result; + } + + @Override + public String toString() { + return "B" + id; + } + + +// to be inlined later on + public int numberOfPreds() { + return getPredecessors().size(); + } + + public int numberOfSux() { + return getSuccessors().size(); + } + + public Block predAt(int i) { + return getPredecessors().get(i); + } + + public Block suxAt(int i) { + return getSuccessors().get(i); + } +// end to be inlined later on +} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/BlockMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/BlockMap.java Sun Feb 05 05:40:36 2012 +0100 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012, 2012, 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.oracle.max.graal.compiler.cfg; + +public class BlockMap { + private final T[] data; + + @SuppressWarnings("unchecked") + public BlockMap(ControlFlowGraph cfg) { + data = (T[]) new Object[cfg.getBlocks().length]; + } + + public T get(Block block) { + return data[block.getId()]; + } + + public void put(Block block, T value) { + data[block.getId()] = value; + } +} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/CFGVerifier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/CFGVerifier.java Sun Feb 05 05:40:36 2012 +0100 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2012, 2012, 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.oracle.max.graal.compiler.cfg; + +public class CFGVerifier { + public static boolean verify(ControlFlowGraph cfg) { + for (Block block : cfg.getBlocks()) { + assert cfg.getBlocks()[block.getId()] == block; + + for (Block pred : block.getPredecessors()) { + assert pred.getSuccessors().contains(block); + assert pred.getId() < block.getId() || pred.isLoopEnd(); + } + + for (Block sux : block.getSuccessors()) { + assert sux.getPredecessors().contains(block); + assert sux.getId() > block.getId() || sux.isLoopHeader(); + } + + if (block.getDominator() != null) { + assert block.getDominator().getId() < block.getId(); + assert block.getDominator().getDominated().contains(block); + } + for (Block dominated : block.getDominated()) { + assert dominated.getId() > block.getId(); + assert dominated.getDominator() == block; + } + + assert cfg.getLoops() == null || !block.isLoopHeader() || block.getLoop().header == block; + } + + if (cfg.getLoops() != null) { + for (Loop loop : cfg.getLoops()) { + assert loop.header.isLoopHeader(); + + for (Block block : loop.blocks) { + assert block.getId() >= loop.header.getId(); + + Loop blockLoop = block.getLoop(); + while (blockLoop != loop) { + blockLoop = blockLoop.parent; + assert blockLoop != null; + } + } + + for (Block block : loop.exits) { + assert block.getId() >= loop.header.getId(); + + Loop blockLoop = block.getLoop(); + while (blockLoop != null) { + blockLoop = blockLoop.parent; + assert blockLoop != loop; + } + } + } + } + + return true; + } +} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/ControlFlowGraph.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/ControlFlowGraph.java Sun Feb 05 05:40:36 2012 +0100 @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2011, 2012, 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.oracle.max.graal.compiler.cfg; + +import java.util.*; + +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.nodes.*; + +public class ControlFlowGraph { + + public final StructuredGraph graph; + + private final NodeMap nodeToBlock; + private Block[] reversePostOrder; + private Loop[] loops; + + public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) { + ControlFlowGraph cfg = new ControlFlowGraph(graph); + cfg.identifyBlocks(); + if (connectBlocks || computeLoops || computeDominators || computePostdominators) { + cfg.connectBlocks(); + } + if (computeLoops) { + cfg.computeLoopInformation(); + } + if (computeDominators) { + cfg.computeDominators(); + } + if (computePostdominators) { + cfg.computePostdominators(); + } + assert CFGVerifier.verify(cfg); + return cfg; + } + + protected ControlFlowGraph(StructuredGraph graph) { + this.graph = graph; + this.nodeToBlock = graph.createNodeMap(); + } + + public Block[] getBlocks() { + return reversePostOrder; + } + + public Block getStartBlock() { + return reversePostOrder[0]; + } + + public NodeMap getNodeToBlock() { + return nodeToBlock; + } + + public Block blockFor(Node node) { + return nodeToBlock.get(node); + } + + public Loop[] getLoops() { + return loops; + } + + private void identifyBlocks() { + // Find all block headers + int numBlocks = 0; + for (Node node : graph.getNodes()) { + if (node instanceof BeginNode) { + Block block = new Block(); + numBlocks++; + + block.beginNode = (BeginNode) node; + Node cur = node; + do { + assert !cur.isDeleted(); + block.endNode = cur; + + assert nodeToBlock.get(cur) == null; + nodeToBlock.set(cur, block); + if (cur instanceof MergeNode) { + for (PhiNode phi : ((MergeNode) cur).phis()) { + nodeToBlock.set(phi, block); + } + } + + if (cur instanceof FixedNode) { + double probability = ((FixedNode) cur).probability(); + if (probability > block.probability) { + block.probability = probability; + } + } + + Node next = null; + for (Node sux : cur.successors()) { + if (sux != null && !(sux instanceof BeginNode)) { + assert next == null; + next = sux; + } + } + cur = next; + } while (cur != null); + } + } + + // Compute reverse postorder. + reversePostOrder = new Block[numBlocks]; + int reversePostOrderId = numBlocks - 1; + + ArrayList stack = new ArrayList<>(); + stack.add(blockFor(graph.start())); + + do { + Block block = stack.get(stack.size() - 1); + if (block.id == -1) { + // First time we see this block: push all successors. + for (Node suxNode : block.getEndNode().cfgSuccessors()) { + Block suxBlock = blockFor(suxNode); + if (suxBlock.id < 0) { + stack.add(suxBlock); + } + } + block.id = -2; + } else { + // Second time we see this block: All successors haved been processed, so insert block into reverse postorder list. + assert block.id == -2; + stack.remove(stack.size() - 1); + block.id = reversePostOrderId; + reversePostOrder[reversePostOrderId] = block; + reversePostOrderId--; + } + } while (!stack.isEmpty()); + assert reversePostOrderId == -1; + } + + // Connect blocks (including loop backward edges). + private void connectBlocks() { + for (Block block : reversePostOrder) { + List predecessors = new ArrayList<>(); + for (Node predNode : block.getBeginNode().cfgPredecessors()) { + predecessors.add(nodeToBlock.get(predNode)); + } + if (block.getBeginNode() instanceof LoopBeginNode) { + predecessors.add(nodeToBlock.get(((LoopBeginNode) block.getBeginNode()).loopEnd())); + } + block.predecessors = predecessors; + + List successors = new ArrayList<>(); + for (Node suxNode : block.getEndNode().cfgSuccessors()) { + successors.add(nodeToBlock.get(suxNode)); + } + if (block.getEndNode() instanceof LoopEndNode) { + successors.add(nodeToBlock.get(((LoopEndNode) block.getEndNode()).loopBegin())); + } + block.successors = successors; + } + } + + private void computeLoopInformation() { + List loopsList = new ArrayList<>(); + for (Block block : reversePostOrder) { + Node beginNode = block.getBeginNode(); + if (beginNode instanceof LoopBeginNode) { + Loop loop = new Loop(block.getLoop(), loopsList.size(), block); + loopsList.add(loop); + + LoopEndNode end = ((LoopBeginNode) beginNode).loopEnd(); + Block endBlock = nodeToBlock.get(end); + computeLoopBlocks(endBlock, loop); + } + } + loops = loopsList.toArray(new Loop[loopsList.size()]); + + for (Loop loop : loops) { + for (Block block : loop.blocks) { + for (Block sux : block.getSuccessors()) { + if (sux.getLoopDepth() < loop.depth) { + loop.exits.add(sux); + } + } + } + } + } + + private void computeLoopBlocks(Block block, Loop loop) { + if (block.getLoop() == loop) { + return; + } + assert block.loop == loop.parent; + block.loop = loop; + + assert !loop.blocks.contains(block); + loop.blocks.add(block); + + if (block != loop.header) { + for (Block pred : block.getPredecessors()) { + computeLoopBlocks(pred, loop); + } + } + } + + private void computeDominators() { + assert reversePostOrder[0].getPredecessors().size() == 0 : "start block has no predecessor and therefore no dominator"; + for (int i = 1; i < reversePostOrder.length; i++) { + Block block = reversePostOrder[i]; + List predecessors = block.getPredecessors(); + assert predecessors.size() > 0; + + if (block.isLoopHeader()) { + // Loop headers have exactly one non-loop predecessor, and that is the dominator. + setDominator(block, predecessors.get(0)); + continue; + } + + Block dominator = predecessors.get(0); + for (int j = 1; j < predecessors.size(); j++) { + Block pred = predecessors.get(j); + dominator = commonDominator(dominator, pred); + } + setDominator(block, dominator); + } + } + + private static void setDominator(Block block, Block dominator) { + block.dominator = dominator; + if (dominator.dominated == null) { + dominator.dominated = new ArrayList<>(); + } + dominator.dominated.add(block); + } + + public static Block commonDominator(Block a, Block b) { + Block iterA = a; + Block iterB = b; + while (iterA != iterB) { + if (iterA.getId() > iterB.getId()) { + iterA = iterA.getDominator(); + } else { + assert iterB.getId() > iterA.getId(); + iterB = iterB.getDominator(); + } + } + return iterA; + } + + private void computePostdominators() { + for (Block block : reversePostOrder) { + if (block.isLoopEnd()) { + // We do not want the loop header registered as the postdominator of the loop end. + continue; + } + Block postdominator = null; + for (Block sux : block.getSuccessors()) { + if (sux.isExceptionEntry()) { + // We ignore exception handlers. + } else if (postdominator == null) { + postdominator = sux; + } else { + postdominator = commonPostdominator(postdominator, sux); + } + } + block.postdominator = postdominator; + } + } + + private static Block commonPostdominator(Block a, Block b) { + Block iterA = a; + Block iterB = b; + while (iterA != iterB) { + if (iterA.getId() < iterB.getId()) { + iterA = iterA.getPostdominator(); + if (iterA == null) { + return null; + } + } else { + assert iterB.getId() < iterA.getId(); + iterB = iterB.getPostdominator(); + if (iterB == null) { + return null; + } + } + } + return iterA; + } +} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Loop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Loop.java Sun Feb 05 05:40:36 2012 +0100 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2012, 2012, 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.oracle.max.graal.compiler.cfg; + +import java.util.*; + +public class Loop { + public final Loop parent; + public final List children; + + public final int depth; + public final int index; + public final Block header; + public final List blocks; + public final List exits; + + protected Loop(Loop parent, int index, Block header) { + this.parent = parent; + if (parent != null) { + this.depth = parent.depth + 1; + parent.children.add(this); + } else { + this.depth = 1; + } + this.index = index; + this.header = header; + this.blocks = new ArrayList<>(); + this.children = new ArrayList<>(); + this.exits = new ArrayList<>(); + } + + @Override + public String toString() { + return "loop " + index + " depth " + depth + (parent != null ? " outer " + parent.index : ""); + } +} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Sun Feb 05 05:40:36 2012 +0100 @@ -46,9 +46,9 @@ import com.oracle.max.cri.xir.*; import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.lir.StandardOp.ParametersOp; -import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.debug.*; import com.oracle.max.graal.graph.*; @@ -77,7 +77,7 @@ protected final RiXirGenerator xir; private final DebugInfoBuilder debugInfoBuilder; - private LIRBlock currentBlock; + private Block currentBlock; private ValueNode currentInstruction; private ValueNode lastInstructionPrinted; // Debugging only private FrameState lastState; @@ -157,12 +157,12 @@ return target; } - private LockScope locksFor(LIRBlock block) { - return blockLocks[block.blockID()]; + private LockScope locksFor(Block block) { + return blockLocks[block.getId()]; } - private void setLocksFor(LIRBlock block, LockScope locks) { - blockLocks[block.blockID()] = locks; + private void setLocksFor(Block block, LockScope locks) { + blockLocks[block.getId()] = locks; } /** @@ -242,7 +242,7 @@ } protected LabelRef getLIRBlock(FixedNode b) { - LIRBlock result = lir.valueToBlock().get(b); + Block result = lir.cfg.blockFor(b); int suxIndex = currentBlock.getSuccessors().indexOf(result); assert suxIndex != -1 : "Block not in successor list of current block"; @@ -287,46 +287,50 @@ TTY.println(op.toStringWithIdPrefix()); TTY.println(); } - currentBlock.lir().add(op); + currentBlock.lir.add(op); } - public void doBlock(LIRBlock block) { + public void doBlock(Block block) { if (GraalOptions.PrintIRWithLIR) { TTY.print(block.toString()); } currentBlock = block; // set up the list of LIR instructions - assert block.lir() == null : "LIR list already computed for this block"; - block.setLir(new ArrayList()); + assert block.lir == null : "LIR list already computed for this block"; + block.lir = new ArrayList<>(); - emitLabel(block.label(), block.align()); + emitLabel(new Label(), block.align); if (GraalOptions.TraceLIRGeneratorLevel >= 1) { - TTY.println("BEGIN Generating LIR for block B" + block.blockID()); + TTY.println("BEGIN Generating LIR for block B" + block.getId()); } - if (block == lir.startBlock()) { + curLocks = null; + for (Block pred : block.getPredecessors()) { + LockScope predLocks = locksFor(pred); + if (curLocks == null) { + curLocks = predLocks; + } else if (curLocks != predLocks && (!pred.isLoopEnd() || predLocks != null)) { + throw new CiBailout("unbalanced monitors: predecessor blocks have different monitor states"); + } + } + + if (block == lir.cfg.getStartBlock()) { assert block.getPredecessors().size() == 0; emitPrologue(); - curLocks = null; } else { assert block.getPredecessors().size() > 0; FrameState fs = null; - curLocks = locksFor(block.predAt(0)); - for (Block p : block.getPredecessors()) { - LIRBlock pred = (LIRBlock) p; + for (Block pred : block.getPredecessors()) { if (fs == null) { - fs = pred.lastState(); - } else if (fs != pred.lastState()) { + fs = pred.lastState; + } else if (fs != pred.lastState) { fs = null; break; } - if (curLocks != locksFor(pred)) { - throw new CiBailout("unbalanced monitors: predecessor blocks have different monitor states"); - } } if (GraalOptions.TraceLIRGeneratorLevel >= 2) { if (fs == null) { @@ -341,17 +345,18 @@ lastState = fs; } - if (GraalOptions.AllocSSA && block.firstNode() instanceof MergeNode) { + if (GraalOptions.AllocSSA && block.getBeginNode() instanceof MergeNode) { block.phis = new LIRPhiMapping(block, this); } - for (int i = 0; i < block.getInstructions().size(); ++i) { - Node instr = block.getInstructions().get(i); + List nodes = lir.nodesFor(block); + for (int i = 0; i < nodes.size(); i++) { + Node instr = nodes.get(i); if (GraalOptions.OptImplicitNullChecks) { Node nextInstr = null; - if (i < block.getInstructions().size() - 1) { - nextInstr = block.getInstructions().get(i + 1); + if (i < nodes.size() - 1) { + nextInstr = nodes.get(i + 1); } if (instr instanceof GuardNode) { @@ -390,19 +395,19 @@ } } } - if (block.numberOfSux() >= 1 && !block.endsWithJump()) { - NodeSuccessorsIterable successors = block.lastNode().successors(); - assert successors.explicitCount() >= 1 : "should have at least one successor : " + block.lastNode(); + if (block.numberOfSux() >= 1 && !endsWithJump(block)) { + NodeSuccessorsIterable successors = block.getEndNode().successors(); + assert successors.count() >= 1 : "should have at least one successor : " + block.getEndNode(); emitJump(getLIRBlock((FixedNode) successors.first()), null); } if (GraalOptions.TraceLIRGeneratorLevel >= 1) { - TTY.println("END Generating LIR for block B" + block.blockID()); + TTY.println("END Generating LIR for block B" + block.getId()); } setLocksFor(currentBlock, curLocks); - block.setLastState(lastState); + block.lastState = lastState; currentBlock = null; if (GraalOptions.PrintIRWithLIR) { @@ -410,6 +415,18 @@ } } + private static boolean endsWithJump(Block block) { + if (block.lir.size() == 0) { + return false; + } + LIRInstruction lirInstruction = block.lir.get(block.lir.size() - 1); + if (lirInstruction instanceof LIRXirInstruction) { + LIRXirInstruction lirXirInstruction = (LIRXirInstruction) lirInstruction; + return (lirXirInstruction.falseSuccessor != null) && (lirXirInstruction.trueSuccessor != null); + } + return lirInstruction instanceof StandardOp.JumpOp; + } + private void doRoot(ValueNode instr) { if (GraalOptions.TraceLIRGeneratorLevel >= 2) { TTY.println("Emitting LIR for instruction " + instr); @@ -480,7 +497,7 @@ @Override public void visitCheckCast(CheckCastNode x) { - XirSnippet snippet = xir.genCheckCast(site(x), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass()); + XirSnippet snippet = xir.genCheckCast(site(x), toXirArgument(x.object()), toXirArgument(x.targetClassInstruction()), x.targetClass(), x.hints(), x.hintsExact()); emitXir(snippet, x, state(), true); // The result of a checkcast is the unmodified object, so no need to allocate a new variable for it. setResult(x, operand(x.object())); @@ -740,7 +757,7 @@ private void emitInstanceOfBranch(InstanceOfNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) { XirArgument obj = toXirArgument(x.object()); - XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass()); + XirSnippet snippet = xir.genInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), x.targetClass(), x.hints(), x.hintsExact()); emitXir(snippet, x, info, null, false, x.negated() ? falseSuccessor : trueSuccessor, x.negated() ? trueSuccessor : falseSuccessor); } @@ -760,8 +777,8 @@ } public Variable emitConditional(BooleanNode node, CiValue trueValue, CiValue falseValue) { - assert trueValue instanceof CiConstant && trueValue.kind.stackKind() == CiKind.Int; - assert falseValue instanceof CiConstant && falseValue.kind.stackKind() == CiKind.Int; + assert trueValue instanceof CiConstant && (trueValue.kind.stackKind() == CiKind.Int || trueValue.kind == CiKind.Long); + assert falseValue instanceof CiConstant && (falseValue.kind.stackKind() == CiKind.Int || trueValue.kind == CiKind.Long); if (node instanceof NullCheckNode) { return emitNullCheckConditional((NullCheckNode) node, trueValue, falseValue); @@ -785,7 +802,7 @@ XirArgument obj = toXirArgument(x.object()); XirArgument trueArg = toXirArgument(x.negated() ? falseValue : trueValue); XirArgument falseArg = toXirArgument(x.negated() ? trueValue : falseValue); - XirSnippet snippet = xir.genMaterializeInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), trueArg, falseArg, x.targetClass()); + XirSnippet snippet = xir.genMaterializeInstanceOf(site(x), obj, toXirArgument(x.targetClassInstruction()), trueArg, falseArg, x.targetClass(), x.hints(), x.hintsExact()); return (Variable) emitXir(snippet, null, null, false); } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIR.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIR.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIR.java Sun Feb 05 05:40:36 2012 +0100 @@ -28,6 +28,7 @@ import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.asm.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; @@ -37,22 +38,23 @@ */ public class LIR { + public final ControlFlowGraph cfg; + /** - * The start block of this LIR. + * The nodes for the blocks. + * TODO: This should go away, we want all nodes connected with a next-pointer. */ - private final LIRBlock startBlock; + private final BlockMap> nodesFor; /** * The linear-scan ordered list of blocks. */ - private final List linearScanOrder; + private final List linearScanOrder; /** * The order in which the code is emitted. */ - private final List codeEmittingOrder; - - private final NodeMap valueToBlock; + private final List codeEmittingOrder; public final List slowPaths; @@ -65,7 +67,6 @@ public SlowPath methodEndMarker; private int numVariables; - private final int numLoops; public SpillMoveFactory spillMoveFactory; @@ -83,37 +84,32 @@ * @param numLoops number of loops * @param compilation the compilation */ - public LIR(LIRBlock startBlock, List linearScanOrder, List codeEmittingOrder, NodeMap valueToBlock, int numLoops) { + public LIR(ControlFlowGraph cfg, BlockMap> nodesFor, List linearScanOrder, List codeEmittingOrder) { + this.cfg = cfg; + this.nodesFor = nodesFor; this.codeEmittingOrder = codeEmittingOrder; this.linearScanOrder = linearScanOrder; - this.startBlock = startBlock; - this.valueToBlock = valueToBlock; - this.numLoops = numLoops; slowPaths = new ArrayList<>(); deoptimizationStubs = new ArrayList<>(); } + public List nodesFor(Block block) { + return nodesFor.get(block); + } + /** * Gets the linear scan ordering of blocks as a list. * @return the blocks in linear scan order */ - public List linearScanOrder() { + public List linearScanOrder() { return linearScanOrder; } - public List codeEmittingOrder() { + public List codeEmittingOrder() { return codeEmittingOrder; } - public LIRBlock startBlock() { - return startBlock; - } - - public NodeMap valueToBlock() { - return valueToBlock; - } - public int numVariables() { return numVariables; } @@ -127,7 +123,7 @@ printLIR(codeEmittingOrder()); } - for (LIRBlock b : codeEmittingOrder()) { + for (Block b : codeEmittingOrder()) { emitBlock(tasm, b); } @@ -143,16 +139,16 @@ emitSlowPath(tasm, methodEndMarker); } - private void emitBlock(TargetMethodAssembler tasm, LIRBlock block) { + private void emitBlock(TargetMethodAssembler tasm, Block block) { if (GraalOptions.PrintLIRWithAssembly) { - block.printWithoutPhis(TTY.out()); + TTY.println(block.toString()); } if (GraalOptions.CommentedAssembly) { - tasm.blockComment(String.format("block B%d loop %d depth %d", block.blockID(), block.loopIndex(), block.loopDepth())); + tasm.blockComment(String.format("block B%d %s", block.getId(), block.getLoop())); } - for (LIRInstruction op : block.lir()) { + for (LIRInstruction op : block.lir) { if (GraalOptions.CommentedAssembly) { tasm.blockComment(String.format("%d %s", op.id(), op)); } @@ -208,9 +204,9 @@ } - public static void printBlock(LIRBlock x) { + public static void printBlock(Block x) { // print block id - TTY.print("B%d ", x.blockID()); + TTY.print("B%d ", x.getId()); // print flags if (x.isLoopHeader()) { @@ -227,39 +223,35 @@ if (x.numberOfPreds() > 0) { TTY.print("preds: "); for (int i = 0; i < x.numberOfPreds(); i++) { - TTY.print("B%d ", x.predAt(i).blockID()); + TTY.print("B%d ", x.predAt(i).getId()); } } if (x.numberOfSux() > 0) { TTY.print("sux: "); for (int i = 0; i < x.numberOfSux(); i++) { - TTY.print("B%d ", x.suxAt(i).blockID()); + TTY.print("B%d ", x.suxAt(i).getId()); } } TTY.println(); } - public static void printLIR(List blocks) { + public static void printLIR(List blocks) { if (TTY.isSuppressed()) { return; } TTY.println("LIR:"); int i; for (i = 0; i < blocks.size(); i++) { - LIRBlock bb = blocks.get(i); + Block bb = blocks.get(i); printBlock(bb); TTY.println("__id_Instruction___________________________________________"); - for (LIRInstruction op : bb.lir()) { + for (LIRInstruction op : bb.lir) { TTY.println(op.toStringWithIdPrefix()); TTY.println(); } TTY.println(); } } - - public int numLoops() { - return numLoops; - } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2009, 2012, 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.oracle.max.graal.compiler.lir; - -import java.util.*; - -import com.oracle.max.asm.*; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.compiler.schedule.*; -import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.nodes.*; -import com.oracle.max.graal.nodes.java.*; - -/** - * The {@code LIRBlock} class definition. - */ -public final class LIRBlock extends Block { - - public static final IdentifyBlocksPhase.BlockFactory FACTORY = new IdentifyBlocksPhase.BlockFactory() { - @Override - public Block createBlock(int blockID) { - return new LIRBlock(blockID); - } - }; - - public final Label label; - private List lir; - private FrameState lastState; - - private boolean align; - - private int linearScanNumber; - - public LIRPhiMapping phis; - - /** - * Bit map specifying which {@linkplain OperandPool operands} are live upon entry to this block. - * These are values used in this block or any of its successors where such value are not defined - * in this block. - * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}. - */ - public BitMap liveIn; - - /** - * Bit map specifying which {@linkplain OperandPool operands} are live upon exit from this block. - * These are values used in a successor block that are either defined in this block or were live - * upon entry to this block. - * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}. - */ - public BitMap liveOut; - - /** - * Bit map specifying which {@linkplain OperandPool operands} are used (before being defined) in this block. - * That is, these are the values that are live upon entry to the block. - * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}. - */ - public BitMap liveGen; - - /** - * Bit map specifying which {@linkplain OperandPool operands} are defined/overwritten in this block. - * The bit index of an operand is its {@linkplain OperandPool#operandNumber(com.sun.cri.ci.CiValue) operand number}. - */ - public BitMap liveKill; - - private int firstLirInstructionID; - private int lastLirInstructionID; - - - public LIRBlock(int blockID) { - super(blockID); - label = new Label(); - } - - public int firstLirInstructionId() { - return firstLirInstructionID; - } - - public boolean align() { - return align; - } - - public void setAlign(boolean b) { - align = b; - } - - public void setFirstLirInstructionId(int firstLirInstructionId) { - this.firstLirInstructionID = firstLirInstructionId; - } - - public int lastLirInstructionId() { - return lastLirInstructionID; - } - - public void setLastLirInstructionId(int lastLirInstructionId) { - this.lastLirInstructionID = lastLirInstructionId; - } - - public List lir() { - return lir; - } - - public void setLir(List lir) { - this.lir = lir; - } - - public void printWithoutPhis(LogStream out) { - out.println("LIR Block " + blockID()); - } - - public int numberOfPreds() { - return predecessors.size(); - } - - public int numberOfSux() { - return successors.size(); - } - - public boolean isPredecessor(LIRBlock block) { - return predecessors.contains(block); - } - - public LIRBlock predAt(int i) { - return (LIRBlock) predecessors.get(i); - } - - public LIRBlock suxAt(int i) { - return (LIRBlock) successors.get(i); - } - - @SuppressWarnings({"unchecked", "cast"}) - public List getLIRSuccessors() { - return (List) (List) super.getSuccessors(); - } - - @SuppressWarnings({"unchecked", "cast"}) - public List getLIRPredecessors() { - return (List) (List) super.getPredecessors(); - } - - - @Override - public String toString() { - return "B" + blockID(); - } - - public Label label() { - return label; - } - - public void setLinearScanNumber(int v) { - linearScanNumber = v; - } - - public int linearScanNumber() { - return linearScanNumber; - } - - public void replaceWith(LIRBlock other) { - for (Block pred : predecessors) { - Util.replaceAllInList(this, other, ((LIRBlock) pred).successors); - } - for (int i = 0; i < other.predecessors.size(); ++i) { - if (other.predecessors.get(i) == this) { - other.predecessors.remove(i); - other.predecessors.addAll(i, this.predecessors); - } - } - successors.clear(); - predecessors.clear(); - } - - public void setLastState(FrameState fs) { - lastState = fs; - } - - public FrameState lastState() { - return lastState; - } - - public boolean endsWithJump() { - if (lir.size() == 0) { - return false; - } - LIRInstruction lirInstruction = lir.get(lir.size() - 1); - if (lirInstruction instanceof LIRXirInstruction) { - LIRXirInstruction lirXirInstruction = (LIRXirInstruction) lirInstruction; - return (lirXirInstruction.falseSuccessor != null) && (lirXirInstruction.trueSuccessor != null); - } - return lirInstruction instanceof StandardOp.JumpOp; - } - - public boolean isExceptionEntry() { - return firstNode() instanceof ExceptionObjectNode; - } -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRPhiMapping.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRPhiMapping.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRPhiMapping.java Sun Feb 05 05:40:36 2012 +0100 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; @@ -33,16 +34,16 @@ import com.oracle.max.graal.nodes.PhiNode.*; public class LIRPhiMapping { - private final LIRBlock block; + private final Block block; private CiValue[][] inputs; private CiValue[] results; - public LIRPhiMapping(LIRBlock block, LIRGenerator gen) { + public LIRPhiMapping(Block block, LIRGenerator gen) { this.block = block; - assert block.firstNode() instanceof MergeNode : "phi functions are only present at control flow merges"; - MergeNode mergeNode = (MergeNode) block.firstNode(); + assert block.getBeginNode() instanceof MergeNode : "phi functions are only present at control flow merges"; + MergeNode mergeNode = (MergeNode) block.getBeginNode(); List phis = mergeNode.phis().snapshot(); for (int i = 0; i < phis.size(); i++) { @@ -54,8 +55,8 @@ } public void fillInputs(LIRGenerator gen) { - assert block.firstNode() instanceof MergeNode : "phi functions are only present at control flow merges"; - MergeNode mergeNode = (MergeNode) block.firstNode(); + assert block.getBeginNode() instanceof MergeNode : "phi functions are only present at control flow merges"; + MergeNode mergeNode = (MergeNode) block.getBeginNode(); List phis = mergeNode.phis().snapshot(); int numPhis = 0; @@ -75,7 +76,7 @@ if (phi.type() == PhiType.Value) { results[phiIdx] = gen.operand(phi); for (int j = 0; j < numPreds; j++) { - assert j == mergeNode.phiPredecessorIndex((FixedNode) block.predAt(j).lastNode()) : "block predecessors and node predecessors must have same order"; + assert j == mergeNode.phiPredecessorIndex((FixedNode) block.predAt(j).getEndNode()) : "block predecessors and node predecessors must have same order"; inputs[j][phiIdx] = gen.operand(phi.valueAt(j)); } phiIdx++; @@ -88,7 +89,7 @@ return results; } - public CiValue[] inputs(LIRBlock pred) { + public CiValue[] inputs(Block pred) { assert pred.numberOfSux() == 1 && pred.suxAt(0) == block; return inputs[block.getPredecessors().indexOf(pred)]; } @@ -96,7 +97,7 @@ private static final EnumSet INPUT_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); private static final EnumSet OUTPUT_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack); - public void forEachInput(LIRBlock pred, PhiValueProcedure proc) { + public void forEachInput(Block pred, PhiValueProcedure proc) { CiValue[] predInputs = inputs(pred); for (int i = 0; i < predInputs.length; i++) { predInputs[i] = proc.doValue(predInputs[i], results[i]); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRVerifier.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRVerifier.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRVerifier.java Sun Feb 05 05:40:36 2012 +0100 @@ -29,11 +29,11 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.criutils.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; -import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.util.*; public final class LIRVerifier { @@ -46,10 +46,10 @@ private final Object[] variableDefinitions; private BitSet liveOutFor(Block block) { - return blockLiveOut[block.blockID()]; + return blockLiveOut[block.getId()]; } private void setLiveOutFor(Block block, BitSet liveOut) { - blockLiveOut[block.blockID()] = liveOut; + blockLiveOut[block.getId()] = liveOut; } private int maxRegisterNum() { @@ -91,7 +91,7 @@ private BitSet curVariablesLive; private CiValue[] curRegistersLive; - private LIRBlock curBlock; + private Block curBlock; private Object curInstruction; private BitSet curRegistersDefined; @@ -100,13 +100,13 @@ ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { return def(value, mode, flags); } }; curRegistersDefined = new BitSet(); - for (LIRBlock block : lir.linearScanOrder()) { + for (Block block : lir.linearScanOrder()) { curBlock = block; curVariablesLive = new BitSet(); curRegistersLive = new CiValue[maxRegisterNum()]; - if (block.dominator() != null) { - curVariablesLive.or(liveOutFor(block.dominator())); + if (block.getDominator() != null) { + curVariablesLive.or(liveOutFor(block.getDominator())); } if (block.phis != null) { @@ -115,13 +115,13 @@ block.phis.forEachOutput(defProc); } - assert block.lir().get(0) instanceof StandardOp.LabelOp : "block must start with label"; + assert block.lir.get(0) instanceof StandardOp.LabelOp : "block must start with label"; if (block.numberOfSux() > 0) { - LIRInstruction last = block.lir().get(block.lir().size() - 1); + LIRInstruction last = block.lir.get(block.lir.size() - 1); assert last instanceof StandardOp.JumpOp || last instanceof LIRXirInstruction : "block with successor must end with unconditional jump"; } - for (LIRInstruction op : block.lir()) { + for (LIRInstruction op : block.lir) { curInstruction = op; op.forEachInput(useProc); @@ -139,7 +139,7 @@ curInstruction = null; } - for (LIRBlock sux : block.getLIRSuccessors()) { + for (Block sux : block.getSuccessors()) { if (sux.phis != null) { assert beforeRegisterAllocation; curInstruction = sux.phis; diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LabelRef.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LabelRef.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LabelRef.java Sun Feb 05 05:40:36 2012 +0100 @@ -23,9 +23,10 @@ package com.oracle.max.graal.compiler.lir; import com.oracle.max.asm.*; +import com.oracle.max.graal.compiler.cfg.*; /** - * LIR instructions such as JUMP and BRANCH need to reference their target {@link LIRBlock}. However, + * LIR instructions such as JUMP and BRANCH need to reference their target {@link Block}. However, * direct references are not possible since the control flow graph (and therefore successors lists) can * be changed by optimizations - and fixing the instructions is error prone. * Therefore, we only reference of block B from block A only via the tuple (A, successor-index-of-B), i.e., @@ -66,11 +67,11 @@ * @param suxIndex The index of the successor. * @return The newly created label reference. */ - public static LabelRef forSuccessor(final LIRBlock block, final int suxIndex) { + public static LabelRef forSuccessor(final Block block, final int suxIndex) { return new LabelRef() { @Override public Label label() { - return block.suxAt(suxIndex).label(); + return ((StandardOp.LabelOp) block.suxAt(suxIndex).lir.get(0)).getLabel(); } @Override diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOp.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOp.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOp.java Sun Feb 05 05:40:36 2012 +0100 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.max.asm.*; import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.asm.*; import com.oracle.max.graal.compiler.util.*; @@ -39,6 +40,7 @@ * The first operation of every block must implement this interface. */ public interface LabelOp { + Label getLabel(); } /** diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/loop/Loop.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/loop/Loop.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -/* - * 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.oracle.max.graal.compiler.loop; - -import java.util.*; - -import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.nodes.*; - -public class Loop { - private final LoopBeginNode loopBegin; - private Loop parent; - private final List children; - private final NodeBitMap exits; - private final NodeBitMap directCFGNodes; - private NodeBitMap loopVariant; - private boolean finished; - - public Loop(LoopBeginNode loopBegin) { - this.loopBegin = loopBegin; - this.children = new ArrayList<>(1); - this.exits = loopBegin.graph().createNodeBitMap(); - this.directCFGNodes = loopBegin.graph().createNodeBitMap(); - } - - public LoopBeginNode loopBegin() { - return loopBegin; - } - - public Loop parent() { - return parent; - } - - public boolean isFinished() { - return finished; - } - - public void setFinished() { - finished = true; - } - - public List children() { - return children; - } - - public NodeBitMap exits() { - return exits; - } - - public boolean isLoopExit(FixedNode node) { - return exits.isMarked(node); - } - - public boolean isChildOf(Loop l) { - return parent == l || (parent != null && parent.isChildOf(l)); - } - - public boolean containsDirectFixed(FixedNode n) { - return directCFGNodes.isMarked(n); - } - - public boolean containsFixed(FixedNode n) { - if (containsDirectFixed(n)) { - return true; - } - for (Loop child : children()) { - if (child.containsFixed(n)) { - return true; - } - } - return false; - } - - public boolean isLoopInvariant(ValueNode value) { - if (loopVariant().isMarked(value)) { - return false; - } - for (Loop child : children()) { - if (!child.isLoopInvariant(value)) { - return false; - } - } - return true; - } - - @SuppressWarnings("unchecked") - public Iterable directFixedNodes() { - return (Iterable) directCFGNodes; - } - - public void addChildren(Loop loop) { - this.children.add(loop); - loop.parent = this; - } - - NodeBitMap directCFGNodes() { - return directCFGNodes; - } - - @Override - public String toString() { - return "Loop " + loopBegin(); - } - - NodeBitMap loopVariant() { - if (loopVariant == null) { - loopVariant = loopBegin().graph().createNodeBitMap(); - NodeFlood work = loopBegin().graph().createNodeFlood(); - work.addAll(directCFGNodes); - for (Node n : work) { - loopVariant.mark(n); - work.addAll(n.usages()); - } - } - return loopVariant; - } - - public int depth() { - if (parent() == null) { - return 0; - } - return parent().depth() + 1; - } - - public int directFixedNodesCount() { - return directCFGNodes.cardinality(); - } - - public int fixedNodesCount() { - int count = directFixedNodesCount(); - for (Loop child : children()) { - count += child.directFixedNodesCount(); - } - return count; - } - - public int exitsCount() { - return exits().cardinality(); - } -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/loop/LoopInfo.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/loop/LoopInfo.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * 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.oracle.max.graal.compiler.loop; - -import java.util.*; - -import com.oracle.max.criutils.*; -import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.util.*; - -public class LoopInfo { - private final NodeMap nodeToLoop; - private final List rootLoops; - - public LoopInfo(NodeMap nodeToLoop, List rootLoops) { - this.nodeToLoop = nodeToLoop; - this.rootLoops = rootLoops; - } - - public Loop loop(Node n) { - return nodeToLoop.get(n); - } - - public List rootLoops() { - return rootLoops; - } - - public Iterable loops() { - return new Iterable() { - @Override - public Iterator iterator() { - return new TreeIterators.PrefixTreeIterator(rootLoops()) { - @Override - protected Iterable children(Loop node) { - return node.children(); - } - }; - } - }; - } - - public void print() { - for (Loop loop : rootLoops) { - print(loop); - } - } - - private void print(final Loop loop) { - TTY.out().printf("%s\n", loop.loopBegin()); - TTY.out().println("-- exits"); - TTY.out().adjustIndentation(+2); - for (Node n : loop.exits()) { - TTY.out().printf("%s from %s\n", n, n.predecessor()); - } - TTY.out().adjustIndentation(-2); - TTY.out().println("-- directNodes"); - TTY.out().adjustIndentation(+2); - for (final Node node : loop.directFixedNodes()) { - TTY.out().printf("%s\n", node); - } - TTY.out().adjustIndentation(-2); - TTY.out().println("-- subloops"); - TTY.out().adjustIndentation(+2); - for (Loop sub : loop.children()) { - print(sub); - } - TTY.out().adjustIndentation(-2); - TTY.out().println("-- sub"); - } -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/loop/LoopUtil.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/loop/LoopUtil.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -/* - * 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.oracle.max.graal.compiler.loop; - -import java.util.*; - -import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.nodes.*; - - -public class LoopUtil { - - public static LoopInfo computeLoopInfo(Graph graph) { - // Create node-to-loop relation. - NodeMap nodeToLoop = graph.createNodeMap(); - for (LoopBeginNode begin : graph.getNodes(LoopBeginNode.class)) { - mark(begin, nodeToLoop); - } - - List rootLoops = new ArrayList<>(1); - LoopInfo info = new LoopInfo(nodeToLoop, rootLoops); - - // Get parent-child relationships between loops. - for (LoopBeginNode begin : graph.getNodes(LoopBeginNode.class)) { - Loop loop = nodeToLoop.get(begin); - Loop parentLoop = nodeToLoop.get(begin.forwardEdge()); - if (parentLoop != null) { - parentLoop.addChildren(loop); - } else { - rootLoops.add(loop); - } - } - - //Find exits - for (Loop loop : info.loops()) { - for (FixedNode n : loop.directFixedNodes()) { - if (n instanceof ControlSplitNode) { - for (BeginNode sux : ((ControlSplitNode) n).blockSuccessors()) { - Loop l = loop; - while (l != null && !l.containsFixed(sux)) { - l.exits().mark(sux); - l = l.parent(); - } - } - } - } - } - - return info; - } - - private static void mark(LoopBeginNode begin, NodeMap nodeToLoop) { - - if (nodeToLoop.get(begin) != null) { - // Loop already processed. - return; - } - Loop loop = new Loop(begin); - nodeToLoop.set(begin, loop); - - NodeFlood workCFG = begin.graph().createNodeFlood(); - workCFG.add(begin.loopEnd()); - for (Node n : workCFG) { - if (n == begin) { - // Stop at loop begin. - continue; - } - markNode(n, loop, nodeToLoop); - - for (Node pred : n.cfgPredecessors()) { - workCFG.add(pred); - } - } - - // We finished marking the loop. - loop.setFinished(); - } - - private static void markNode(Node n, Loop loop, NodeMap nodeToLoop) { - Loop oldMark = nodeToLoop.get(n); - if (oldMark == null || !oldMark.isFinished()) { - - // We have an inner loop, start marking it. - if (n instanceof LoopBeginNode) { - mark((LoopBeginNode) n, nodeToLoop); - } else { - if (oldMark != null) { - oldMark.directCFGNodes().clear(n); - } - nodeToLoop.set(n, loop); - loop.directCFGNodes().mark(n); - } - } - } -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/BoxingEliminationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/BoxingEliminationPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/BoxingEliminationPhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -22,11 +22,14 @@ */ package com.oracle.max.graal.compiler.phases; +import static com.oracle.max.graal.graph.iterators.NodePredicates.*; + import java.util.*; import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.graph.iterators.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.PhiNode.*; import com.oracle.max.graal.nodes.extended.*; @@ -106,11 +109,9 @@ virtualizeUsages(boxNode, boxNode.source(), boxNode.exactType()); - for (Node n : boxNode.usages()) { - if (!(n instanceof FrameState) && !(n instanceof VirtualObjectFieldNode)) { - // Elimination failed, because boxing object escapes. - return; - } + if (boxNode.usages().filter(isNotA(FrameState.class).nor(VirtualObjectFieldNode.class)).isNotEmpty()) { + // Elimination failed, because boxing object escapes. + return; } // TODO(ls) this seems weird: there might still be references to boxNode, yet it is deleted... @@ -125,7 +126,7 @@ private static void virtualizeUsages(ValueNode boxNode, ValueNode replacement, RiResolvedType exactType) { ValueNode virtualValueNode = null; VirtualObjectNode virtualObjectNode = null; - for (Node n : boxNode.usages().filter(FrameState.class).or(VirtualObjectFieldNode.class).snapshot()) { + for (Node n : boxNode.usages().filter(NodePredicates.isA(FrameState.class).or(VirtualObjectFieldNode.class)).snapshot()) { if (virtualValueNode == null) { virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(exactType, replacement)); } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.compiler.phases; +import static com.oracle.max.graal.graph.iterators.NodePredicates.*; + import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.graal.debug.*; @@ -63,7 +65,7 @@ Tool tool = new Tool(nodeWorkList, runtime, target, assumptions); for (Node node : nodeWorkList) { if (node instanceof Canonicalizable) { - Debug.log("Canonicalizer: work on %1s"); + Debug.log("Canonicalizer: work on %s", node); graph.mark(); ValueNode canonical = ((Canonicalizable) node).canonical(tool); // cases: original node: @@ -232,8 +234,8 @@ if (node instanceof PhiNode) { node.replaceFirstInput(input, null); } else { - for (Node usage : node.usages().snapshot()) { - if ((usage instanceof FloatingNode || usage instanceof CallTargetNode) && !usage.isDeleted()) { + for (Node usage : node.usages().filter(isA(FloatingNode.class).or(CallTargetNode.class)).snapshot()) { + if (!usage.isDeleted()) { killNonCFG(usage, node); } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/EscapeAnalysisPhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -306,7 +306,7 @@ private static Node escape(EscapeRecord record, Node usage) { final Node node = record.node; if (usage instanceof FrameState) { - assert ((FrameState) usage).inputs().contains(node); + assert usage.inputs().contains(node); return null; } else { if (usage instanceof FixedNode) { diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/FloatingReadPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/FloatingReadPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/FloatingReadPhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -25,8 +25,7 @@ import java.util.*; import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.compiler.loop.*; -import com.oracle.max.graal.compiler.schedule.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.debug.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; @@ -90,7 +89,7 @@ Node current = anyLocationNode; if (anyLocationNode instanceof PhiNode) { PhiNode phiNode = (PhiNode) anyLocationNode; - if (phiNode.merge() == block.firstNode()) { + if (phiNode.merge() == block.getBeginNode()) { PhiNode phiCopy = (PhiNode) phiNode.copyWithInputs(); phiCopy.removeInput(phiCopy.valueCount() - 1); current = phiCopy; @@ -109,7 +108,7 @@ Debug.log("Nothing to merge both nodes are %s.", original); return; } - MergeNode m = (MergeNode) mergeBlock.firstNode(); + MergeNode m = (MergeNode) mergeBlock.getBeginNode(); if (m.isPhiAtMerge(original)) { PhiNode phi = (PhiNode) original; phi.addInput((ValueNode) newValue); @@ -188,7 +187,7 @@ } private void createLoopEntryPhi(Object modifiedLocation, Node other, Loop loop) { - PhiNode phi = other.graph().unique(new PhiNode(CiKind.Illegal, loop.loopBegin(), PhiType.Memory)); + PhiNode phi = other.graph().unique(new PhiNode(CiKind.Illegal, (MergeNode) loop.header.getBeginNode(), PhiType.Memory)); phi.addInput((ValueNode) other); map.put(modifiedLocation, phi); loopEntryMap.put(modifiedLocation, phi); @@ -206,43 +205,43 @@ // Add start node write checkpoint. addStartCheckpoint(graph); - LoopInfo loopInfo = LoopUtil.computeLoopInfo(graph); + // Identify blocks. + ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false); + Block[] blocks = cfg.getBlocks(); HashMap> modifiedValues = new HashMap<>(); // Initialize modified values to empty hash set. - for (Loop loop : loopInfo.loops()) { + for (Loop loop : cfg.getLoops()) { modifiedValues.put(loop, new HashSet<>()); } // Get modified values in loops. for (Node n : graph.getNodes()) { - Loop loop = loopInfo.loop(n); - if (loop != null) { + Block block = cfg.blockFor(n); + if (block != null && block.getLoop() != null) { if (n instanceof WriteNode) { WriteNode writeNode = (WriteNode) n; - traceWrite(loop, writeNode.location().locationIdentity(), modifiedValues); + traceWrite(block.getLoop(), writeNode.location().locationIdentity(), modifiedValues); } else if (n instanceof MemoryCheckpoint) { - traceMemoryCheckpoint(loop, modifiedValues); + traceMemoryCheckpoint(block.getLoop(), modifiedValues); } } } // Propagate values to parent loops. - for (Loop loop : loopInfo.rootLoops()) { - propagateFromChildren(loop, modifiedValues); + for (Loop loop : cfg.getLoops()) { + if (loop.depth == 1) { + propagateFromChildren(loop, modifiedValues); + } } Debug.log("Modified values: %s.", modifiedValues); - // Identify blocks. - final IdentifyBlocksPhase s = new IdentifyBlocksPhase(false); - s.apply(graph); - List blocks = s.getBlocks(); // Process blocks (predecessors first). - MemoryMap[] memoryMaps = new MemoryMap[blocks.size()]; + MemoryMap[] memoryMaps = new MemoryMap[blocks.length]; for (final Block b : blocks) { - processBlock(b, memoryMaps, s.getNodeToBlock(), modifiedValues, loopInfo); + processBlock(b, memoryMaps, cfg.getNodeToBlock(), modifiedValues); } } @@ -254,41 +253,28 @@ } } - private void processBlock(Block b, MemoryMap[] memoryMaps, NodeMap nodeToBlock, HashMap> modifiedValues, LoopInfo loopInfo) { - - // Visit every block at most once. - if (memoryMaps[b.blockID()] != null) { - return; - } - - // Process predecessors before this block. - for (Block pred : b.getPredecessors()) { - processBlock(pred, memoryMaps, nodeToBlock, modifiedValues, loopInfo); - } - - + private static void processBlock(Block b, MemoryMap[] memoryMaps, NodeMap nodeToBlock, HashMap> modifiedValues) { // Create initial memory map for the block. MemoryMap map = null; if (b.getPredecessors().size() == 0) { map = new MemoryMap(b); } else { - map = new MemoryMap(b, memoryMaps[b.getPredecessors().get(0).blockID()]); + map = new MemoryMap(b, memoryMaps[b.getPredecessors().get(0).getId()]); if (b.isLoopHeader()) { - assert b.getPredecessors().size() == 1; - Loop loop = loopInfo.loop(b.firstNode()); + Loop loop = b.getLoop(); map.createLoopEntryMemoryMap(modifiedValues.get(loop), loop); } else { for (int i = 1; i < b.getPredecessors().size(); ++i) { - assert b.firstNode() instanceof MergeNode : b.firstNode(); + assert b.getBeginNode() instanceof MergeNode : b.getBeginNode(); Block block = b.getPredecessors().get(i); - map.mergeWith(memoryMaps[block.blockID()], b); + map.mergeWith(memoryMaps[block.getId()], b); } } } - memoryMaps[b.blockID()] = map; + memoryMaps[b.getId()] = map; // Process instructions of this block. - for (Node n : b.getInstructions()) { + for (Node n : b.getNodes()) { if (n instanceof ReadNode) { ReadNode readNode = (ReadNode) n; map.processRead(readNode); @@ -302,12 +288,12 @@ } - if (b.lastNode() instanceof LoopEndNode) { - LoopEndNode end = (LoopEndNode) b.lastNode(); + if (b.getEndNode() instanceof LoopEndNode) { + LoopEndNode end = (LoopEndNode) b.getEndNode(); LoopBeginNode begin = end.loopBegin(); Block beginBlock = nodeToBlock.get(begin); - MemoryMap memoryMap = memoryMaps[beginBlock.blockID()]; - assert memoryMap != null : beginBlock.name(); + MemoryMap memoryMap = memoryMaps[beginBlock.getId()]; + assert memoryMap != null; assert memoryMap.getLoopEntryMap() != null; memoryMap.mergeLoopEntryWith(map, begin); } @@ -318,7 +304,7 @@ } private void propagateFromChildren(Loop loop, HashMap> modifiedValues) { - for (Loop child : loop.children()) { + for (Loop child : loop.children) { propagateFromChildren(child, modifiedValues); modifiedValues.get(loop).addAll(modifiedValues.get(child)); } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -47,7 +47,7 @@ private final CiTarget target; private final GraalRuntime runtime; - private final Collection hints; + private final Collection hints; private final PriorityQueue inlineCandidates = new PriorityQueue<>(); private CiAssumptions assumptions; @@ -58,7 +58,7 @@ private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed"); private static final DebugMetric metricInliningConsidered = Debug.metric("InliningConsidered"); - public InliningPhase(CiTarget target, GraalRuntime runtime, Collection hints, CiAssumptions assumptions, PhasePlan plan) { + public InliningPhase(CiTarget target, GraalRuntime runtime, Collection hints, CiAssumptions assumptions, PhasePlan plan) { this.target = target; this.runtime = runtime; this.hints = hints; @@ -125,11 +125,8 @@ Invoke invoke = (Invoke) node; scanInvoke(invoke, level); } - for (Node usage : node.usages().snapshot()) { - if (usage instanceof Invoke) { - Invoke invoke = (Invoke) usage; - scanInvoke(invoke, level); - } + for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) { + scanInvoke((Invoke) usage, level); } } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012, 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.oracle.max.graal.compiler.phases; + +import com.oracle.max.graal.nodes.*; + +public class InsertStateAfterPlaceholderPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + for (ReturnNode ret : graph.getNodes(ReturnNode.class)) { + PlaceholderNode p = graph.add(new PlaceholderNode()); + p.setStateAfter(graph.add(new FrameState(null, FrameState.AFTER_BCI, 0, 0, false))); + graph.addBeforeFixed(ret, p); + } + } + +} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/IntrinsificationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/IntrinsificationPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/IntrinsificationPhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -25,6 +25,7 @@ import com.oracle.max.cri.ri.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.cri.*; +import com.oracle.max.graal.debug.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; @@ -58,6 +59,7 @@ intrinsicGraph = runtime.intrinsicGraph(invoke.stateAfter().method(), invoke.bci(), target, invoke.callTarget().arguments()); } if (intrinsicGraph != null) { + Debug.log(" > Intrinsify %s", target); InliningUtil.inline(invoke, intrinsicGraph, true); } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -23,7 +23,7 @@ package com.oracle.max.graal.compiler.phases; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.schedule.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.cri.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; @@ -39,13 +39,11 @@ @Override protected void run(final StructuredGraph graph) { - final IdentifyBlocksPhase s = new IdentifyBlocksPhase(false); - s.apply(graph); - s.calculateAlwaysReachedBlock(); + ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, true); NodeBitMap processed = graph.createNodeBitMap(); NodeBitMap activeGuards = graph.createNodeBitMap(); - processBlock(s.getStartBlock(), activeGuards, processed, null); + processBlock(cfg.getStartBlock(), activeGuards, processed, null); processed.negate(); final CiLoweringTool loweringTool = new CiLoweringTool() { @@ -62,6 +60,7 @@ @Override public Node createGuard(Node condition) { + // TODO(tw): Explain why this must not be called on floating nodes. throw new UnsupportedOperationException(); } }; @@ -77,21 +76,21 @@ FixedNode anchor = parentAnchor; if (anchor == null) { - anchor = block.createAnchor(); + anchor = block.getBeginNode(); } process(block, activeGuards, processed, anchor); // Process always reached block first. - Block alwaysReachedBlock = block.alwaysReachedBlock(); - if (alwaysReachedBlock != null && alwaysReachedBlock.dominator() == block) { - assert alwaysReachedBlock.dominator() == block; + Block alwaysReachedBlock = block.getPostdominator(); + if (alwaysReachedBlock != null && alwaysReachedBlock.getDominator() == block) { + assert alwaysReachedBlock.getDominator() == block; processBlock(alwaysReachedBlock, activeGuards, processed, anchor); } // Now go for the other dominators. for (Block dominated : block.getDominated()) { if (dominated != alwaysReachedBlock) { - assert dominated.dominator() == block; + assert dominated.getDominator() == block; processBlock(dominated, activeGuards, processed, null); } } @@ -135,7 +134,7 @@ }; // Lower the instructions of this block. - for (final Node node : b.getInstructions()) { + for (Node node : b.getNodes()) { processed.mark(node); if (node instanceof Lowerable) { ((Lowerable) node).lower(loweringTool); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/PhiStampPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/PhiStampPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/PhiStampPhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.max.graal.compiler.phases; -import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; public class PhiStampPhase extends Phase { @@ -45,22 +44,16 @@ private void iterativeInferPhi(PhiNode phi) { if (phi.inferStamp()) { - for (Node n : phi.usages()) { - if (n instanceof PhiNode) { - PhiNode phiUsage = (PhiNode) n; - iterativeInferPhi(phiUsage); - } + for (PhiNode phiUsage : phi.usages().filter(PhiNode.class)) { + iterativeInferPhi(phiUsage); } } } private void inferPhi(PhiNode phi) { - for (ValueNode v : phi.values()) { - if (v instanceof PhiNode) { - PhiNode phiInput = (PhiNode) v; - if (!phiInput.isLoopPhi()) { - inferPhi(phiInput); - } + for (PhiNode phiInput : phi.values().filter(PhiNode.class)) { + if (!phiInput.isLoopPhi()) { + inferPhi(phiInput); } } phi.inferStamp(); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RemovePlaceholderPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RemovePlaceholderPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * 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.oracle.max.graal.compiler.phases; - -import com.oracle.max.graal.nodes.*; - -public class RemovePlaceholderPhase extends Phase { - @Override - protected void run(StructuredGraph graph) { - for (PlaceholderNode n : graph.getNodes(PlaceholderNode.class)) { - graph.removeFixed(n); - } - } -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SafepointPollingEliminationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SafepointPollingEliminationPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SafepointPollingEliminationPhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -22,9 +22,9 @@ */ package com.oracle.max.graal.compiler.phases; -import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.iterators.*; import com.oracle.max.graal.nodes.*; +import com.oracle.max.graal.util.*; public class SafepointPollingEliminationPhase extends Phase { diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SnippetIntrinsificationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SnippetIntrinsificationPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/SnippetIntrinsificationPhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -156,6 +156,7 @@ Constructor< ? > constructor; try { constructor = nodeClass.getDeclaredConstructor(parameterTypes); + constructor.setAccessible(true); } catch (Exception e) { throw new RuntimeException(e); } @@ -169,36 +170,33 @@ public void cleanUpReturnCheckCast(Node newInstance) { if (newInstance instanceof ValueNode && ((ValueNode) newInstance).kind() != CiKind.Object) { StructuredGraph graph = (StructuredGraph) newInstance.graph(); - for (Node usage : newInstance.usages().snapshot()) { - if (usage instanceof CheckCastNode) { - CheckCastNode checkCastNode = (CheckCastNode) usage; - for (Node checkCastUsage : checkCastNode.usages().snapshot()) { - if (checkCastUsage instanceof ValueAnchorNode) { - ValueAnchorNode valueAnchorNode = (ValueAnchorNode) checkCastUsage; - graph.removeFixed(valueAnchorNode); - } else if (checkCastUsage instanceof MethodCallTargetNode) { - MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) checkCastUsage; - assert pool.isUnboxingMethod(checkCastCallTarget.targetMethod()); - Invoke invokeNode = checkCastCallTarget.invoke(); - invokeNode.node().replaceAtUsages(newInstance); - if (invokeNode instanceof InvokeWithExceptionNode) { - // Destroy exception edge & clear stateAfter. - InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode; + for (CheckCastNode checkCastNode : newInstance.usages().filter(CheckCastNode.class).snapshot()) { + for (Node checkCastUsage : checkCastNode.usages().snapshot()) { + if (checkCastUsage instanceof ValueAnchorNode) { + ValueAnchorNode valueAnchorNode = (ValueAnchorNode) checkCastUsage; + graph.removeFixed(valueAnchorNode); + } else if (checkCastUsage instanceof MethodCallTargetNode) { + MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) checkCastUsage; + assert pool.isUnboxingMethod(checkCastCallTarget.targetMethod()); + Invoke invokeNode = checkCastCallTarget.invoke(); + invokeNode.node().replaceAtUsages(newInstance); + if (invokeNode instanceof InvokeWithExceptionNode) { + // Destroy exception edge & clear stateAfter. + InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invokeNode; - invokeWithExceptionNode.killExceptionEdge(); - graph.removeSplit(invokeWithExceptionNode, InvokeWithExceptionNode.NORMAL_EDGE); - } else { - graph.removeFixed((InvokeNode) invokeNode); - } - checkCastCallTarget.safeDelete(); - } else if (checkCastUsage instanceof FrameState) { - checkCastUsage.replaceFirstInput(checkCastNode, null); + invokeWithExceptionNode.killExceptionEdge(); + graph.removeSplit(invokeWithExceptionNode, InvokeWithExceptionNode.NORMAL_EDGE); } else { - assert false : "unexpected checkcast usage: " + checkCastUsage; + graph.removeFixed((InvokeNode) invokeNode); } + checkCastCallTarget.safeDelete(); + } else if (checkCastUsage instanceof FrameState) { + checkCastUsage.replaceFirstInput(checkCastNode, null); + } else { + assert false : "unexpected checkcast usage: " + checkCastUsage; } - checkCastNode.safeDelete(); } + checkCastNode.safeDelete(); } } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2011, 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.oracle.max.graal.compiler.schedule; - -import java.util.*; - -import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.nodes.*; -import com.oracle.max.graal.nodes.java.*; - - -public class Block { - - private int blockID; - protected final List successors = new ArrayList<>(); - protected final List predecessors = new ArrayList<>(); - private final List dominated = new ArrayList<>(); - private List instructions = new ArrayList<>(); - private Block alwaysReachedBlock; - private Block dominator; - private EndNode end; - private int loopDepth = 0; - private int loopIndex = -1; - private double probability; - - /** - * For loop headers only: The list of all blocks in this loop. - */ - public List loopBlocks; - - private Node firstNode; - private Node lastNode; - - public Node firstNode() { - return firstNode; - } - - public void setFirstNode(Node node) { - this.firstNode = node; - } - - public Block alwaysReachedBlock() { - return alwaysReachedBlock; - } - - public boolean isExceptionBlock() { - return firstNode() instanceof ExceptionObjectNode; - } - - public void setAlwaysReachedBlock(Block alwaysReachedBlock) { - assert alwaysReachedBlock != this; - this.alwaysReachedBlock = alwaysReachedBlock; - } - - public EndNode end() { - return end; - } - - public void setEnd(EndNode end) { - this.end = end; - } - - public Node lastNode() { - return lastNode; - } - - public int loopDepth() { - return loopDepth; - } - - public void setLoopDepth(int i) { - loopDepth = i; - } - - public int loopIndex() { - return loopIndex; - } - - public void setLoopIndex(int i) { - loopIndex = i; - } - - public double probability() { - return probability; - } - - - public void setProbability(double probability) { - if (probability > this.probability) { - this.probability = probability; - } - } - - public BeginNode createAnchor() { - return (BeginNode) firstNode; - } - - public void setLastNode(Node node) { - this.lastNode = node; - } - - public List getSuccessors() { - return Collections.unmodifiableList(successors); - } - - public void setDominator(Block dominator) { - assert this.dominator == null; - assert dominator != null; - this.dominator = dominator; - dominator.dominated.add(this); - } - - public List getDominated() { - return Collections.unmodifiableList(dominated); - } - - public List getInstructions() { - return instructions; - } - - public List getPredecessors() { - return Collections.unmodifiableList(predecessors); - } - - public Block(int blockID) { - this.blockID = blockID; - } - - public void addSuccessor(Block other) { - successors.add(other); - other.predecessors.add(this); - } - - public int blockID() { - return blockID; - } - - /** - * Iterate over this block, its exception handlers, and its successors, in that order. - * - * @param closure the closure to apply to each block - */ - public void iteratePreOrder(BlockClosure closure) { - // TODO: identity hash map might be too slow, consider a boolean array or a mark field - iterate(new IdentityHashMap(), closure); - } - - private void iterate(IdentityHashMap mark, BlockClosure closure) { - if (!mark.containsKey(this)) { - mark.put(this, this); - closure.apply(this); - - iterateReverse(mark, closure, this.successors); - } - } - - private static void iterateReverse(IdentityHashMap mark, BlockClosure closure, List list) { - for (int i = list.size() - 1; i >= 0; i--) { - list.get(i).iterate(mark, closure); - } - } - - @Override - public String toString() { - return "B" + blockID; - } - - public boolean isLoopHeader() { - return firstNode instanceof LoopBeginNode; - } - - public boolean isLoopEnd() { - return lastNode instanceof LoopEndNode; - } - - public Block dominator() { - return dominator; - } - - public void setInstructions(List instructions) { - this.instructions = instructions; - } - - public static void iteratePostOrder(List blocks, BlockClosure closure) { - ArrayList startBlocks = new ArrayList<>(); - for (Block block : blocks) { - if (block.getPredecessors().size() == 0) { - startBlocks.add(block); - } - } - iteratePostOrder(blocks, closure, startBlocks.toArray(new Block[startBlocks.size()])); - } - - public static void iteratePostOrder(List blocks, BlockClosure closure, Block... startBlocks) { - BitMap visited = new BitMap(blocks.size()); - LinkedList workList = new LinkedList<>(); - for (Block block : startBlocks) { - workList.add(block); - visited.set(block.blockID()); - } - - while (!workList.isEmpty()) { - Block b = workList.remove(); - - closure.apply(b); - - for (Block succ : b.getSuccessors()) { - if (!visited.get(succ.blockID())) { - boolean delay = false; - for (Block pred : succ.getPredecessors()) { - if (!visited.get(pred.blockID()) && !(pred.lastNode instanceof LoopEndNode)) { - delay = true; - break; - } - } - - if (!delay) { - visited.set(succ.blockID()); - workList.add(succ); - } - } - } - } - } - - public String name() { - return "B" + blockID; - } -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/BlockClosure.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/BlockClosure.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/BlockClosure.java Sun Feb 05 05:40:36 2012 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.compiler.schedule; +import com.oracle.max.graal.compiler.cfg.*; + /** * The {@code BlockClosure} interface represents a closure for iterating over blocks. */ diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,641 +0,0 @@ -/* - * Copyright (c) 2011, 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.oracle.max.graal.compiler.schedule; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.phases.*; -import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.graph.Node.Verbosity; -import com.oracle.max.graal.nodes.*; -import com.oracle.max.graal.nodes.extended.*; -import com.oracle.max.graal.nodes.virtual.*; - - -public class IdentifyBlocksPhase extends Phase { - - public static class BlockFactory { - public Block createBlock(int blockID) { - return new Block(blockID); - } - } - - private final BlockFactory blockFactory; - private final List blocks = new ArrayList<>(); - private NodeMap nodeToBlock; - private NodeMap earliestCache; - private Block startBlock; - private boolean scheduleAllNodes; - private int loopCount; - - public IdentifyBlocksPhase(boolean scheduleAllNodes) { - this(scheduleAllNodes, new BlockFactory()); - } - - public IdentifyBlocksPhase(boolean scheduleAllNodes, BlockFactory blockFactory) { - super(scheduleAllNodes ? "FullSchedule" : "PartSchedule"); - this.blockFactory = blockFactory; - this.scheduleAllNodes = scheduleAllNodes; - } - - public void calculateAlwaysReachedBlock() { - for (Block b : blocks) { - calculateAlwaysReachedBlock(b); - } - } - - - private void calculateAlwaysReachedBlock(Block b) { - if (b.getSuccessors().size() == 1) { - b.setAlwaysReachedBlock(b.getSuccessors().get(0)); - } else if (b.getSuccessors().size() > 1) { - BitMap blockBitMap = new BitMap(blocks.size()); - List visitedBlocks = new ArrayList<>(); - - // Do a fill starting at the dominated blocks and going upwards over predecessors. - for (Block dominated : b.getDominated()) { - for (Block pred : dominated.getPredecessors()) { - blockFill(blockBitMap, pred, b, visitedBlocks); - } - } - - boolean ok = true; - - // Find out if there is exactly 1 dominated block that is left unmarked (this is the potential merge block that is always reached). - Block unmarkedDominated = null; - for (Block dominated : b.getDominated()) { - if (!blockBitMap.get(dominated.blockID())) { - if (unmarkedDominated != null) { - ok = false; - break; - } - unmarkedDominated = dominated; - } - } - - if (ok) { - // Check that there is no exit possible except for exception edges. - for (Block visitedBlock : visitedBlocks) { - assert blockBitMap.get(visitedBlock.blockID()); - for (Block succ : visitedBlock.getSuccessors()) { - if (succ != unmarkedDominated && !succ.isExceptionBlock() && !blockBitMap.get(succ.blockID())) { - ok = false; - break; - } - } - - if (!ok) { - break; - } - } - } - - if (ok) { - assert unmarkedDominated != null; - b.setAlwaysReachedBlock(unmarkedDominated); - } - } - } - - private void blockFill(BitMap blockBitMap, Block cur, Block stop, List visitedBlocks) { - if (blockBitMap.get(cur.blockID())) { - return; - } - - blockBitMap.set(cur.blockID()); - visitedBlocks.add(cur); - - if (cur != stop) { - for (Block pred : cur.getPredecessors()) { - blockFill(blockBitMap, pred, stop, visitedBlocks); - } - } - } - - @Override - protected void run(StructuredGraph graph) { - nodeToBlock = graph.createNodeMap(); - earliestCache = graph.createNodeMap(); - identifyBlocks(graph); - } - - public Block getStartBlock() { - return startBlock; - } - - public List getBlocks() { - return Collections.unmodifiableList(blocks); - } - - public NodeMap getNodeToBlock() { - return nodeToBlock; - } - - private Block createBlock() { - Block b = blockFactory.createBlock(blocks.size()); - blocks.add(b); - return b; - } - - public int loopCount() { - return loopCount; - } - - private Block assignBlockNew(Node n, Block block, StructuredGraph graph) { - Block b = block; - if (b == null) { - b = createBlock(); - } - - assert nodeToBlock.get(n) == null; - nodeToBlock.set(n, b); - - if (n == graph.start()) { - startBlock = b; - } - - if (n instanceof MergeNode) { - for (Node usage : n.usages()) { - if (usage instanceof PhiNode) { - nodeToBlock.set(usage, b); - } - } - } - if (n instanceof EndNode) { - assert b.end() == null || n == b.end(); - b.setEnd((EndNode) n); - } - if (b.lastNode() == null) { - b.setFirstNode(n); - b.setLastNode(n); - b.getInstructions().add(n); - } else { - b.getInstructions().add(0, n); - b.setFirstNode(n); - } - - return b; - } - - public static boolean isBlockEnd(Node n) { - return trueSuccessorCount(n) > 1 || n instanceof ReturnNode || n instanceof UnwindNode || n instanceof DeoptimizeNode; - } - - private void identifyBlocks(StructuredGraph graph) { - - // Identify blocks. - for (Node n : graph.getNodes()) { - if (n instanceof EndNode || n instanceof ReturnNode || n instanceof UnwindNode || n instanceof LoopEndNode || n instanceof DeoptimizeNode) { - Block block = null; - Node currentNode = n; - Node prev = null; - while (nodeToBlock.get(currentNode) == null) { - block = assignBlockNew(currentNode, block, graph); - if (currentNode instanceof FixedNode) { - block.setProbability(((FixedNode) currentNode).probability()); - } - if (currentNode.predecessor() == null) { - // At a merge node => stop iteration. - assert currentNode instanceof MergeNode || currentNode == ((StructuredGraph) currentNode.graph()).start() : currentNode; - break; - } - if (block != null && currentNode instanceof BeginNode) { - // We are at a split node => start a new block. - block = null; - } - prev = currentNode; - currentNode = currentNode.predecessor(); - // FIX(ls) what's the meaning of this assert? -// assert !(currentNode instanceof AccessNode && ((AccessNode) currentNode).next() != prev) : currentNode; - assert !currentNode.isDeleted() : prev + " " + currentNode; - } - } - } - - // Connect blocks. - for (Block block : blocks) { - Node n = block.firstNode(); - if (n instanceof MergeNode) { - MergeNode m = (MergeNode) n; - for (Node pred : m.cfgPredecessors()) { - Block predBlock = nodeToBlock.get(pred); - predBlock.addSuccessor(block); - } - } else { - if (n.predecessor() != null) { - if (Util.isFixed(n.predecessor())) { - Block predBlock = nodeToBlock.get(n.predecessor()); - predBlock.addSuccessor(block); - } - } - } - } - - computeDominators(graph); - - if (scheduleAllNodes) { - computeLoopInformation(); // Will make the graph cyclic. - assignBlockToNodes(graph); - sortNodesWithinBlocks(graph); - } - } - - private void computeLoopInformation() { - // Add successors of loop end nodes. Makes the graph cyclic. - for (Block block : blocks) { - Node n = block.lastNode(); - if (n instanceof LoopEndNode) { - LoopEndNode loopEnd = (LoopEndNode) n; - assert loopEnd.loopBegin() != null; - Block loopBeginBlock = nodeToBlock.get(loopEnd.loopBegin()); - block.addSuccessor(loopBeginBlock); - BitMap map = new BitMap(blocks.size()); - loopBeginBlock.loopBlocks = new ArrayList<>(); - markBlocks(block, loopBeginBlock, map, loopCount++, block.loopDepth()); - assert loopBeginBlock.loopDepth() == block.loopDepth() && loopBeginBlock.loopIndex() == block.loopIndex(); - } - } - } - - private void markBlocks(Block block, Block loopBeginBlock, BitMap map, int loopIndex, int initialDepth) { - if (map.get(block.blockID())) { - return; - } - - map.set(block.blockID()); - loopBeginBlock.loopBlocks.add(block); - if (block.loopDepth() <= initialDepth) { - assert block.loopDepth() == initialDepth; - block.setLoopIndex(loopIndex); - } - block.setLoopDepth(block.loopDepth() + 1); - - if (block == loopBeginBlock) { - return; - } - - for (Block pred : block.getPredecessors()) { - markBlocks(pred, loopBeginBlock, map, loopIndex, initialDepth); - } - - if (block.isLoopHeader()) { - markBlocks(nodeToBlock.get(((LoopBeginNode) block.firstNode()).loopEnd()), loopBeginBlock, map, loopIndex, initialDepth); - } - } - - private void assignBlockToNodes(StructuredGraph graph) { - for (Node n : graph.getNodes()) { - assignBlockToNode(n); - } - } - - public void assignBlockToNode(Node n) { - if (n == null) { - return; - } - - assert !n.isDeleted(); - - Block prevBlock = nodeToBlock.get(n); - if (prevBlock != null) { - return; - } - assert !(n instanceof PhiNode) : n; - // if in CFG, schedule at the latest position possible in the outermost loop possible - Block latestBlock = latestBlock(n); - Block block; - if (latestBlock == null) { - block = earliestBlock(n); - } else if (GraalOptions.ScheduleOutOfLoops && !(n instanceof VirtualObjectFieldNode) && !(n instanceof VirtualObjectNode)) { - Block earliestBlock = earliestBlock(n); - block = scheduleOutOfLoops(n, latestBlock, earliestBlock); - } else { - block = latestBlock; - } - assert !(n instanceof MergeNode); - nodeToBlock.set(n, block); - block.getInstructions().add(n); - } - - private Block latestBlock(Node n) { - Block block = null; - for (Node succ : n.successors()) { - if (succ == null) { - continue; - } - assignBlockToNode(succ); - block = getCommonDominator(block, nodeToBlock.get(succ)); - } - ensureScheduledUsages(n); - CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(block); - for (Node usage : n.usages()) { - blocksForUsage(n, usage, cdbc); - } - return cdbc.block; - } - - private class CommonDominatorBlockClosure implements BlockClosure { - public Block block; - public CommonDominatorBlockClosure(Block block) { - this.block = block; - } - @Override - public void apply(Block newBlock) { - this.block = getCommonDominator(this.block, newBlock); - } - } - - private Block earliestBlock(Node n) { - Block earliest = nodeToBlock.get(n); - if (earliest != null) { - return earliest; - } - earliest = earliestCache.get(n); - if (earliest != null) { - return earliest; - } - BitMap bits = new BitMap(blocks.size()); - ArrayList before = new ArrayList<>(); - if (n.predecessor() != null) { - before.add(n.predecessor()); - } - for (Node input : n.inputs()) { - before.add(input); - } - for (Node pred : before) { - if (pred == null) { - continue; - } - Block b = earliestBlock(pred); - if (!bits.get(b.blockID())) { - earliest = b; - do { - bits.set(b.blockID()); - b = b.dominator(); - } while(b != null && !bits.get(b.blockID())); - } - } - if (earliest == null) { - Block start = nodeToBlock.get(((StructuredGraph) n.graph()).start()); - assert start != null; - return start; - } - earliestCache.set(n, earliest); - return earliest; - } - - - private static Block scheduleOutOfLoops(Node n, Block latestBlock, Block earliest) { - assert latestBlock != null : "no latest : " + n; - Block cur = latestBlock; - Block result = latestBlock; - while (cur.loopDepth() != 0 && cur != earliest && cur.dominator() != null) { - Block dom = cur.dominator(); - if (dom.loopDepth() < result.loopDepth()) { - result = dom; - } - cur = dom; - } - return result; - } - - private void blocksForUsage(Node node, Node usage, BlockClosure closure) { - if (usage instanceof PhiNode) { - PhiNode phi = (PhiNode) usage; - MergeNode merge = phi.merge(); - Block mergeBlock = nodeToBlock.get(merge); - assert mergeBlock != null : "no block for merge " + merge.toString(Verbosity.Id); - for (int i = 0; i < phi.valueCount(); ++i) { - if (phi.valueAt(i) == node) { - if (mergeBlock.getPredecessors().size() <= i) { - TTY.println(merge.toString()); - TTY.println(phi.toString()); - TTY.println(merge.cfgPredecessors().toString()); - TTY.println(phi.inputs().toString()); - TTY.println("value count: " + phi.valueCount()); - } - closure.apply(mergeBlock.getPredecessors().get(i)); - } - } - } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) { - MergeNode merge = ((FrameState) usage).block(); - Block block = null; - for (Node pred : merge.cfgPredecessors()) { - block = getCommonDominator(block, nodeToBlock.get(pred)); - } - closure.apply(block); - } else { - assignBlockToNode(usage); - closure.apply(nodeToBlock.get(usage)); - } - } - - private void ensureScheduledUsages(Node node) { - for (Node usage : node.usages().snapshot()) { - assignBlockToNode(usage); - } - // now true usages are ready - } - - private Block getCommonDominator(Block a, Block b) { - if (a == null) { - return b; - } - if (b == null) { - return a; - } - return commonDominator(a, b); - } - - private void sortNodesWithinBlocks(StructuredGraph graph) { - NodeBitMap map = graph.createNodeBitMap(); - for (Block b : blocks) { - sortNodesWithinBlocks(b, map); - } - } - - private void sortNodesWithinBlocks(Block b, NodeBitMap map) { - List instructions = b.getInstructions(); - List sortedInstructions = new ArrayList<>(instructions.size() + 2); - - assert !map.isMarked(b.firstNode()) && nodeToBlock.get(b.firstNode()) == b; - assert !map.isMarked(b.lastNode()) && nodeToBlock.get(b.lastNode()) == b; - - for (Node i : instructions) { - addToSorting(b, i, sortedInstructions, map); - } - - // Make sure that last node gets really last (i.e. when a frame state successor hangs off it). - Node lastSorted = sortedInstructions.get(sortedInstructions.size() - 1); - if (lastSorted != b.lastNode()) { - int idx = sortedInstructions.indexOf(b.lastNode()); - boolean canNotMove = false; - for (int i = idx + 1; i < sortedInstructions.size(); i++) { - if (sortedInstructions.get(i).inputs().contains(b.lastNode())) { - canNotMove = true; - break; - } - } - if (canNotMove) { - // (cwi) this was the assertion commented out below. However, it is failing frequently when the - // scheduler is used for debug printing in early compiler phases. This was annoying during debugging - // when an excpetion breakpoint is set for assertion errors, so I changed it to a bailout. - if (b.lastNode() instanceof ControlSplitNode) { - throw new CiBailout(""); - } - //assert !(b.lastNode() instanceof ControlSplitNode); - - //b.setLastNode(lastSorted); - } else { - sortedInstructions.remove(b.lastNode()); - sortedInstructions.add(b.lastNode()); - } - } - b.setInstructions(sortedInstructions); - } - - private void addToSorting(Block b, Node i, List sortedInstructions, NodeBitMap map) { - if (i == null || map.isMarked(i) || nodeToBlock.get(i) != b || i instanceof PhiNode || i instanceof LocalNode) { - return; - } - - if (i instanceof WriteNode) { - // TODO(tw): Make sure every ReadNode that is connected to the same memory state is executed before every write node. - // WriteNode wn = (WriteNode) i; - } - - FrameState state = null; - WriteNode writeNode = null; - for (Node input : i.inputs()) { - if (input instanceof WriteNode && !map.isMarked(input) && nodeToBlock.get(input) == b) { - writeNode = (WriteNode) input; - } else if (input instanceof FrameState) { - state = (FrameState) input; - } else { - addToSorting(b, input, sortedInstructions, map); - } - } - - if (i.predecessor() != null) { - addToSorting(b, i.predecessor(), sortedInstructions, map); - } - - map.mark(i); - - addToSorting(b, state, sortedInstructions, map); - assert writeNode == null || !map.isMarked(writeNode); - addToSorting(b, writeNode, sortedInstructions, map); - - // Now predecessors and inputs are scheduled => we can add this node. - sortedInstructions.add(i); - } - - private void computeDominators(StructuredGraph graph) { - Block dominatorRoot = nodeToBlock.get(graph.start()); - assert dominatorRoot != null; - assert dominatorRoot.getPredecessors().size() == 0; - BitMap visited = new BitMap(blocks.size()); - visited.set(dominatorRoot.blockID()); - LinkedList workList = new LinkedList<>(); - workList.add(dominatorRoot); - - int cnt = 0; - while (!workList.isEmpty()) { - if (cnt++ > blocks.size() * 20) { - throw new RuntimeException("(ls) endless loop in computeDominators?"); - } - Block b = workList.remove(); - - List predecessors = b.getPredecessors(); - if (predecessors.size() == 1) { - b.setDominator(predecessors.get(0)); - } else if (predecessors.size() > 1) { - boolean delay = false; - for (Block pred : predecessors) { - if (pred != dominatorRoot && pred.dominator() == null) { - delay = true; - break; - } - } - - if (delay) { - workList.add(b); - continue; - } - - Block dominator = null; - for (Block pred : predecessors) { - if (dominator == null) { - dominator = pred; - } else { - dominator = commonDominator(dominator, pred); - } - } - b.setDominator(dominator); - } - - for (Block succ : b.getSuccessors()) { - if (!visited.get(succ.blockID())) { - visited.set(succ.blockID()); - workList.add(succ); - } - } - } - } - - public Block commonDominator(Block a, Block b) { - BitMap bitMap = new BitMap(blocks.size()); - Block cur = a; - while (cur != null) { - bitMap.set(cur.blockID()); - cur = cur.dominator(); - } - - cur = b; - while (cur != null) { - if (bitMap.get(cur.blockID())) { - return cur; - } - cur = cur.dominator(); - } - - throw new IllegalStateException("no common dominator between " + a + " and " + b); - } - - public static int trueSuccessorCount(Node n) { - if (n == null) { - return 0; - } - int i = 0; - for (Node s : n.successors()) { - if (Util.isFixed(s)) { - i++; - } - } - return i; - } -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/SchedulePhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/SchedulePhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2011, 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.oracle.max.graal.compiler.schedule; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.criutils.*; +import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.cfg.*; +import com.oracle.max.graal.compiler.phases.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.graph.Node.Verbosity; +import com.oracle.max.graal.nodes.*; +import com.oracle.max.graal.nodes.extended.*; +import com.oracle.max.graal.nodes.virtual.*; + +public class SchedulePhase extends Phase { + private ControlFlowGraph cfg; + private NodeMap earliestCache; + + private BlockMap> nodesFor; + + public SchedulePhase() { + super("Schedule"); + } + + @Override + protected void run(StructuredGraph graph) { + cfg = ControlFlowGraph.compute(graph, true, true, true, false); + earliestCache = graph.createNodeMap(); + nodesFor = new BlockMap<>(cfg); + + assignBlockToNodes(graph); + sortNodesWithinBlocks(graph); + } + + public ControlFlowGraph getCFG() { + return cfg; + } + + public BlockMap> getNodesFor() { + return nodesFor; + } + + public List nodesFor(Block block) { + return nodesFor.get(block); + } + + private void assignBlockToNodes(StructuredGraph graph) { + for (Block block : cfg.getBlocks()) { + List nodes = new ArrayList<>(); + assert nodesFor.get(block) == null; + nodesFor.put(block, nodes); + for (Node node : block.getNodes()) { + nodes.add(node); + } + } + + for (Node n : graph.getNodes()) { + assignBlockToNode(n); + } + } + + private void assignBlockToNode(Node n) { + if (n == null) { + return; + } + + assert !n.isDeleted(); + + Block prevBlock = cfg.getNodeToBlock().get(n); + if (prevBlock != null) { + return; + } + assert !(n instanceof PhiNode) : n; + // if in CFG, schedule at the latest position possible in the outermost loop possible + Block latestBlock = latestBlock(n); + Block block; + if (latestBlock == null) { + block = earliestBlock(n); + } else if (GraalOptions.ScheduleOutOfLoops && !(n instanceof VirtualObjectFieldNode) && !(n instanceof VirtualObjectNode)) { + Block earliestBlock = earliestBlock(n); + block = scheduleOutOfLoops(n, latestBlock, earliestBlock); + } else { + block = latestBlock; + } + assert !(n instanceof MergeNode); + cfg.getNodeToBlock().set(n, block); + nodesFor.get(block).add(n); + } + + private Block latestBlock(Node n) { + Block block = null; + for (Node succ : n.successors()) { + if (succ == null) { + continue; + } + assignBlockToNode(succ); + block = getCommonDominator(block, cfg.getNodeToBlock().get(succ)); + } + ensureScheduledUsages(n); + CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(block); + for (Node usage : n.usages()) { + blocksForUsage(n, usage, cdbc); + } + return cdbc.block; + } + + private class CommonDominatorBlockClosure implements BlockClosure { + public Block block; + public CommonDominatorBlockClosure(Block block) { + this.block = block; + } + @Override + public void apply(Block newBlock) { + this.block = getCommonDominator(this.block, newBlock); + } + } + + private Block earliestBlock(Node n) { + Block earliest = cfg.getNodeToBlock().get(n); + if (earliest != null) { + return earliest; + } + earliest = earliestCache.get(n); + if (earliest != null) { + return earliest; + } + BitMap bits = new BitMap(cfg.getBlocks().length); + ArrayList before = new ArrayList<>(); + if (n.predecessor() != null) { + before.add(n.predecessor()); + } + for (Node input : n.inputs()) { + before.add(input); + } + for (Node pred : before) { + if (pred == null) { + continue; + } + Block b = earliestBlock(pred); + if (!bits.get(b.getId())) { + earliest = b; + do { + bits.set(b.getId()); + b = b.getDominator(); + } while(b != null && !bits.get(b.getId())); + } + } + if (earliest == null) { + Block start = cfg.getNodeToBlock().get(((StructuredGraph) n.graph()).start()); + assert start != null; + return start; + } + earliestCache.set(n, earliest); + return earliest; + } + + + private static Block scheduleOutOfLoops(Node n, Block latestBlock, Block earliest) { + assert latestBlock != null : "no latest : " + n; + Block cur = latestBlock; + Block result = latestBlock; + while (cur.getLoop() != null && cur != earliest && cur.getDominator() != null) { + Block dom = cur.getDominator(); + if (dom.getLoopDepth() < result.getLoopDepth()) { + result = dom; + } + cur = dom; + } + return result; + } + + private void blocksForUsage(Node node, Node usage, BlockClosure closure) { + if (usage instanceof PhiNode) { + PhiNode phi = (PhiNode) usage; + MergeNode merge = phi.merge(); + Block mergeBlock = cfg.getNodeToBlock().get(merge); + assert mergeBlock != null : "no block for merge " + merge.toString(Verbosity.Id); + for (int i = 0; i < phi.valueCount(); ++i) { + if (phi.valueAt(i) == node) { + if (mergeBlock.getPredecessors().size() <= i) { + TTY.println(merge.toString()); + TTY.println(phi.toString()); + TTY.println(merge.cfgPredecessors().toString()); + TTY.println(phi.inputs().toString()); + TTY.println("value count: " + phi.valueCount()); + } + closure.apply(mergeBlock.getPredecessors().get(i)); + } + } + } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) { + MergeNode merge = ((FrameState) usage).block(); + Block block = null; + for (Node pred : merge.cfgPredecessors()) { + block = getCommonDominator(block, cfg.getNodeToBlock().get(pred)); + } + closure.apply(block); + } else { + assignBlockToNode(usage); + closure.apply(cfg.getNodeToBlock().get(usage)); + } + } + + private void ensureScheduledUsages(Node node) { + for (Node usage : node.usages().snapshot()) { + assignBlockToNode(usage); + } + // now true usages are ready + } + + private static Block getCommonDominator(Block a, Block b) { + if (a == null) { + return b; + } + if (b == null) { + return a; + } + return ControlFlowGraph.commonDominator(a, b); + } + + private void sortNodesWithinBlocks(StructuredGraph graph) { + NodeBitMap map = graph.createNodeBitMap(); + for (Block b : cfg.getBlocks()) { + sortNodesWithinBlocks(b, map); + } + } + + private void sortNodesWithinBlocks(Block b, NodeBitMap map) { + List instructions = nodesFor.get(b); + List sortedInstructions = new ArrayList<>(instructions.size() + 2); + + assert !map.isMarked(b.getBeginNode()) && cfg.blockFor(b.getBeginNode()) == b; + assert !map.isMarked(b.getEndNode()) && cfg.blockFor(b.getEndNode()) == b; + + for (Node i : instructions) { + addToSorting(b, i, sortedInstructions, map); + } + + // Make sure that last node gets really last (i.e. when a frame state successor hangs off it). + Node lastSorted = sortedInstructions.get(sortedInstructions.size() - 1); + if (lastSorted != b.getEndNode()) { + int idx = sortedInstructions.indexOf(b.getEndNode()); + boolean canNotMove = false; + for (int i = idx + 1; i < sortedInstructions.size(); i++) { + if (sortedInstructions.get(i).inputs().contains(b.getEndNode())) { + canNotMove = true; + break; + } + } + if (canNotMove) { + // (cwi) this was the assertion commented out below. However, it is failing frequently when the + // scheduler is used for debug printing in early compiler phases. This was annoying during debugging + // when an excpetion breakpoint is set for assertion errors, so I changed it to a bailout. + if (b.getEndNode() instanceof ControlSplitNode) { + throw new CiBailout(""); + } + //assert !(b.lastNode() instanceof ControlSplitNode); + + //b.setLastNode(lastSorted); + } else { + sortedInstructions.remove(b.getEndNode()); + sortedInstructions.add(b.getEndNode()); + } + } + nodesFor.put(b, sortedInstructions); + } + + private void addToSorting(Block b, Node i, List sortedInstructions, NodeBitMap map) { + if (i == null || map.isMarked(i) || cfg.getNodeToBlock().get(i) != b || i instanceof PhiNode || i instanceof LocalNode) { + return; + } + + if (i instanceof WriteNode) { + // TODO(tw): Make sure every ReadNode that is connected to the same memory state is executed before every write node. + // WriteNode wn = (WriteNode) i; + } + + FrameState state = null; + WriteNode writeNode = null; + for (Node input : i.inputs()) { + if (input instanceof WriteNode && !map.isMarked(input) && cfg.getNodeToBlock().get(input) == b) { + writeNode = (WriteNode) input; + } else if (input instanceof FrameState) { + state = (FrameState) input; + } else { + addToSorting(b, input, sortedInstructions, map); + } + } + + if (i.predecessor() != null) { + addToSorting(b, i.predecessor(), sortedInstructions, map); + } + + map.mark(i); + + addToSorting(b, state, sortedInstructions, map); + assert writeNode == null || !map.isMarked(writeNode); + addToSorting(b, writeNode, sortedInstructions, map); + + // Now predecessors and inputs are scheduled => we can add this node. + sortedInstructions.add(i); + } +} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlow.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlow.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlow.java Sun Feb 05 05:40:36 2012 +0100 @@ -66,6 +66,11 @@ protected EnumSet flagsFor(OperandMode mode, int index) { throw Util.shouldNotReachHere(); } + + @Override + public Label getLabel() { + return label; + } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java Sun Feb 05 05:40:36 2012 +0100 @@ -371,7 +371,7 @@ InvokeWithExceptionNode invokeWithException = ((InvokeWithExceptionNode) invoke); if (unwindNode != null) { assert unwindNode.predecessor() != null; - assert invokeWithException.exceptionEdge().successors().explicitCount() == 1; + assert invokeWithException.exceptionEdge().successors().count() == 1; ExceptionObjectNode obj = (ExceptionObjectNode) invokeWithException.exceptionEdge().next(); stateAtExceptionEdge = obj.stateAfter(); UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/NodeIterators.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/NodeIterators.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * 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.oracle.max.graal.compiler.util; - -import java.util.*; - -import com.oracle.max.graal.graph.iterators.*; -import com.oracle.max.graal.nodes.*; -import com.oracle.max.graal.util.*; - -public class NodeIterators { - - public static NodeIterable dominators(final FixedNode n) { - return new NodeIterable() { - @Override - public Iterator iterator() { - return new NodeIterator(until){ - FixedNode p = n; - @Override - protected void forward() { - if (current == null) { - if (p instanceof MergeNode) { - current = new ComputeImmediateDominator((MergeNode) p).compute(); - } else { - current = (FixedNode) p.predecessor(); - } - p = current; - } - } - }; - } - }; - } -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java Sun Feb 05 05:40:36 2012 +0100 @@ -22,9 +22,11 @@ */ package com.oracle.max.graal.compiler.util; +import java.lang.reflect.*; import java.util.*; import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; import com.oracle.max.criutils.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; @@ -371,4 +373,8 @@ public static boolean isFloating(Node n) { return n instanceof FloatingNode; } + + public static boolean isFinalClass(RiResolvedType type) { + return Modifier.isFinal(type.accessFlags()) || (type.isArrayClass() && Modifier.isFinal(type.componentType().accessFlags())); + } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/Debug.java --- a/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/Debug.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/Debug.java Sun Feb 05 05:40:36 2012 +0100 @@ -144,7 +144,7 @@ } } - public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isTimerEnabled) { + public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isTimerEnabled, final List dumpHandlers) { return new DebugConfig() { @Override @@ -174,7 +174,7 @@ @Override public Collection< ? extends DebugDumpHandler> dumpHandlers() { - return Collections.emptyList(); + return dumpHandlers; } }; } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/internal/DebugScope.java --- a/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/internal/DebugScope.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.debug/src/com/oracle/max/graal/debug/internal/DebugScope.java Sun Feb 05 05:40:36 2012 +0100 @@ -136,7 +136,6 @@ private T executeScope(Runnable runnable, Callable callable) { try { - instanceTL.get().log("Starting scope %s", instanceTL.get().getQualifiedName()); if (runnable != null) { runnable.run(); } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Graph.java Sun Feb 05 05:40:36 2012 +0100 @@ -265,9 +265,9 @@ * Returns an {@link Iterable} providing all nodes added since the last {@link Graph#mark() mark}. * @return an {@link Iterable} providing the new nodes */ - public Iterable getNewNodes() { + public NodeIterable getNewNodes() { final int index = this.mark; - return new Iterable() { + return new NodeIterable() { @Override public Iterator iterator() { return new NodeIterator(index); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java Sun Feb 05 05:40:36 2012 +0100 @@ -496,11 +496,11 @@ @Override public void formatTo(Formatter formatter, int flags, int width, int precision) { if ((flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE) { - formatter.format(toString(Verbosity.Id)); + formatter.format("%s", toString(Verbosity.Id)); } else if ((flags & FormattableFlags.UPPERCASE) == FormattableFlags.UPPERCASE) { - formatter.format(toString(Verbosity.Long)); + formatter.format("%s", toString(Verbosity.Long)); } else { - formatter.format(toString(Verbosity.Short)); + formatter.format("%s", toString(Verbosity.Short)); } boolean neighborsAlternate = ((flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags.LEFT_JUSTIFY); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeInputList.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeInputList.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeInputList.java Sun Feb 05 05:40:36 2012 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.graph; +import java.util.*; + public final class NodeInputList extends NodeList { @@ -42,6 +44,12 @@ this.self = self; } + public NodeInputList(Node self, List elements) { + super(elements); + assert self.usages() == null; + this.self = self; + } + @Override protected void update(T oldNode, T newNode) { self.updateUsages(oldNode, newNode); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeInputsIterable.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeInputsIterable.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeInputsIterable.java Sun Feb 05 05:40:36 2012 +0100 @@ -26,9 +26,6 @@ import com.oracle.max.graal.graph.iterators.*; public abstract class NodeInputsIterable extends NodeIterable { - - public abstract boolean contains(Node node); - @Override public abstract NodeClassIterator iterator(); } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeList.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeList.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeList.java Sun Feb 05 05:40:36 2012 +0100 @@ -27,7 +27,9 @@ import java.util.List; import java.util.ListIterator; -public abstract class NodeList implements Iterable, List { +import com.oracle.max.graal.graph.iterators.*; + +public abstract class NodeList extends NodeIterable implements List { protected static final Node[] EMPTY_NODE_ARRAY = new Node[0]; @@ -62,6 +64,21 @@ } } + protected NodeList(List elements) { + if (elements == null || elements.isEmpty()) { + this.size = 0; + this.nodes = EMPTY_NODE_ARRAY; + this.initialSize = 0; + } else { + this.size = elements.size(); + this.initialSize = elements.size(); + this.nodes = new Node[elements.size()]; + for (int i = 0; i < elements.size(); i++) { + this.nodes[i] = elements.get(i); + } + } + } + protected abstract void update(T oldNode, T newNode); @Override @@ -74,6 +91,16 @@ return size == 0; } + @Override + public boolean isNotEmpty() { + return size > 0; + } + + @Override + public int count() { + return size; + } + protected final void incModCount() { modCount++; } @@ -214,6 +241,7 @@ }; } + @Override public boolean contains(T other) { for (int i = 0; i < size; i++) { if (nodes[i] == other) { @@ -223,33 +251,10 @@ return false; } - public Iterable snapshot() { - return new Iterable() { - - @Override - public Iterator iterator() { - return new Iterator() { - private Node[] nodesCopy = Arrays.copyOf(NodeList.this.nodes, NodeList.this.size); - private int index = 0; - - @Override - public boolean hasNext() { - return index < nodesCopy.length; - } - - @SuppressWarnings("unchecked") - @Override - public T next() { - return (T) nodesCopy[index++]; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - }; + @SuppressWarnings("unchecked") + @Override + public List snapshot() { + return (List) Arrays.asList(Arrays.copyOf(this.nodes, this.size)); } @SuppressWarnings("unchecked") diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeSuccessorsIterable.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeSuccessorsIterable.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeSuccessorsIterable.java Sun Feb 05 05:40:36 2012 +0100 @@ -26,17 +26,6 @@ import com.oracle.max.graal.graph.iterators.*; public abstract class NodeSuccessorsIterable extends NodeIterable { - - public int explicitCount() { - int count = 0; - for (@SuppressWarnings("unused") Node node : this) { - count++; - } - return count; - } - - public abstract boolean contains(Node node); - @Override public abstract NodeClassIterator iterator(); } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeUsagesList.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeUsagesList.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeUsagesList.java Sun Feb 05 05:40:36 2012 +0100 @@ -58,6 +58,11 @@ return size > 0; } + @Override + public int count() { + return size; + } + protected void incModCount() { modCount++; } @@ -140,6 +145,7 @@ }; } + @Override public boolean contains(Node other) { for (int i = 0; i < size; i++) { if (nodes[i] == other) { diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/FilteredNodeIterable.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/FilteredNodeIterable.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/FilteredNodeIterable.java Sun Feb 05 05:40:36 2012 +0100 @@ -28,20 +28,10 @@ public class FilteredNodeIterable extends NodeIterable { private final NodeIterable nodeIterable; - private NodePredicate predicate = NodePredicate.TAUTOLOGY; + private NodePredicate predicate = NodePredicates.alwaysTrue(); + private NodePredicate until = NodePredicates.isNull(); public FilteredNodeIterable(NodeIterable nodeIterable) { this.nodeIterable = nodeIterable; - this.until = nodeIterable.until; - } - @SuppressWarnings("unchecked") - public FilteredNodeIterable and(Class clazz) { - this.predicate = predicate.and(new TypePredicate(clazz)); - return (FilteredNodeIterable) this; - } - @SuppressWarnings("unchecked") - public FilteredNodeIterable or(Class clazz) { - this.predicate = predicate.or(new TypePredicate(clazz)); - return (FilteredNodeIterable) this; } public FilteredNodeIterable and(NodePredicate nodePredicate) { this.predicate = this.predicate.and(nodePredicate); @@ -52,8 +42,34 @@ return this; } @Override + public NodeIterable until(final T u) { + until = until.or(NodePredicates.equals(u)); + return this; + } + @Override + public NodeIterable until(final Class clazz) { + until = until.or(NodePredicates.isA(clazz)); + return this; + } + @Override public Iterator iterator() { final Iterator iterator = nodeIterable.iterator(); return new PredicatedProxyNodeIterator<>(until, iterator, predicate); } + + @SuppressWarnings("unchecked") + @Override + public FilteredNodeIterable filter(Class clazz) { + return (FilteredNodeIterable) this.and(NodePredicates.isA(clazz)); + } + + @Override + public FilteredNodeIterable filter(NodePredicate p) { + return this.and(p); + } + + @Override + public FilteredNodeIterable filterInterface(Class< ? > iface) { + return this.and(NodePredicates.isAInterface(iface)); + } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodeIterable.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodeIterable.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodeIterable.java Sun Feb 05 05:40:36 2012 +0100 @@ -27,17 +27,18 @@ import com.oracle.max.graal.graph.*; public abstract class NodeIterable implements Iterable { - protected NodePredicate until = NodePredicate.IS_NULL; public NodeIterable until(final T u) { - until = until.or(NodePredicate.equals(u)); - return this; + return new FilteredNodeIterable<>(this).until(u); } public NodeIterable until(final Class clazz) { - until = until.or(new TypePredicate(clazz)); - return this; + return new FilteredNodeIterable<>(this).until(clazz); } + @SuppressWarnings("unchecked") public FilteredNodeIterable filter(Class clazz) { - return new FilteredNodeIterable<>(this).and(clazz); + return (FilteredNodeIterable) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz)); + } + public FilteredNodeIterable filterInterface(Class iface) { + return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface)); } public FilteredNodeIterable filter(NodePredicate predicate) { return new FilteredNodeIterable<>(this).and(predicate); @@ -71,4 +72,7 @@ public boolean isNotEmpty() { return iterator().hasNext(); } + public boolean contains(T node) { + return this.filter(NodePredicates.equals(node)).isNotEmpty(); + } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodeIterator.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodeIterator.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodeIterator.java Sun Feb 05 05:40:36 2012 +0100 @@ -28,21 +28,17 @@ public abstract class NodeIterator implements Iterator{ protected T current; - protected final NodePredicate until; - public NodeIterator(NodePredicate until) { - this.until = until; - } protected abstract void forward(); @Override public boolean hasNext() { forward(); - return current != null && !until.apply(current); + return current != null; } @Override public T next() { forward(); T ret = current; - if (current == null || until.apply(current)) { + if (current == null) { throw new NoSuchElementException(); } current = null; diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodePredicate.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodePredicate.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodePredicate.java Sun Feb 05 05:40:36 2012 +0100 @@ -25,78 +25,18 @@ import com.oracle.max.graal.graph.*; public abstract class NodePredicate { - public static final TautologyPredicate TAUTOLOGY = new TautologyPredicate(); - - public static final IsNullPredicate IS_NULL = new IsNullPredicate(); - - public static final class TautologyPredicate extends NodePredicate { - @Override - public boolean apply(Node n) { - return true; - } - } - - public static final class AndPredicate extends NodePredicate { - private final NodePredicate a; - private final NodePredicate b; - private AndPredicate(NodePredicate np, NodePredicate thiz) { - this.a = np; - this.b = thiz; - } - @Override - public boolean apply(Node n) { - return b.apply(n) && a.apply(n); - } - } - - public static final class OrPredicate extends NodePredicate { - private final NodePredicate a; - private final NodePredicate b; - private OrPredicate(NodePredicate np, NodePredicate thiz) { - this.a = np; - this.b = thiz; - } - @Override - public boolean apply(Node n) { - return b.apply(n) || a.apply(n); - } - } - - public static final class IsNullPredicate extends NodePredicate { - @Override - public boolean apply(Node n) { - return n == null; - } - } - - public static final class EqualsPredicate extends NodePredicate { - private final T u; - public EqualsPredicate(T u) { - this.u = u; - } - @Override - public boolean apply(Node n) { - return u == n; - } - } public abstract boolean apply(Node n); - public NodePredicate and(final NodePredicate np) { - if (this instanceof TautologyPredicate) { - return np; - } - return new AndPredicate(this, np); + public NodePredicate and(NodePredicate np) { + return NodePredicates.and(this, np); } - public NodePredicate or(final NodePredicate np) { - if (this instanceof TautologyPredicate) { - return this; - } - return new OrPredicate(this, np); + public NodePredicate or(NodePredicate np) { + return NodePredicates.or(this, np); } - public static EqualsPredicate equals(T u) { - return new EqualsPredicate<>(u); + public NodePredicate negate() { + return NodePredicates.not(this); } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodePredicates.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/NodePredicates.java Sun Feb 05 05:40:36 2012 +0100 @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2012, 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.oracle.max.graal.graph.iterators; + +import com.oracle.max.graal.graph.*; + +public abstract class NodePredicates { + private static final TautologyPredicate TAUTOLOGY = new TautologyPredicate(); + private static final FalsePredicate FALSE = new FalsePredicate(); + private static final IsNullPredicate IS_NULL = new IsNullPredicate(); + private static final IsNotNullPredicate IS_NOT_NULL = new IsNotNullPredicate(); + + public static NodePredicate alwaysTrue() { + return TAUTOLOGY; + } + + public static NodePredicate alwaysFalse() { + return FALSE; + } + + public static NodePredicate isNull() { + return IS_NULL; + } + + public static NodePredicate isNotNull() { + return IS_NOT_NULL; + } + + public static NodePredicate equals(Node n) { + return new EqualsPredicate(n); + } + + public static NodePredicate not(NodePredicate a) { + if (a == TAUTOLOGY) { + return FALSE; + } + if (a == FALSE) { + return TAUTOLOGY; + } + if (a == IS_NULL) { + return IS_NOT_NULL; + } + if (a == IS_NOT_NULL) { + return IS_NULL; + } + if (a instanceof NotPredicate) { + return ((NotPredicate) a).a; + } + if (a instanceof PositiveTypePredicate) { + return new NegativeTypePredicate((PositiveTypePredicate) a); + } + if (a instanceof NegativeTypePredicate) { + return new PositiveTypePredicate((NegativeTypePredicate) a); + } + if (a instanceof EqualsPredicate) { + return new NotEqualsPredicate(((EqualsPredicate) a).u); + } + if (a instanceof NotEqualsPredicate) { + return new EqualsPredicate(((NotEqualsPredicate) a).u); + } + return new NotPredicate(a); + } + + public static NodePredicate and(NodePredicate a, NodePredicate b) { + if (a == TAUTOLOGY) { + return b; + } + if (b == TAUTOLOGY) { + return a; + } + if (a == FALSE || b == FALSE) { + return FALSE; + } + return new AndPredicate(a, b); + } + + public static NodePredicate or(NodePredicate a, NodePredicate b) { + if (a == FALSE) { + return b; + } + if (b == FALSE) { + return a; + } + if (a == TAUTOLOGY || b == TAUTOLOGY) { + return TAUTOLOGY; + } + return new OrPredicate(a, b); + } + + public static NegativeTypePredicate isNotA(Class clazz) { + return new NegativeTypePredicate(clazz); + } + + public static PositiveTypePredicate isA(Class clazz) { + return new PositiveTypePredicate(clazz); + } + + public static NodePredicate isAInterface(Class iface) { + assert iface.isInterface(); + return new PositiveTypePredicate(iface); + } + + public static NodePredicate isNotAInterface(Class iface) { + assert iface.isInterface(); + return new NegativeTypePredicate(iface); + } + + private static final class TautologyPredicate extends NodePredicate { + @Override + public boolean apply(Node n) { + return true; + } + } + + private static final class FalsePredicate extends NodePredicate { + @Override + public boolean apply(Node n) { + return false; + } + } + + private static final class AndPredicate extends NodePredicate { + private final NodePredicate a; + private final NodePredicate b; + private AndPredicate(NodePredicate a, NodePredicate b) { + this.a = a; + this.b = b; + } + @Override + public boolean apply(Node n) { + return a.apply(n) && b.apply(n); + } + } + + private static final class NotPredicate extends NodePredicate { + private final NodePredicate a; + private NotPredicate(NodePredicate n) { + this.a = n; + } + @Override + public boolean apply(Node n) { + return !a.apply(n); + } + } + + private static final class OrPredicate extends NodePredicate { + private final NodePredicate a; + private final NodePredicate b; + private OrPredicate(NodePredicate a, NodePredicate b) { + this.a = a; + this.b = b; + } + @Override + public boolean apply(Node n) { + return a.apply(n) || b.apply(n); + } + } + + private static final class IsNullPredicate extends NodePredicate { + @Override + public boolean apply(Node n) { + return n == null; + } + } + + private static final class IsNotNullPredicate extends NodePredicate { + @Override + public boolean apply(Node n) { + return n != null; + } + } + + private static final class EqualsPredicate extends NodePredicate { + private final Node u; + public EqualsPredicate(Node u) { + this.u = u; + } + @Override + public boolean apply(Node n) { + return u == n; + } + } + + private static final class NotEqualsPredicate extends NodePredicate { + private final Node u; + public NotEqualsPredicate(Node u) { + this.u = u; + } + @Override + public boolean apply(Node n) { + return u != n; + } + } + + public static final class PositiveTypePredicate extends NodePredicate { + private final Class type; + private PositiveTypePredicate or; + public PositiveTypePredicate(Class type) { + this.type = type; + } + public PositiveTypePredicate(NegativeTypePredicate a) { + type = a.type; + if (a.nor != null) { + or = new PositiveTypePredicate(a.nor); + } + } + @Override + public boolean apply(Node n) { + return type.isInstance(n) || (or != null && or.apply(n)); + } + public PositiveTypePredicate or(Class clazz) { + if (or == null) { + or = new PositiveTypePredicate(clazz); + } else { + or.or(clazz); + } + return this; + } + } + + public static final class NegativeTypePredicate extends NodePredicate { + private final Class type; + private NegativeTypePredicate nor; + public NegativeTypePredicate(Class type) { + this.type = type; + } + public NegativeTypePredicate(PositiveTypePredicate a) { + type = a.type; + if (a.or != null) { + nor = new NegativeTypePredicate(a.or); + } + } + @Override + public boolean apply(Node n) { + return !type.isInstance(n) && (nor == null || nor.apply(n)); + } + public NegativeTypePredicate nor(Class clazz) { + if (nor == null) { + nor = new NegativeTypePredicate(clazz); + } else { + nor.nor(clazz); + } + return this; + } + } +} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/PredicatedProxyNodeIterator.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/PredicatedProxyNodeIterator.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/PredicatedProxyNodeIterator.java Sun Feb 05 05:40:36 2012 +0100 @@ -29,8 +29,9 @@ public final class PredicatedProxyNodeIterator extends NodeIterator { private final Iterator iterator; private final NodePredicate predicate; + private final NodePredicate until; public PredicatedProxyNodeIterator(NodePredicate until, Iterator iterator, NodePredicate predicate) { - super(until); + this.until = until; this.iterator = iterator; this.predicate = predicate; } @@ -39,7 +40,7 @@ while ((current == null || !current.isAlive() || !predicate.apply(current)) && iterator.hasNext()) { current = iterator.next(); } - if (current != null && (!current.isAlive() || !predicate.apply(current))) { + if (current != null && (!current.isAlive() || !predicate.apply(current) || until.apply(current))) { current = null; } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/TypePredicate.java --- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/iterators/TypePredicate.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * 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.oracle.max.graal.graph.iterators; - -import com.oracle.max.graal.graph.*; - -public final class TypePredicate extends NodePredicate { - private final Class type; - public TypePredicate(Class< ? extends Node> type) { - this.type = type; - } - @Override - public boolean apply(Node n) { - return type.isInstance(n); - } -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java Sun Feb 05 05:40:36 2012 +0100 @@ -25,6 +25,7 @@ import java.util.*; import java.util.regex.*; +import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.debug.*; @@ -76,7 +77,6 @@ filter = filter.replace("[", "\\["); filter = filter.replace("]", "\\]"); filter = filter.replace(":", "\\:");*/ - System.out.println("regexp: " + filter + " string=" + currentScope + ", " + Pattern.matches(filter, currentScope)); return Pattern.matches(filter, currentScope); } return currentScope.contains(filter); @@ -89,7 +89,7 @@ for (Object o : Debug.context()) { if (o instanceof RiMethod) { RiMethod riMethod = (RiMethod) o; - if (riMethod.toString().contains(methodFilter)) { + if (CiUtil.format("%H.%n", riMethod).contains(methodFilter)) { return true; } } @@ -121,7 +121,11 @@ @Override public RuntimeException interceptException(RuntimeException e) { - Debug.setConfig(Debug.fixedConfig(true, true, false, false)); + if (e instanceof CiBailout) { + return e; + } + Debug.setConfig(Debug.fixedConfig(true, true, false, false, dumpHandlers)); + // sync "Exception occured in scope: " with mx/sanitycheck.py::Test.__init__ Debug.log(String.format("Exception occured in scope: %s", Debug.currentScope())); for (Object o : Debug.context()) { Debug.log("Context obj %s", o); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java Sun Feb 05 05:40:36 2012 +0100 @@ -31,7 +31,7 @@ import com.oracle.max.graal.hotspot.ri.*; /** - * Entries into the HotSpot VM from Java code. + * Calls from Java into HotSpot. */ public interface CompilerToVM { diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompiler.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompiler.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompiler.java Sun Feb 05 05:40:36 2012 +0100 @@ -28,7 +28,7 @@ import com.oracle.max.graal.hotspot.ri.*; /** - * Exits from the HotSpot VM into Java code. + * Calls from HotSpot into Java. */ public interface VMToCompiler { diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java Sun Feb 05 05:40:36 2012 +0100 @@ -39,6 +39,7 @@ import com.oracle.max.graal.hotspot.Compiler; import com.oracle.max.graal.hotspot.ri.*; import com.oracle.max.graal.hotspot.server.*; +import com.oracle.max.graal.hotspot.snippets.*; import com.oracle.max.graal.java.*; import com.oracle.max.graal.snippets.*; @@ -49,6 +50,7 @@ private final Compiler compiler; private int compiledMethodCount; + private IntrinsifyArrayCopyPhase intrinsifyArrayCopy; public final HotSpotTypePrimitive typeBoolean; public final HotSpotTypePrimitive typeChar; @@ -110,9 +112,11 @@ // Install intrinsics. HotSpotRuntime runtime = (HotSpotRuntime) compiler.getCompiler().runtime; if (GraalOptions.Intrinsify) { + this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime); GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget(), PhasePlan.DEFAULT); Snippets.install(runtime, runtime.getCompiler().getTarget(), new SystemSnippets(), PhasePlan.DEFAULT); Snippets.install(runtime, runtime.getCompiler().getTarget(), new UnsafeSnippets(), PhasePlan.DEFAULT); + Snippets.install(runtime, runtime.getCompiler().getTarget(), new ArrayCopySnippets(), PhasePlan.DEFAULT); } // Create compilation queue. @@ -227,15 +231,27 @@ @Override public void compileMethod(final HotSpotMethodResolved method, final int entryBCI, boolean blocking) throws Throwable { try { - if (Thread.currentThread() instanceof CompilerThread && method.holder().name().contains("java/util/concurrent")) { - return; + if (Thread.currentThread() instanceof CompilerThread) { + if (method.holder().name().contains("java/util/concurrent")) { + // This is required to avoid deadlocking a compiler thread. The issue is that a + // java.util.concurrent.BlockingQueue is used to implement the compilation worker + // queues. If a compiler thread triggers a compilation, then it may be blocked trying + // to add something to its own queue. + return; + } + } else { + if (GraalOptions.Debug) { + Debug.enable(); + HotSpotDebugConfig hotspotDebugConfig = new HotSpotDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter); + Debug.setConfig(hotspotDebugConfig); + } } Runnable runnable = new Runnable() { public void run() { try { - PhasePlan plan = new PhasePlan(); + PhasePlan plan = getDefaultPhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime()); plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); long startTime = 0; @@ -372,4 +388,10 @@ public CiConstant createCiConstantObject(Object object) { return CiConstant.forObject(object); } + + private PhasePlan getDefaultPhasePlan() { + PhasePlan phasePlan = new PhasePlan(); + phasePlan.addPhase(PhasePosition.HIGH_LEVEL, intrinsifyArrayCopy); + return phasePlan; + } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/nodes/TailcallNode.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/nodes/TailcallNode.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/nodes/TailcallNode.java Sun Feb 05 05:40:36 2012 +0100 @@ -30,6 +30,7 @@ import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.hotspot.*; import com.oracle.max.graal.hotspot.target.amd64.*; +import com.oracle.max.graal.java.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.spi.*; import com.oracle.max.graal.nodes.type.*; @@ -62,10 +63,10 @@ CiKind[] signature = CiUtil.signatureToKinds(method.signature(), isStatic ? null : method.holder().kind(true)); CiCallingConvention cc = gen.frameMap().registerConfig.getCallingConvention(CiCallingConvention.Type.JavaCall, signature, gen.target(), false); - gen.frameMap().callsMethod(cc, CiCallingConvention.Type.JavaCall); + gen.frameMap().callsMethod(cc, CiCallingConvention.Type.JavaCall); // TODO (aw): I think this is unnecessary for a tail call. List parameters = new ArrayList<>(); - for (int i = 0; i < cc.locations.length; i++) { - parameters.add(frameState.localAt(i)); + for (int i = 0, slot = 0; i < cc.locations.length; i++, slot += FrameStateBuilder.stackSlots(frameState.localAt(slot).kind())) { + parameters.add(frameState.localAt(slot)); } List argList = gen.visitInvokeArguments(cc, parameters, null); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeResolvedImpl.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeResolvedImpl.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeResolvedImpl.java Sun Feb 05 05:40:36 2012 +0100 @@ -81,7 +81,11 @@ @Override public RiResolvedType uniqueConcreteSubtype() { - return (RiResolvedType) compiler.getVMEntries().RiType_uniqueConcreteSubtype(this); + if (isArrayClass()) { + return Modifier.isFinal(componentType().accessFlags()) ? this : null; + } else { + return (RiResolvedType) compiler.getVMEntries().RiType_uniqueConcreteSubtype(this); + } } @Override diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java Sun Feb 05 05:40:36 2012 +0100 @@ -637,14 +637,13 @@ } }; - private SimpleTemplates checkCastTemplates = new SimpleTemplates(NULL_CHECK) { + private IndexTemplates checkCastTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { asm.restart(CiKind.Void); XirParameter object = asm.createInputParameter("object", CiKind.Object); - final XirOperand hub; - hub = asm.createConstantInputParameter("hub", CiKind.Object); + final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", CiKind.Object); XirOperand objHub = asm.createTemp("objHub", CiKind.Object); @@ -657,15 +656,37 @@ } asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); - // if we get an exact match: succeed immediately - asm.jneq(slowPath, objHub, hub); - asm.bindInline(end); + if (hintCount == 0) { + assert !is(EXACT_HINTS, flags); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(slowPath, objHub, asm.o(null)); + asm.bindInline(end); - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jneq(end, objHub, asm.o(null)); + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(slowPath); + } else { + XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10); + // if we get an exact match: succeed immediately + for (int i = 0; i < hintCount; i++) { + XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object); + asm.mov(scratchObject, hintHub); + if (i < hintCount - 1) { + asm.jeq(end, objHub, scratchObject); + } else { + asm.jneq(slowPath, objHub, scratchObject); + } + } + asm.bindInline(end); + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(slowPath); + if (!is(EXACT_HINTS, flags)) { + checkSubtype(asm, objHub, objHub, hub); + asm.jneq(end, objHub, asm.o(null)); + } + } XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); + asm.mov(scratch, wordConst(asm, 2)); asm.callRuntime(CiRuntimeCall.Deoptimize, null); @@ -675,18 +696,16 @@ } }; - private SimpleTemplates instanceOfTemplates = new SimpleTemplates(NULL_CHECK) { + private IndexTemplates instanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { asm.restart(CiKind.Void); XirParameter object = asm.createInputParameter("object", CiKind.Object); - final XirOperand hub; - hub = asm.createConstantInputParameter("hub", CiKind.Object); + final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", CiKind.Object); XirOperand objHub = asm.createTemp("objHub", CiKind.Object); - XirLabel slowPath = asm.createOutOfLineLabel("slow path"); XirLabel trueSucc = asm.createInlineLabel(XirLabel.TrueSuccessor); XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor); @@ -696,37 +715,60 @@ } asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); - // if we get an exact match: succeed immediately - asm.jeq(trueSucc, objHub, hub); - asm.jmp(slowPath); + if (hintCount == 0) { + assert !is(EXACT_HINTS, flags); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(trueSucc); + } else { + XirLabel slowPath = null; + XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10); - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jeq(falseSucc, objHub, asm.o(null)); - asm.jmp(trueSucc); + // if we get an exact match: succeed immediately + for (int i = 0; i < hintCount; i++) { + XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object); + asm.mov(scratchObject, hintHub); + if (i < hintCount - 1) { + asm.jeq(trueSucc, objHub, scratchObject); + } else { + if (is(EXACT_HINTS, flags)) { + asm.jneq(falseSucc, objHub, scratchObject); + asm.jmp(trueSucc); + } else { + slowPath = asm.createOutOfLineLabel("slow path"); + asm.jneq(slowPath, objHub, scratchObject); + asm.jmp(trueSucc); + } + } + } + + // -- out of line ------------------------------------------------------- + if (slowPath != null) { + asm.bindOutOfLine(slowPath); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(trueSucc); + } + } return asm.finishTemplate("instanceof"); } }; - private SimpleTemplates materializeInstanceOfTemplates = new SimpleTemplates(NULL_CHECK) { + private IndexTemplates materializeInstanceOfTemplates = new IndexTemplates(NULL_CHECK, EXACT_HINTS) { @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { + protected XirTemplate create(CiXirAssembler asm, long flags, int hintCount) { XirOperand result = asm.restart(CiKind.Int); XirParameter object = asm.createInputParameter("object", CiKind.Object); - final XirOperand hub; - hub = asm.createConstantInputParameter("hub", CiKind.Object); + final XirOperand hub = is(EXACT_HINTS, flags) ? null : asm.createConstantInputParameter("hub", CiKind.Object); XirOperand trueValue = asm.createConstantInputParameter("trueValue", CiKind.Int); XirOperand falseValue = asm.createConstantInputParameter("falseValue", CiKind.Int); XirOperand objHub = asm.createTemp("objHub", CiKind.Object); - XirLabel slowPath = asm.createOutOfLineLabel("slow path"); - XirLabel trueSucc = asm.createInlineLabel("ok"); + XirLabel end = asm.createInlineLabel("end"); XirLabel falseSucc = asm.createInlineLabel("ko"); - XirLabel end = asm.createInlineLabel("end"); if (is(NULL_CHECK, flags)) { // null isn't "instanceof" anything @@ -734,22 +776,47 @@ } asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); - // if we get an exact match: succeed immediately - asm.jeq(trueSucc, objHub, hub); - asm.jmp(slowPath); + asm.mov(result, trueValue); + + if (hintCount == 0) { + assert !is(EXACT_HINTS, flags); + checkSubtype(asm, objHub, objHub, hub); + asm.jneq(end, objHub, asm.o(null)); + asm.bindInline(falseSucc); + asm.mov(result, falseValue); + asm.bindInline(end); + } else { + XirLabel slowPath = null; + XirOperand scratchObject = asm.createRegisterTemp("scratch", CiKind.Object, AMD64.r10); - asm.bindInline(trueSucc); - asm.mov(result, trueValue); - asm.jmp(end); - asm.bindInline(falseSucc); - asm.mov(result, falseValue); - asm.bindInline(end); + // if we get an exact match: succeed immediately + for (int i = 0; i < hintCount; i++) { + XirParameter hintHub = asm.createConstantInputParameter("hintHub" + i, CiKind.Object); + asm.mov(scratchObject, hintHub); + if (i < hintCount - 1) { + asm.jeq(end, objHub, scratchObject); + } else { + if (is(EXACT_HINTS, flags)) { + asm.jeq(end, objHub, scratchObject); + } else { + slowPath = asm.createOutOfLineLabel("slow path"); + asm.jeq(end, objHub, scratchObject); + asm.jmp(slowPath); + } + } + } + asm.bindInline(falseSucc); + asm.mov(result, falseValue); + asm.bindInline(end); - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jeq(falseSucc, objHub, asm.o(null)); - asm.jmp(trueSucc); + // -- out of line ------------------------------------------------------- + if (slowPath != null) { + asm.bindOutOfLine(slowPath); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(end); + } + } return asm.finishTemplate("instanceof"); } @@ -1253,18 +1320,62 @@ } @Override - public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { - return new XirSnippet(checkCastTemplates.get(site), receiver, hub); + public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact) { + if (hints == null || hints.length == 0) { + return new XirSnippet(checkCastTemplates.get(site, 0), receiver, hub); + } else { + XirArgument[] params = new XirArgument[hints.length + (hintsExact ? 1 : 2)]; + int i = 0; + params[i++] = receiver; + if (!hintsExact) { + params[i++] = hub; + } + for (RiResolvedType hint : hints) { + params[i++] = XirArgument.forObject(hint); + } + XirTemplate template = hintsExact ? checkCastTemplates.get(site, hints.length, EXACT_HINTS) : checkCastTemplates.get(site, hints.length); + return new XirSnippet(template, params); + } } @Override - public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type) { - return new XirSnippet(instanceOfTemplates.get(site), object, hub); + public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type, RiResolvedType[] hints, boolean hintsExact) { + if (hints == null || hints.length == 0) { + return new XirSnippet(instanceOfTemplates.get(site, 0), object, hub); + } else { + XirArgument[] params = new XirArgument[hints.length + (hintsExact ? 1 : 2)]; + int i = 0; + params[i++] = object; + if (!hintsExact) { + params[i++] = hub; + } + for (RiResolvedType hint : hints) { + params[i++] = XirArgument.forObject(hint); + } + XirTemplate template = hintsExact ? instanceOfTemplates.get(site, hints.length, EXACT_HINTS) : instanceOfTemplates.get(site, hints.length); + return new XirSnippet(template, params); + } } @Override - public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type) { - return new XirSnippet(materializeInstanceOfTemplates.get(site), object, hub, trueValue, falseValue); + public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type, RiResolvedType[] hints, boolean hintsExact) { + if (hints == null || hints.length == 0) { + return new XirSnippet(materializeInstanceOfTemplates.get(site, 0), object, hub, trueValue, falseValue); + } else { + XirArgument[] params = new XirArgument[hints.length + (hintsExact ? 3 : 4)]; + int i = 0; + params[i++] = object; + if (!hintsExact) { + params[i++] = hub; + } + params[i++] = trueValue; + params[i++] = falseValue; + for (RiResolvedType hint : hints) { + params[i++] = XirArgument.forObject(hint); + } + XirTemplate template = hintsExact ? materializeInstanceOfTemplates.get(site, hints.length, EXACT_HINTS) : materializeInstanceOfTemplates.get(site, hints.length); + return new XirSnippet(template, params); + } } @Override diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/TemplateFlag.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/TemplateFlag.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/TemplateFlag.java Sun Feb 05 05:40:36 2012 +0100 @@ -23,7 +23,7 @@ package com.oracle.max.graal.hotspot.ri; enum TemplateFlag { - NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED; + NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED, EXACT_HINTS; private static final long FIRST_FLAG = 0x0000000100000000L; public static final long FLAGS_MASK = 0x0000FFFF00000000L; diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/ArrayCopySnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/ArrayCopySnippets.java Sun Feb 05 05:40:36 2012 +0100 @@ -0,0 +1,462 @@ +/* + * 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.oracle.max.graal.hotspot.snippets; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.cri.*; +import com.oracle.max.graal.hotspot.*; +import com.oracle.max.graal.nodes.*; +import com.oracle.max.graal.nodes.extended.*; +import com.oracle.max.graal.nodes.spi.*; +import com.oracle.max.graal.nodes.type.*; +import com.oracle.max.graal.snippets.*; +import com.oracle.max.graal.snippets.nodes.*; + + +public class ArrayCopySnippets implements SnippetsInterface{ + + @Snippet + public static void arraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + if ((length & 0x01) == 0) { + if ((length & 0x02) == 0) { + if ((length & 0x04) == 0) { + copyLongsDown(src, srcPos, dest, destPos, length >> 3); + } else { + copyIntsDown(src, srcPos, dest, destPos, length >> 2); + } + } else { + copyShortsDown(src, srcPos, dest, destPos, length >> 1); + } + } else { + copyBytesDown(src, srcPos, dest, destPos, length); + } + } else { + if ((length & 0x01) == 0) { + if ((length & 0x02) == 0) { + if ((length & 0x04) == 0) { + copyLongsUp(src, srcPos, dest, destPos, length >> 3); + } else { + copyIntsUp(src, srcPos, dest, destPos, length >> 2); + } + } else { + copyShortsUp(src, srcPos, dest, destPos, length >> 1); + } + } else { + copyBytesUp(src, srcPos, dest, destPos, length); + } + } + } + + @Snippet + public static void arraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + if ((length & 0x01) == 0) { + if ((length & 0x02) == 0) { + copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2); + } else { + copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1); + } + } else { + copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length); + } + } else { + if ((length & 0x01) == 0) { + if ((length & 0x02) == 0) { + copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2); + } else { + copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1); + } + } else { + copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length); + } + } + } + + @Snippet + public static void arraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + if ((length & 0x01) == 0) { + if ((length & 0x02) == 0) { + copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2); + } else { + copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1); + } + } else { + copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length); + } + } else { + if ((length & 0x01) == 0) { + if ((length & 0x02) == 0) { + copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2); + } else { + copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1); + } + } else { + copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length); + } + } + } + + @Snippet + public static void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + if ((length & 0x01) == 0) { + copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1); + } else { + copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length); + } + } else { + if ((length & 0x01) == 0) { + copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1); + } else { + copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length); + } + } + } + + @Snippet + public static void arraycopy(float[] src, int srcPos, float[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + if ((length & 0x01) == 0) { + copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1); + } else { + copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length); + } + } else { + if ((length & 0x01) == 0) { + copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1); + } else { + copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length); + } + } + } + + @Snippet + public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length); + } else { + copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length); + } + } + + @Snippet + public static void arraycopy(double[] src, int srcPos, double[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length); + } else { + copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length); + } + } + + // Does NOT perform store checks + @Snippet + public static void arraycopy(Object[] src, int srcPos, Object[] dest, int destPos, int length) { + if (src == null || dest == null) { + throw new NullPointerException(); + } + if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { + throw new IndexOutOfBoundsException(); + } + if (src == dest && srcPos < destPos) { // bad aliased case + copyObjectsDown(src, srcPos * 8L, dest, destPos * 8L, length); + } else { + copyObjectsUp(src, srcPos * 8L, dest, destPos * 8L, length); + } + if (length > 0) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object); + int cardShift = CardTableShiftNode.get(); + long cardStart = CardTableStartNode.get(); + long dstAddr = GetObjectAddressNode.get(dest); + long start = (dstAddr + header + destPos * 8L) >>> cardShift; + long end = (dstAddr + header + (destPos + length - 1) * 8L) >>> cardShift; + long count = end - start + 1; + while (count-- > 0) { + DirectStoreNode.store((start + cardStart) + count, false); + } + } + } + + @Snippet + public static void copyBytesDown(Object src, int srcPos, Object dest, int destPos, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte); + for (long i = length - 1; i >= 0; i--) { + Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte); + UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte); + } + } + + @Snippet + public static void copyShortsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); + for (long i = (length - 1) * 2; i >= 0; i -= 2) { + Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short); + UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short); + } + } + + @Snippet + public static void copyIntsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); + for (long i = (length - 1) * 4; i >= 0; i -= 4) { + Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int); + UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int); + } + } + + @Snippet + public static void copyLongsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); + for (long i = (length - 1) * 8; i >= 0; i -= 8) { + Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long); + UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long); + } + } + + // Does NOT perform store checks + @Snippet + public static void copyObjectsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object); + for (long i = (length - 1) * 8; i >= 0; i -= 8) { + Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object); + DirectObjectStoreNode.store(dest, i + (destOffset + header), a); + } + } + + /** + * Copies {@code length} bytes from {@code src} starting at {@code srcPos} to {@code dest} starting at {@code destPos}. + * @param src source object + * @param srcPos source offset + * @param dest destination object + * @param destPos destination offset + * @param length number of bytes to copy + */ + @Snippet + public static void copyBytesUp(Object src, int srcPos, Object dest, int destPos, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte); + for (long i = 0; i < length; i++) { + Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte); + UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte); + } + } + + /** + * Copies {@code length} shorts from {@code src} starting at offset {@code srcOffset} (in bytes) to {@code dest} starting at offset {@code destOffset} (in bytes). + * @param src + * @param srcOffset (in bytes) + * @param dest + * @param destOffset (in bytes) + * @param length (in shorts) + */ + @Snippet + public static void copyShortsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); + for (long i = 0; i < length * 2L; i += 2) { + Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short); + UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short); + } + } + + @Snippet + public static void copyIntsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Int); + for (long i = 0; i < length * 4L; i += 4) { + Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int); + UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int); + } + } + + @Snippet + public static void copyLongsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Long); + for (long i = 0; i < length * 8L; i += 8) { + Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long); + UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long); + } + } + + // Does NOT perform store checks + @Snippet + public static void copyObjectsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { + long header = ArrayHeaderSizeNode.sizeFor(CiKind.Object); + for (long i = 0; i < length * 8L; i += 8) { + Object a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Object); + DirectObjectStoreNode.store(dest, i + (destOffset + header), a); + } + } + + private static class GetObjectAddressNode extends FixedWithNextNode implements LIRLowerable { + @Input private ValueNode object; + + public GetObjectAddressNode(ValueNode obj) { + super(StampFactory.forKind(CiKind.Long)); + this.object = obj; + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static long get(Object array) { + throw new UnsupportedOperationException(); + } + + @Override + public void generate(LIRGeneratorTool gen) { + CiValue obj = gen.newVariable(gen.target().wordKind); + gen.emitMove(gen.operand(object), obj); + gen.setResult(this, obj); + } + } + + private static class DirectStoreNode extends FixedWithNextNode implements LIRLowerable { + @Input private ValueNode address; + @Input private ValueNode value; + + public DirectStoreNode(ValueNode address, ValueNode value) { + super(StampFactory.illegal()); + this.address = address; + this.value = value; + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void store(long address, long value) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void store(long address, boolean value) { + throw new UnsupportedOperationException(); + } + + @Override + public void generate(LIRGeneratorTool gen) { + CiValue v = gen.operand(value); + gen.emitStore(new CiAddress(v.kind, gen.operand(address)), v, false); + } + } + + private static class DirectObjectStoreNode extends FixedWithNextNode implements Lowerable { + @Input private ValueNode object; + @Input private ValueNode value; + @Input private ValueNode offset; + + public DirectObjectStoreNode(ValueNode object, ValueNode offset, ValueNode value) { + super(StampFactory.illegal()); + this.object = object; + this.value = value; + this.offset = offset; + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void store(Object obj, long offset, long value) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void store(Object obj, long offset, boolean value) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void store(Object obj, long offset, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public void lower(CiLoweringTool tool) { + StructuredGraph graph = (StructuredGraph) this.graph(); + IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, value.kind(), 0, offset, graph, false); + WriteNode write = graph.add(new WriteNode(object, value, location)); + graph.replaceFixedWithFixed(this, write); + } + } + + private static class CardTableShiftNode extends ConstantNode { + public CardTableShiftNode() { + super(CiConstant.forInt(CompilerImpl.getInstance().getConfig().cardtableShift)); + } + + @NodeIntrinsic + public static int get() { + throw new UnsupportedOperationException(); + } + } + + private static class CardTableStartNode extends ConstantNode { + public CardTableStartNode() { + super(CiConstant.forLong(CompilerImpl.getInstance().getConfig().cardtableStartAddress)); + } + + @NodeIntrinsic + public static long get() { + throw new UnsupportedOperationException(); + } + } +} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -0,0 +1,129 @@ +/* + * 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.oracle.max.graal.hotspot.snippets; + +import java.lang.reflect.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.compiler.phases.*; +import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.cri.*; +import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.nodes.*; +import com.oracle.max.graal.nodes.java.*; + +public class IntrinsifyArrayCopyPhase extends Phase { + private final GraalRuntime runtime; + private RiResolvedMethod arrayCopy; + private RiResolvedMethod byteArrayCopy; + private RiResolvedMethod shortArrayCopy; + private RiResolvedMethod charArrayCopy; + private RiResolvedMethod intArrayCopy; + private RiResolvedMethod longArrayCopy; + private RiResolvedMethod floatArrayCopy; + private RiResolvedMethod doubleArrayCopy; + private RiResolvedMethod objectArrayCopy; + + public IntrinsifyArrayCopyPhase(GraalRuntime runtime) { + this.runtime = runtime; + try { + byteArrayCopy = getArrayCopySnippet(runtime, byte.class); + charArrayCopy = getArrayCopySnippet(runtime, char.class); + shortArrayCopy = getArrayCopySnippet(runtime, short.class); + intArrayCopy = getArrayCopySnippet(runtime, int.class); + longArrayCopy = getArrayCopySnippet(runtime, long.class); + floatArrayCopy = getArrayCopySnippet(runtime, float.class); + doubleArrayCopy = getArrayCopySnippet(runtime, double.class); + objectArrayCopy = getArrayCopySnippet(runtime, Object.class); + arrayCopy = runtime.getRiMethod(System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class)); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + + private static RiResolvedMethod getArrayCopySnippet(RiRuntime runtime, Class componentClass) throws NoSuchMethodException { + Class arrayClass = Array.newInstance(componentClass, 0).getClass(); + return runtime.getRiMethod(ArrayCopySnippets.class.getDeclaredMethod("arraycopy", arrayClass, int.class, arrayClass, int.class, int.class)); + } + + @Override + protected void run(StructuredGraph graph) { + boolean hits = false; + for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { + RiResolvedMethod targetMethod = methodCallTarget.targetMethod(); + RiResolvedMethod snippetMethod = null; + if (targetMethod == arrayCopy) { + ValueNode src = methodCallTarget.arguments().get(0); + ValueNode dest = methodCallTarget.arguments().get(2); + if (src == null || dest == null) { //TODO (gd) this should never be null : check + return; + } + RiResolvedType srcDeclaredType = src.declaredType(); + RiResolvedType destDeclaredType = dest.declaredType(); + if (srcDeclaredType != null + && srcDeclaredType.isArrayClass() + && destDeclaredType != null + && destDeclaredType.isArrayClass()) { + CiKind componentKind = srcDeclaredType.componentType().kind(false); + if (srcDeclaredType.componentType() == destDeclaredType.componentType()) { + if (componentKind == CiKind.Int) { + snippetMethod = intArrayCopy; + } else if (componentKind == CiKind.Char) { + snippetMethod = charArrayCopy; + } else if (componentKind == CiKind.Long) { + snippetMethod = longArrayCopy; + } else if (componentKind == CiKind.Byte) { + snippetMethod = byteArrayCopy; + } else if (componentKind == CiKind.Short) { + snippetMethod = shortArrayCopy; + } else if (componentKind == CiKind.Float) { + snippetMethod = floatArrayCopy; + } else if (componentKind == CiKind.Double) { + snippetMethod = doubleArrayCopy; + } else if (componentKind == CiKind.Object) { + snippetMethod = objectArrayCopy; + } + } else if (componentKind == CiKind.Object + && srcDeclaredType.componentType().isSubtypeOf(destDeclaredType.componentType())) { + snippetMethod = objectArrayCopy; + } + } + } + + if (snippetMethod != null) { + StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.compilerStorage().get(Graph.class); + assert snippetGraph != null : "ArrayCopySnippets should be installed"; + hits = true; + Debug.log("%s > Intinsify (%s)", Debug.currentScope(), snippetMethod.signature().argumentTypeAt(0, snippetMethod.holder()).componentType()); + InliningUtil.inline(methodCallTarget.invoke(), snippetGraph, false); + } + } + if (hits) { + new CanonicalizerPhase(null, runtime, null).apply(graph); + } + } +} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/SystemSnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/SystemSnippets.java Sun Feb 05 05:40:36 2012 +0100 @@ -0,0 +1,43 @@ +/* + * 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.oracle.max.graal.hotspot.snippets; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.graal.nodes.extended.*; +import com.oracle.max.graal.snippets.*; + +/** + * Snippets for {@link java.lang.System} methods. + */ +@ClassSubstitution(java.lang.System.class) +public class SystemSnippets implements SnippetsInterface { + + public static long currentTimeMillis() { + return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeMillis); + } + + public static long nanoTime() { + return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeNanos); + } + +} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/UnsafeSnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/snippets/UnsafeSnippets.java Sun Feb 05 05:40:36 2012 +0100 @@ -0,0 +1,252 @@ +/* + * 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.oracle.max.graal.hotspot.snippets; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.util.*; +import com.oracle.max.graal.nodes.extended.*; +import com.oracle.max.graal.nodes.java.*; +import com.oracle.max.graal.snippets.*; + +/** + * Snippets for {@link sun.misc.Unsafe} methods. + */ +@ClassSubstitution(sun.misc.Unsafe.class) +public class UnsafeSnippets implements SnippetsInterface { + + public boolean compareAndSwapObject(Object o, long offset, Object expected, Object x) { + return CompareAndSwapNode.compareAndSwap(o, offset, expected, x); + } + + public boolean compareAndSwapInt(Object o, long offset, int expected, int x) { + return CompareAndSwapNode.compareAndSwap(o, offset, expected, x); + } + + public boolean compareAndSwapLong(Object o, long offset, long expected, long x) { + return CompareAndSwapNode.compareAndSwap(o, offset, expected, x); + } + + public Object getObject(Object o, long offset) { + return UnsafeLoadNode.load(o, offset, CiKind.Object); + } + + public Object getObjectVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + Object result = getObject(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putObject(Object o, long offset, Object x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Object); + } + + public void putObjectVolatile(Object o, long offset, Object x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putObject(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public int getInt(Object o, long offset) { + Integer value = UnsafeLoadNode.load(o, offset, CiKind.Int); + return value; + } + + public int getIntVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + int result = getInt(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putInt(Object o, long offset, int x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Int); + } + + public void putIntVolatile(Object o, long offset, int x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putInt(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public boolean getBoolean(Object o, long offset) { + @JavacBug(id = 6995200) + Boolean result = UnsafeLoadNode.load(o, offset, CiKind.Boolean); + return result; + } + + public boolean getBooleanVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + boolean result = getBoolean(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putBoolean(Object o, long offset, boolean x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Boolean); + } + + public void putBooleanVolatile(Object o, long offset, boolean x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putBoolean(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public byte getByte(Object o, long offset) { + @JavacBug(id = 6995200) + Byte result = UnsafeLoadNode.load(o, offset, CiKind.Byte); + return result; + } + + public byte getByteVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + byte result = getByte(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putByte(Object o, long offset, byte x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Byte); + } + + public void putByteVolatile(Object o, long offset, byte x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putByte(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public short getShort(Object o, long offset) { + @JavacBug(id = 6995200) + Short result = UnsafeLoadNode.load(o, offset, CiKind.Short); + return result; + } + + public short getShortVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + short result = getShort(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putShort(Object o, long offset, short x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Short); + } + + public void putShortVolatile(Object o, long offset, short x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putShort(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public char getChar(Object o, long offset) { + @JavacBug(id = 6995200) + Character result = UnsafeLoadNode.load(o, offset, CiKind.Char); + return result; + } + + public char getCharVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + char result = getChar(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putChar(Object o, long offset, char x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Char); + } + + public void putCharVolatile(Object o, long offset, char x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putChar(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public long getLong(Object o, long offset) { + @JavacBug(id = 6995200) + Long result = UnsafeLoadNode.load(o, offset, CiKind.Long); + return result; + } + + public long getLongVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + long result = getLong(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putLong(Object o, long offset, long x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Long); + } + + public void putLongVolatile(Object o, long offset, long x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putLong(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public float getFloat(Object o, long offset) { + @JavacBug(id = 6995200) + Float result = UnsafeLoadNode.load(o, offset, CiKind.Float); + return result; + } + + public float getFloatVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + float result = getFloat(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putFloat(Object o, long offset, float x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Float); + } + + public void putFloatVolatile(Object o, long offset, float x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putFloat(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } + + public double getDouble(Object o, long offset) { + @JavacBug(id = 6995200) + Double result = UnsafeLoadNode.load(o, offset, CiKind.Double); + return result; + } + + public double getDoubleVolatile(Object o, long offset) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); + double result = getDouble(o, offset); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); + return result; + } + + public void putDouble(Object o, long offset, double x) { + UnsafeStoreNode.store(o, offset, x, CiKind.Double); + } + + public void putDoubleVolatile(Object o, long offset, double x) { + MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); + putDouble(o, offset, x); + MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); + } +} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/target/amd64/AMD64TailcallOp.java Sun Feb 05 05:40:36 2012 +0100 @@ -37,9 +37,15 @@ * Performs a hard-coded tail call to the specified target, which normally should be an RiCompiledCode instance. */ public class AMD64TailcallOp extends AMD64LIRInstruction { + public AMD64TailcallOp(List parameters, CiValue target, CiValue[] callingConvention) { super("TAILCALL", LIRInstruction.NO_OPERANDS, null, toArray(parameters, target), LIRInstruction.NO_OPERANDS, callingConvention.clone()); assert inputs.length == temps.length + 1; + + for (int i = 0; i < temps.length; i++) { + assert isRegister(temps[i]) : "too many parameters for tail call"; + assert sameRegister(temps[i], inputs[i]) : "inputs do not match calling convention"; + } } private static CiValue[] toArray(List parameters, CiValue target) { @@ -51,19 +57,6 @@ @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - // move all parameters to the correct positions, according to the calling convention - // TODO: These moves should not be part of the TAILCALL opcode, but emitted as separate MOVE instructions before. - for (int i = 0; i < inputs.length - 1; i++) { - assert inputs[i].kind == CiKind.Object || inputs[i].kind == CiKind.Int || inputs[i].kind == CiKind.Long : "only Object, int and long supported for now"; - assert isRegister(temps[i]) : "too many parameters"; - if (isRegister(inputs[i])) { - if (inputs[i] != temps[i]) { - masm.movq(asRegister(temps[i]), asRegister(inputs[i])); - } - } else { - masm.movq(asRegister(temps[i]), tasm.asAddress(inputs[i])); - } - } // destroy the current frame (now the return address is the top of stack) masm.leave(); @@ -74,10 +67,10 @@ @Override protected EnumSet flagsFor(OperandMode mode, int index) { - if (mode == OperandMode.Input && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Stack); - } else if (mode == OperandMode.Temp && index == 0) { - return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + if (mode == OperandMode.Input) { + return EnumSet.of(OperandFlag.Register); + } else if (mode == OperandMode.Temp) { + return EnumSet.of(OperandFlag.Register); } throw Util.shouldNotReachHere(); } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BciBlockMapping.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BciBlockMapping.java Sun Feb 05 05:40:36 2012 +0100 @@ -0,0 +1,631 @@ +/* + * 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.oracle.max.graal.java; + +import static com.oracle.max.graal.java.Bytecodes.*; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.nodes.*; + +/** + * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow + * graph. Note that this class serves a similar role to C1's {@code BlockListBuilder}, but makes fewer assumptions about + * what the compiler interface provides. It builds all basic blocks for the control flow graph without requiring the + * compiler interface to provide a bitmap of the beginning of basic blocks. It makes two linear passes; one over the + * bytecodes to build block starts and successor lists, and one pass over the block map to build the CFG. + * + * Note that the CFG built by this class is not connected to the actual {@code BlockBegin} instances; this class + * does, however, compute and assign the reverse postorder number of the blocks. This comment needs refinement. (MJJ) + * + *

More Details on {@link BciBlockMapping#build}

+ * + * If the method has any exception handlers the {@linkplain #exceptionMap exception map} will be created (TBD). + * + * The bytecodes are then scanned linearly looking for bytecodes that contain control transfers, e.g., {@code GOTO}, + * {@code RETURN}, {@code IFGE}, and creating the corresponding entries in {@link #successorMap} and {@link #blockMap}. + * In addition, if {@link #exceptionMap} is not null, entries are made for any bytecode that can cause an exception. + * More TBD. + * + * Observe that this process finds bytecodes that terminate basic blocks, so the {@link #moveSuccessorLists} method is + * called to reassign the successors to the {@code BlockBegin} node that actually starts the block. + * + *

Example

+ * + * Consider the following source code: + * + *
+ * 
+ *     public static int test(int arg1, int arg2) {
+ *         int x = 0;
+ *         while (arg2 > 0) {
+ *             if (arg1 > 0) {
+ *                 x += 1;
+ *             } else if (arg1 < 0) {
+ *                 x -= 1;
+ *             }
+ *         }
+ *         return x;
+ *     }
+ * 
+ * 
+ * + * This is translated by javac to the following bytecode: + * + *
+ * 
+ *    0:   iconst_0
+ *    1:   istore_2
+ *    2:   goto    22
+ *    5:   iload_0
+ *    6:   ifle    15
+ *    9:   iinc    2, 1
+ *    12:  goto    22
+ *    15:  iload_0
+ *    16:  ifge    22
+ *    19:  iinc    2, -1
+ *    22:  iload_1
+ *    23:  ifgt    5
+ *    26:  iload_2
+ *    27:  ireturn
+ *    
+ * 
+ * + * There are seven basic blocks in this method, 0..2, 5..6, 9..12, 15..16, 19..19, 22..23 and 26..27. Therefore, before + * the call to {@code moveSuccessorLists}, the {@code blockMap} array has {@code BlockBegin} nodes at indices 0, 5, 9, + * 15, 19, 22 and 26. The {@code successorMap} array has entries at 2, 6, 12, 16, 23, 27 corresponding to the control + * transfer bytecodes. The entry at index 6, for example, is a length two array of {@code BlockBegin} nodes for indices + * 9 and 15, which are the successors for the basic block 5..6. After the call to {@code moveSuccessors}, {@code + * successorMap} has entries at 0, 5, 9, 15, 19, 22 and 26, i.e, matching {@code blockMap}. + *

+ * Next the blocks are numbered using reverse + * post-order. For the above example this results in the numbering 2, 4, 7, 5, 6, 3, 8. Also loop header blocks are + * detected during the traversal by detecting a repeat visit to a block that is still being processed. This causes the + * block to be flagged as a loop header and also added to the {@link #loopBlocks} list. The {@code loopBlocks} list + * contains the blocks at 0, 5, 9, 15, 19, 22, with 22 as the loop header. (N.B. the loop header block is added multiple + * (4) times to this list). (Should 0 be in? It's not inside the loop). + * + * If the {@code computeStoresInLoops} argument to {@code build} is true, the {@code loopBlocks} list is processed to + * mark all local variables that are stored in the blocks in the list. + */ +public final class BciBlockMapping { + + public static class Block implements Cloneable { + public int startBci; + public int endBci; + public boolean isExceptionEntry; + public boolean isLoopHeader; + public int blockID; + + public FixedWithNextNode firstInstruction; + + public ArrayList successors = new ArrayList<>(2); + public int normalSuccessors; + + private boolean visited; + private boolean active; + public long loops; + + public HashMap jsrAlternatives; + public JsrScope jsrScope = JsrScope.EMPTY_SCOPE; + public Block jsrSuccessor; + public int jsrReturnBci; + public Block retSuccessor; + public boolean endsWithRet = false; + + public Block copy() { + try { + Block block = (Block) super.clone(); + block.successors = new ArrayList<>(successors); + return block; + } catch (CloneNotSupportedException e) { + throw new RuntimeException(e); + } + } + } + + public static class ExceptionBlock extends Block { + public RiExceptionHandler handler; + public int deoptBci; + } + + public static class DeoptBlock extends Block { + public DeoptBlock(int startBci) { + this.startBci = startBci; + } + } + + /** + * The blocks found in this method, in reverse postorder. + */ + public final List blocks; + + public final RiResolvedMethod method; + + private final RiExceptionHandler[] exceptionHandlers; + + private Block[] blockMap; + + public final BitSet canTrap; + + public boolean hasJsrBytecodes; + + public Block startBlock; + + public final boolean useBranchPrediction; + + /** + * Creates a new BlockMap instance from bytecode of the given method . + * @param method the compiler interface method containing the code + */ + public BciBlockMapping(RiResolvedMethod method, boolean useBranchPrediction) { + this.method = method; + exceptionHandlers = method.exceptionHandlers(); + this.blockMap = new Block[method.codeSize()]; + this.canTrap = new BitSet(blockMap.length); + this.blocks = new ArrayList<>(); + this.useBranchPrediction = useBranchPrediction; + } + + public RiExceptionHandler[] exceptionHandlers() { + return exceptionHandlers; + } + + /** + * Builds the block map and conservative CFG and numbers blocks. + */ + public void build() { + makeExceptionEntries(); + iterateOverBytecodes(); + addExceptionEdges(); + if (hasJsrBytecodes) { + if (!GraalOptions.SupportJsrBytecodes) { + throw new JsrNotSupportedBailout("jsr/ret parsing disabled"); + } + createJsrAlternatives(blockMap[0]); + } + computeBlockOrder(); + + initializeBlockIds(); + + startBlock = blockMap[0]; + + // Discard big arrays so that they can be GCed + blockMap = null; + } + + private void initializeBlockIds() { + for (int i = 0; i < blocks.size(); i++) { + blocks.get(i).blockID = i; + } + } + + private void makeExceptionEntries() { + // start basic blocks at all exception handler blocks and mark them as exception entries + for (RiExceptionHandler h : this.exceptionHandlers) { + Block xhandler = makeBlock(h.handlerBCI()); + xhandler.isExceptionEntry = true; + } + } + + private void iterateOverBytecodes() { + // iterate over the bytecodes top to bottom. + // mark the entrypoints of basic blocks and build lists of successors for + // all bytecodes that end basic blocks (i.e. goto, ifs, switches, throw, jsr, returns, ret) + byte[] code = method.code(); + Block current = null; + int bci = 0; + while (bci < code.length) { + if (current == null || blockMap[bci] != null) { + Block b = makeBlock(bci); + if (current != null) { + setSuccessors(current.endBci, b); + } + current = b; + } + blockMap[bci] = current; + current.endBci = bci; + + int opcode = Bytes.beU1(code, bci); + switch (opcode) { + case IRETURN: // fall through + case LRETURN: // fall through + case FRETURN: // fall through + case DRETURN: // fall through + case ARETURN: // fall through + case RETURN: { + current = null; + break; + } + case ATHROW: { + current = null; + canTrap.set(bci); + break; + } + case IFEQ: // fall through + case IFNE: // fall through + case IFLT: // fall through + case IFGE: // fall through + case IFGT: // fall through + case IFLE: // fall through + case IF_ICMPEQ: // fall through + case IF_ICMPNE: // fall through + case IF_ICMPLT: // fall through + case IF_ICMPGE: // fall through + case IF_ICMPGT: // fall through + case IF_ICMPLE: // fall through + case IF_ACMPEQ: // fall through + case IF_ACMPNE: // fall through + case IFNULL: // fall through + case IFNONNULL: { + current = null; + double probability = useBranchPrediction ? method.branchProbability(bci) : -1; + + Block b1 = probability == 0.0 ? new DeoptBlock(bci + Bytes.beS2(code, bci + 1)) : makeBlock(bci + Bytes.beS2(code, bci + 1)); + Block b2 = probability == 1.0 ? new DeoptBlock(bci + 3) : makeBlock(bci + 3); + setSuccessors(bci, b1, b2); + break; + } + case GOTO: + case GOTO_W: { + current = null; + int target = bci + Bytes.beSVar(code, bci + 1, opcode == GOTO_W); + Block b1 = makeBlock(target); + setSuccessors(bci, b1); + break; + } + case TABLESWITCH: { + current = null; + BytecodeTableSwitch sw = new BytecodeTableSwitch(code, bci); + setSuccessors(bci, makeSwitchSuccessors(sw)); + break; + } + case LOOKUPSWITCH: { + current = null; + BytecodeLookupSwitch sw = new BytecodeLookupSwitch(code, bci); + setSuccessors(bci, makeSwitchSuccessors(sw)); + break; + } + case JSR: + case JSR_W: { + hasJsrBytecodes = true; + int target = bci + Bytes.beSVar(code, bci + 1, opcode == JSR_W); + if (target == 0) { + throw new JsrNotSupportedBailout("jsr target bci 0 not allowed"); + } + Block b1 = makeBlock(target); + current.jsrSuccessor = b1; + current.jsrReturnBci = bci + lengthOf(opcode); + current = null; + setSuccessors(bci, b1); + break; + } + case RET: { + current.endsWithRet = true; + current = null; + break; + } + case WIDE: { + int opcode2 = Bytes.beU1(code, bci); + switch (opcode2) { + case RET: { + current.endsWithRet = true; + current = null; + break; + } + } + break; + } + case INVOKEINTERFACE: + case INVOKESPECIAL: + case INVOKESTATIC: + case INVOKEVIRTUAL: { + current = null; + int target = bci + lengthOf(code, bci); + Block b1 = makeBlock(target); + setSuccessors(bci, b1); + canTrap.set(bci); + break; + } + default: { + if (canTrap(opcode, bci)) { + canTrap.set(bci); + } + } + } + bci += lengthOf(code, bci); + } + } + + public boolean canTrap(int opcode, int bci) { + switch (opcode) { + case INVOKESTATIC: + case INVOKESPECIAL: + case INVOKEVIRTUAL: + case INVOKEINTERFACE: { + return true; + } + case IASTORE: + case LASTORE: + case FASTORE: + case DASTORE: + case AASTORE: + case BASTORE: + case CASTORE: + case SASTORE: + case IALOAD: + case LALOAD: + case FALOAD: + case DALOAD: + case AALOAD: + case BALOAD: + case CALOAD: + case SALOAD: + case PUTFIELD: + case GETFIELD: { + if (GraalOptions.AllowExplicitExceptionChecks) { + return method.exceptionProbability(bci) > 0; + } + } + } + return false; + } + + private Block makeBlock(int startBci) { + Block oldBlock = blockMap[startBci]; + if (oldBlock == null) { + Block newBlock = new Block(); + newBlock.startBci = startBci; + blockMap[startBci] = newBlock; + return newBlock; + + } else if (oldBlock.startBci != startBci) { + // Backward branch into the middle of an already processed block. + // Add the correct fall-through successor. + Block newBlock = new Block(); + newBlock.startBci = startBci; + newBlock.endBci = oldBlock.endBci; + newBlock.successors.addAll(oldBlock.successors); + newBlock.normalSuccessors = oldBlock.normalSuccessors; + + oldBlock.endBci = startBci - 1; + oldBlock.successors.clear(); + oldBlock.successors.add(newBlock); + oldBlock.normalSuccessors = 1; + + for (int i = startBci; i <= newBlock.endBci; i++) { + blockMap[i] = newBlock; + } + return newBlock; + + } else { + return oldBlock; + } + } + + private Block[] makeSwitchSuccessors(BytecodeSwitch tswitch) { + int max = tswitch.numberOfCases(); + Block[] successors = new Block[max + 1]; + for (int i = 0; i < max; i++) { + successors[i] = makeBlock(tswitch.targetAt(i)); + } + successors[max] = makeBlock(tswitch.defaultTarget()); + return successors; + } + + private void setSuccessors(int predBci, Block... successors) { + Block predecessor = blockMap[predBci]; + assert predecessor.successors.size() == 0; + for (Block sux : successors) { + if (sux.isExceptionEntry) { + throw new CiBailout("Exception handler can be reached by both normal and exceptional control flow"); + } + predecessor.successors.add(sux); + } + predecessor.normalSuccessors = successors.length; + } + + private final HashSet jsrVisited = new HashSet<>(); + + private void createJsrAlternatives(Block block) { + jsrVisited.add(block); + JsrScope scope = block.jsrScope; + + if (block.endsWithRet) { + block.retSuccessor = blockMap[scope.nextReturnAddress()]; + block.successors.add(block.retSuccessor); + assert block.retSuccessor != block.jsrSuccessor; + } + + if (block.jsrSuccessor != null || !scope.isEmpty()) { + for (int i = 0; i < block.successors.size(); i++) { + Block successor = block.successors.get(i); + JsrScope nextScope = scope; + if (successor == block.jsrSuccessor) { + nextScope = scope.push(block.jsrReturnBci); + } + if (successor == block.retSuccessor) { + nextScope = scope.pop(); + } + if (!successor.jsrScope.isEmpty()) { + throw new JsrNotSupportedBailout("unstructured control flow (" + successor.jsrScope + " " + nextScope + ")"); + } + if (!nextScope.isEmpty()) { + Block clone; + if (successor.jsrAlternatives != null && successor.jsrAlternatives.containsKey(nextScope)) { + clone = successor.jsrAlternatives.get(nextScope); + } else { + if (successor.jsrAlternatives == null) { + successor.jsrAlternatives = new HashMap<>(); + } + clone = successor.copy(); + clone.jsrScope = nextScope; + successor.jsrAlternatives.put(nextScope, clone); + } + block.successors.set(i, clone); + if (successor == block.jsrSuccessor) { + block.jsrSuccessor = clone; + } + if (successor == block.retSuccessor) { + block.retSuccessor = clone; + } + } + } + } + for (Block successor : block.successors) { + if (!jsrVisited.contains(successor)) { + createJsrAlternatives(successor); + } + } + } + + private HashMap exceptionDispatch = new HashMap<>(); + + private Block makeExceptionDispatch(List handlers, int index, int bci) { + RiExceptionHandler handler = handlers.get(index); + if (handler.isCatchAll()) { + return blockMap[handler.handlerBCI()]; + } + ExceptionBlock block = exceptionDispatch.get(handler); + if (block == null) { + block = new ExceptionBlock(); + block.startBci = -1; + block.endBci = -1; + block.deoptBci = bci; + block.handler = handler; + block.successors.add(blockMap[handler.handlerBCI()]); + if (index < handlers.size() - 1) { + block.successors.add(makeExceptionDispatch(handlers, index + 1, bci)); + } + exceptionDispatch.put(handler, block); + } + return block; + } + + private void addExceptionEdges() { + for (int bci = canTrap.nextSetBit(0); bci >= 0; bci = canTrap.nextSetBit(bci + 1)) { + Block block = blockMap[bci]; + + ArrayList handlers = null; + for (RiExceptionHandler h : this.exceptionHandlers) { + if (h.startBCI() <= bci && bci < h.endBCI()) { + if (handlers == null) { + handlers = new ArrayList<>(); + } + handlers.add(h); + if (h.isCatchAll()) { + break; + } + } + } + if (handlers != null) { + Block dispatch = makeExceptionDispatch(handlers, 0, bci); + block.successors.add(dispatch); + } + } + } + + private void computeBlockOrder() { + long loop = computeBlockOrder(blockMap[0]); + + if (loop != 0) { + // There is a path from a loop end to the method entry that does not pass the loop header. + // Therefore, the loop is non reducible (has more than one entry). + // We don't want to compile such methods because the IR only supports structured loops. + throw new CiBailout("Non-reducible loop"); + } + + // Convert postorder to the desired reverse postorder. + Collections.reverse(blocks); + } + + /** + * The next available loop number. + */ + private int nextLoop; + + /** + * Mark the block as a loop header, using the next available loop number. + * Also checks for corner cases that we don't want to compile. + */ + private void makeLoopHeader(Block block) { + if (!block.isLoopHeader) { + block.isLoopHeader = true; + + if (block.isExceptionEntry) { + // Loops that are implicitly formed by an exception handler lead to all sorts of corner cases. + // Don't compile such methods for now, until we see a concrete case that allows checking for correctness. + throw new CiBailout("Loop formed by an exception handler"); + } + if (nextLoop >= Long.SIZE) { + // This restriction can be removed by using a fall-back to a BitSet in case we have more than 64 loops + // Don't compile such methods for now, until we see a concrete case that allows checking for correctness. + throw new CiBailout("Too many loops in method"); + } + + assert block.loops == 0; + block.loops = (long) 1 << (long) nextLoop; + nextLoop++; + } + assert Long.bitCount(block.loops) == 1; + } + + /** + * Depth-first traversal of the control flow graph. The flag {@linkplain Block#visited} is used to + * visit every block only once. The flag {@linkplain Block#active} is used to detect cycles (backward + * edges). + */ + private long computeBlockOrder(Block block) { + if (block.visited) { + if (block.active) { + // Reached block via backward branch. + makeLoopHeader(block); + } + // Return cached loop information for this block. + return block.loops; + } + + block.visited = true; + block.active = true; + + int loops = 0; + for (Block successor : block.successors) { + // Recursively process successors. + loops |= computeBlockOrder(successor); + } + + if (block.isLoopHeader) { + assert Long.bitCount(block.loops) == 1; + loops &= ~block.loops; + } + + block.loops = loops; + block.active = false; + blocks.add(block); + + return loops; + } +} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BlockMap.java --- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/BlockMap.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,631 +0,0 @@ -/* - * 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.oracle.max.graal.java; - -import static com.oracle.max.graal.java.Bytecodes.*; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.nodes.*; - -/** - * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow - * graph. Note that this class serves a similar role to C1's {@code BlockListBuilder}, but makes fewer assumptions about - * what the compiler interface provides. It builds all basic blocks for the control flow graph without requiring the - * compiler interface to provide a bitmap of the beginning of basic blocks. It makes two linear passes; one over the - * bytecodes to build block starts and successor lists, and one pass over the block map to build the CFG. - * - * Note that the CFG built by this class is not connected to the actual {@code BlockBegin} instances; this class - * does, however, compute and assign the reverse postorder number of the blocks. This comment needs refinement. (MJJ) - * - *

More Details on {@link BlockMap#build}

- * - * If the method has any exception handlers the {@linkplain #exceptionMap exception map} will be created (TBD). - * - * The bytecodes are then scanned linearly looking for bytecodes that contain control transfers, e.g., {@code GOTO}, - * {@code RETURN}, {@code IFGE}, and creating the corresponding entries in {@link #successorMap} and {@link #blockMap}. - * In addition, if {@link #exceptionMap} is not null, entries are made for any bytecode that can cause an exception. - * More TBD. - * - * Observe that this process finds bytecodes that terminate basic blocks, so the {@link #moveSuccessorLists} method is - * called to reassign the successors to the {@code BlockBegin} node that actually starts the block. - * - *

Example

- * - * Consider the following source code: - * - *
- * 
- *     public static int test(int arg1, int arg2) {
- *         int x = 0;
- *         while (arg2 > 0) {
- *             if (arg1 > 0) {
- *                 x += 1;
- *             } else if (arg1 < 0) {
- *                 x -= 1;
- *             }
- *         }
- *         return x;
- *     }
- * 
- * 
- * - * This is translated by javac to the following bytecode: - * - *
- * 
- *    0:   iconst_0
- *    1:   istore_2
- *    2:   goto    22
- *    5:   iload_0
- *    6:   ifle    15
- *    9:   iinc    2, 1
- *    12:  goto    22
- *    15:  iload_0
- *    16:  ifge    22
- *    19:  iinc    2, -1
- *    22:  iload_1
- *    23:  ifgt    5
- *    26:  iload_2
- *    27:  ireturn
- *    
- * 
- * - * There are seven basic blocks in this method, 0..2, 5..6, 9..12, 15..16, 19..19, 22..23 and 26..27. Therefore, before - * the call to {@code moveSuccessorLists}, the {@code blockMap} array has {@code BlockBegin} nodes at indices 0, 5, 9, - * 15, 19, 22 and 26. The {@code successorMap} array has entries at 2, 6, 12, 16, 23, 27 corresponding to the control - * transfer bytecodes. The entry at index 6, for example, is a length two array of {@code BlockBegin} nodes for indices - * 9 and 15, which are the successors for the basic block 5..6. After the call to {@code moveSuccessors}, {@code - * successorMap} has entries at 0, 5, 9, 15, 19, 22 and 26, i.e, matching {@code blockMap}. - *

- * Next the blocks are numbered using reverse - * post-order. For the above example this results in the numbering 2, 4, 7, 5, 6, 3, 8. Also loop header blocks are - * detected during the traversal by detecting a repeat visit to a block that is still being processed. This causes the - * block to be flagged as a loop header and also added to the {@link #loopBlocks} list. The {@code loopBlocks} list - * contains the blocks at 0, 5, 9, 15, 19, 22, with 22 as the loop header. (N.B. the loop header block is added multiple - * (4) times to this list). (Should 0 be in? It's not inside the loop). - * - * If the {@code computeStoresInLoops} argument to {@code build} is true, the {@code loopBlocks} list is processed to - * mark all local variables that are stored in the blocks in the list. - */ -public final class BlockMap { - - public static class Block implements Cloneable { - public int startBci; - public int endBci; - public boolean isExceptionEntry; - public boolean isLoopHeader; - public int blockID; - - public FixedWithNextNode firstInstruction; - - public ArrayList successors = new ArrayList<>(2); - public int normalSuccessors; - - private boolean visited; - private boolean active; - public long loops; - - public HashMap jsrAlternatives; - public JsrScope jsrScope = JsrScope.EMPTY_SCOPE; - public Block jsrSuccessor; - public int jsrReturnBci; - public Block retSuccessor; - public boolean endsWithRet = false; - - public Block copy() { - try { - Block block = (Block) super.clone(); - block.successors = new ArrayList<>(successors); - return block; - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } - } - } - - public static class ExceptionBlock extends Block { - public RiExceptionHandler handler; - public int deoptBci; - } - - public static class DeoptBlock extends Block { - public DeoptBlock(int startBci) { - this.startBci = startBci; - } - } - - /** - * The blocks found in this method, in reverse postorder. - */ - public final List blocks; - - public final RiResolvedMethod method; - - private final RiExceptionHandler[] exceptionHandlers; - - private Block[] blockMap; - - public final BitSet canTrap; - - public boolean hasJsrBytecodes; - - public Block startBlock; - - public final boolean useBranchPrediction; - - /** - * Creates a new BlockMap instance from bytecode of the given method . - * @param method the compiler interface method containing the code - */ - public BlockMap(RiResolvedMethod method, boolean useBranchPrediction) { - this.method = method; - exceptionHandlers = method.exceptionHandlers(); - this.blockMap = new Block[method.codeSize()]; - this.canTrap = new BitSet(blockMap.length); - this.blocks = new ArrayList<>(); - this.useBranchPrediction = useBranchPrediction; - } - - public RiExceptionHandler[] exceptionHandlers() { - return exceptionHandlers; - } - - /** - * Builds the block map and conservative CFG and numbers blocks. - */ - public void build() { - makeExceptionEntries(); - iterateOverBytecodes(); - addExceptionEdges(); - if (hasJsrBytecodes) { - if (!GraalOptions.SupportJsrBytecodes) { - throw new JsrNotSupportedBailout("jsr/ret parsing disabled"); - } - createJsrAlternatives(blockMap[0]); - } - computeBlockOrder(); - - initializeBlockIds(); - - startBlock = blockMap[0]; - - // Discard big arrays so that they can be GCed - blockMap = null; - } - - private void initializeBlockIds() { - for (int i = 0; i < blocks.size(); i++) { - blocks.get(i).blockID = i; - } - } - - private void makeExceptionEntries() { - // start basic blocks at all exception handler blocks and mark them as exception entries - for (RiExceptionHandler h : this.exceptionHandlers) { - Block xhandler = makeBlock(h.handlerBCI()); - xhandler.isExceptionEntry = true; - } - } - - private void iterateOverBytecodes() { - // iterate over the bytecodes top to bottom. - // mark the entrypoints of basic blocks and build lists of successors for - // all bytecodes that end basic blocks (i.e. goto, ifs, switches, throw, jsr, returns, ret) - byte[] code = method.code(); - Block current = null; - int bci = 0; - while (bci < code.length) { - if (current == null || blockMap[bci] != null) { - Block b = makeBlock(bci); - if (current != null) { - setSuccessors(current.endBci, b); - } - current = b; - } - blockMap[bci] = current; - current.endBci = bci; - - int opcode = Bytes.beU1(code, bci); - switch (opcode) { - case IRETURN: // fall through - case LRETURN: // fall through - case FRETURN: // fall through - case DRETURN: // fall through - case ARETURN: // fall through - case RETURN: { - current = null; - break; - } - case ATHROW: { - current = null; - canTrap.set(bci); - break; - } - case IFEQ: // fall through - case IFNE: // fall through - case IFLT: // fall through - case IFGE: // fall through - case IFGT: // fall through - case IFLE: // fall through - case IF_ICMPEQ: // fall through - case IF_ICMPNE: // fall through - case IF_ICMPLT: // fall through - case IF_ICMPGE: // fall through - case IF_ICMPGT: // fall through - case IF_ICMPLE: // fall through - case IF_ACMPEQ: // fall through - case IF_ACMPNE: // fall through - case IFNULL: // fall through - case IFNONNULL: { - current = null; - double probability = useBranchPrediction ? method.branchProbability(bci) : -1; - - Block b1 = probability == 0.0 ? new DeoptBlock(bci + Bytes.beS2(code, bci + 1)) : makeBlock(bci + Bytes.beS2(code, bci + 1)); - Block b2 = probability == 1.0 ? new DeoptBlock(bci + 3) : makeBlock(bci + 3); - setSuccessors(bci, b1, b2); - break; - } - case GOTO: - case GOTO_W: { - current = null; - int target = bci + Bytes.beSVar(code, bci + 1, opcode == GOTO_W); - Block b1 = makeBlock(target); - setSuccessors(bci, b1); - break; - } - case TABLESWITCH: { - current = null; - BytecodeTableSwitch sw = new BytecodeTableSwitch(code, bci); - setSuccessors(bci, makeSwitchSuccessors(sw)); - break; - } - case LOOKUPSWITCH: { - current = null; - BytecodeLookupSwitch sw = new BytecodeLookupSwitch(code, bci); - setSuccessors(bci, makeSwitchSuccessors(sw)); - break; - } - case JSR: - case JSR_W: { - hasJsrBytecodes = true; - int target = bci + Bytes.beSVar(code, bci + 1, opcode == JSR_W); - if (target == 0) { - throw new JsrNotSupportedBailout("jsr target bci 0 not allowed"); - } - Block b1 = makeBlock(target); - current.jsrSuccessor = b1; - current.jsrReturnBci = bci + lengthOf(opcode); - current = null; - setSuccessors(bci, b1); - break; - } - case RET: { - current.endsWithRet = true; - current = null; - break; - } - case WIDE: { - int opcode2 = Bytes.beU1(code, bci); - switch (opcode2) { - case RET: { - current.endsWithRet = true; - current = null; - break; - } - } - break; - } - case INVOKEINTERFACE: - case INVOKESPECIAL: - case INVOKESTATIC: - case INVOKEVIRTUAL: { - current = null; - int target = bci + lengthOf(code, bci); - Block b1 = makeBlock(target); - setSuccessors(bci, b1); - canTrap.set(bci); - break; - } - default: { - if (canTrap(opcode, bci)) { - canTrap.set(bci); - } - } - } - bci += lengthOf(code, bci); - } - } - - public boolean canTrap(int opcode, int bci) { - switch (opcode) { - case INVOKESTATIC: - case INVOKESPECIAL: - case INVOKEVIRTUAL: - case INVOKEINTERFACE: { - return true; - } - case IASTORE: - case LASTORE: - case FASTORE: - case DASTORE: - case AASTORE: - case BASTORE: - case CASTORE: - case SASTORE: - case IALOAD: - case LALOAD: - case FALOAD: - case DALOAD: - case AALOAD: - case BALOAD: - case CALOAD: - case SALOAD: - case PUTFIELD: - case GETFIELD: { - if (GraalOptions.AllowExplicitExceptionChecks) { - return method.exceptionProbability(bci) > 0; - } - } - } - return false; - } - - private Block makeBlock(int startBci) { - Block oldBlock = blockMap[startBci]; - if (oldBlock == null) { - Block newBlock = new Block(); - newBlock.startBci = startBci; - blockMap[startBci] = newBlock; - return newBlock; - - } else if (oldBlock.startBci != startBci) { - // Backward branch into the middle of an already processed block. - // Add the correct fall-through successor. - Block newBlock = new Block(); - newBlock.startBci = startBci; - newBlock.endBci = oldBlock.endBci; - newBlock.successors.addAll(oldBlock.successors); - newBlock.normalSuccessors = oldBlock.normalSuccessors; - - oldBlock.endBci = startBci - 1; - oldBlock.successors.clear(); - oldBlock.successors.add(newBlock); - oldBlock.normalSuccessors = 1; - - for (int i = startBci; i <= newBlock.endBci; i++) { - blockMap[i] = newBlock; - } - return newBlock; - - } else { - return oldBlock; - } - } - - private Block[] makeSwitchSuccessors(BytecodeSwitch tswitch) { - int max = tswitch.numberOfCases(); - Block[] successors = new Block[max + 1]; - for (int i = 0; i < max; i++) { - successors[i] = makeBlock(tswitch.targetAt(i)); - } - successors[max] = makeBlock(tswitch.defaultTarget()); - return successors; - } - - private void setSuccessors(int predBci, Block... successors) { - Block predecessor = blockMap[predBci]; - assert predecessor.successors.size() == 0; - for (Block sux : successors) { - if (sux.isExceptionEntry) { - throw new CiBailout("Exception handler can be reached by both normal and exceptional control flow"); - } - predecessor.successors.add(sux); - } - predecessor.normalSuccessors = successors.length; - } - - private final HashSet jsrVisited = new HashSet<>(); - - private void createJsrAlternatives(Block block) { - jsrVisited.add(block); - JsrScope scope = block.jsrScope; - - if (block.endsWithRet) { - block.retSuccessor = blockMap[scope.nextReturnAddress()]; - block.successors.add(block.retSuccessor); - assert block.retSuccessor != block.jsrSuccessor; - } - - if (block.jsrSuccessor != null || !scope.isEmpty()) { - for (int i = 0; i < block.successors.size(); i++) { - Block successor = block.successors.get(i); - JsrScope nextScope = scope; - if (successor == block.jsrSuccessor) { - nextScope = scope.push(block.jsrReturnBci); - } - if (successor == block.retSuccessor) { - nextScope = scope.pop(); - } - if (!successor.jsrScope.isEmpty()) { - throw new JsrNotSupportedBailout("unstructured control flow (" + successor.jsrScope + " " + nextScope + ")"); - } - if (!nextScope.isEmpty()) { - Block clone; - if (successor.jsrAlternatives != null && successor.jsrAlternatives.containsKey(nextScope)) { - clone = successor.jsrAlternatives.get(nextScope); - } else { - if (successor.jsrAlternatives == null) { - successor.jsrAlternatives = new HashMap<>(); - } - clone = successor.copy(); - clone.jsrScope = nextScope; - successor.jsrAlternatives.put(nextScope, clone); - } - block.successors.set(i, clone); - if (successor == block.jsrSuccessor) { - block.jsrSuccessor = clone; - } - if (successor == block.retSuccessor) { - block.retSuccessor = clone; - } - } - } - } - for (Block successor : block.successors) { - if (!jsrVisited.contains(successor)) { - createJsrAlternatives(successor); - } - } - } - - private HashMap exceptionDispatch = new HashMap<>(); - - private Block makeExceptionDispatch(List handlers, int index, int bci) { - RiExceptionHandler handler = handlers.get(index); - if (handler.isCatchAll()) { - return blockMap[handler.handlerBCI()]; - } - ExceptionBlock block = exceptionDispatch.get(handler); - if (block == null) { - block = new ExceptionBlock(); - block.startBci = -1; - block.endBci = -1; - block.deoptBci = bci; - block.handler = handler; - block.successors.add(blockMap[handler.handlerBCI()]); - if (index < handlers.size() - 1) { - block.successors.add(makeExceptionDispatch(handlers, index + 1, bci)); - } - exceptionDispatch.put(handler, block); - } - return block; - } - - private void addExceptionEdges() { - for (int bci = canTrap.nextSetBit(0); bci >= 0; bci = canTrap.nextSetBit(bci + 1)) { - Block block = blockMap[bci]; - - ArrayList handlers = null; - for (RiExceptionHandler h : this.exceptionHandlers) { - if (h.startBCI() <= bci && bci < h.endBCI()) { - if (handlers == null) { - handlers = new ArrayList<>(); - } - handlers.add(h); - if (h.isCatchAll()) { - break; - } - } - } - if (handlers != null) { - Block dispatch = makeExceptionDispatch(handlers, 0, bci); - block.successors.add(dispatch); - } - } - } - - private void computeBlockOrder() { - long loop = computeBlockOrder(blockMap[0]); - - if (loop != 0) { - // There is a path from a loop end to the method entry that does not pass the loop header. - // Therefore, the loop is non reducible (has more than one entry). - // We don't want to compile such methods because the IR only supports structured loops. - throw new CiBailout("Non-reducible loop"); - } - - // Convert postorder to the desired reverse postorder. - Collections.reverse(blocks); - } - - /** - * The next available loop number. - */ - private int nextLoop; - - /** - * Mark the block as a loop header, using the next available loop number. - * Also checks for corner cases that we don't want to compile. - */ - private void makeLoopHeader(Block block) { - if (!block.isLoopHeader) { - block.isLoopHeader = true; - - if (block.isExceptionEntry) { - // Loops that are implicitly formed by an exception handler lead to all sorts of corner cases. - // Don't compile such methods for now, until we see a concrete case that allows checking for correctness. - throw new CiBailout("Loop formed by an exception handler"); - } - if (nextLoop >= Long.SIZE) { - // This restriction can be removed by using a fall-back to a BitSet in case we have more than 32 loops - // Don't compile such methods for now, until we see a concrete case that allows checking for correctness. - throw new CiBailout("Too many loops in method"); - } - - assert block.loops == 0; - block.loops = (long) 1 << (long) nextLoop; - nextLoop++; - } - assert Long.bitCount(block.loops) == 1; - } - - /** - * Depth-first traversal of the control flow graph. The flag {@linkplain Block#visited} is used to - * visit every block only once. The flag {@linkplain Block#active} is used to detect cycles (backward - * edges). - */ - private long computeBlockOrder(Block block) { - if (block.visited) { - if (block.active) { - // Reached block via backward branch. - makeLoopHeader(block); - } - // Return cached loop information for this block. - return block.loops; - } - - block.visited = true; - block.active = true; - - int loops = 0; - for (Block successor : block.successors) { - // Recursively process successors. - loops |= computeBlockOrder(successor); - } - - if (block.isLoopHeader) { - assert Long.bitCount(block.loops) == 1; - loops &= ~block.loops; - } - - block.loops = loops; - block.active = false; - blocks.add(block); - - return loops; - } -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.java/src/com/oracle/max/graal/java/GraphBuilderPhase.java Sun Feb 05 05:40:36 2012 +0100 @@ -34,13 +34,12 @@ import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.phases.*; -import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.debug.*; import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.java.BlockMap.Block; -import com.oracle.max.graal.java.BlockMap.DeoptBlock; -import com.oracle.max.graal.java.BlockMap.ExceptionBlock; +import com.oracle.max.graal.java.BciBlockMapping.Block; +import com.oracle.max.graal.java.BciBlockMapping.DeoptBlock; +import com.oracle.max.graal.java.BciBlockMapping.ExceptionBlock; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.DeoptimizeNode.DeoptAction; import com.oracle.max.graal.nodes.PhiNode.PhiType; @@ -136,8 +135,8 @@ return getName() + " " + CiUtil.format("%H.%n(%p):%r", method); } - private BlockMap createBlockMap() { - BlockMap map = new BlockMap(method, config.useBranchPrediction()); + private BciBlockMapping createBlockMap() { + BciBlockMapping map = new BciBlockMapping(method, config.useBranchPrediction()); map.build(); // if (currentContext.isObserved()) { @@ -155,7 +154,7 @@ } // compute the block map, setup exception handlers and get the entrypoint(s) - BlockMap blockMap = createBlockMap(); + BciBlockMapping blockMap = createBlockMap(); this.canTrapBitSet = blockMap.canTrap; exceptionHandlers = blockMap.exceptionHandlers(); @@ -687,6 +686,32 @@ } } + private static final RiResolvedType[] EMPTY_TYPE_ARRAY = new RiResolvedType[0]; + + private RiResolvedType[] getTypeCheckHints(RiResolvedType type, int maxHints) { + if (!GraalOptions.UseInstanceOfHints || Util.isFinalClass(type)) { + return new RiResolvedType[] {type}; + } else { + RiResolvedType uniqueSubtype = type.uniqueConcreteSubtype(); + if (uniqueSubtype != null) { + return new RiResolvedType[] {uniqueSubtype}; + } else { + RiTypeProfile typeProfile = method.typeProfile(bci()); + if (typeProfile != null && typeProfile.types != null && typeProfile.types.length > 0 && typeProfile.morphism <= maxHints) { + RiResolvedType[] hints = new RiResolvedType[typeProfile.types.length]; + int hintCount = 0; + for (RiResolvedType hint : typeProfile.types) { + if (hint.isSubtypeOf(type)) { + hints[hintCount++] = hint; + } + } + return Arrays.copyOf(hints, Math.min(maxHints, hintCount)); + } + return EMPTY_TYPE_ARRAY; + } + } + } + private void genCheckCast() { int cpi = stream().readCPI(); RiType type = lookupType(cpi, CHECKCAST); @@ -696,7 +721,13 @@ ValueNode object = frameState.apop(); AnchorNode anchor = currentGraph.add(new AnchorNode()); append(anchor); - CheckCastNode checkCast = currentGraph.unique(new CheckCastNode(anchor, typeInstruction, (RiResolvedType) type, object)); + CheckCastNode checkCast; + if (type instanceof RiResolvedType) { + RiResolvedType[] hints = getTypeCheckHints((RiResolvedType) type, 2); + checkCast = currentGraph.unique(new CheckCastNode(anchor, typeInstruction, (RiResolvedType) type, object, hints, Util.isFinalClass((RiResolvedType) type))); + } else { + checkCast = currentGraph.unique(new CheckCastNode(anchor, typeInstruction, (RiResolvedType) type, object)); + } append(currentGraph.add(new ValueAnchorNode(checkCast))); frameState.apush(checkCast); } else { @@ -711,8 +742,12 @@ RiType type = lookupType(cpi, INSTANCEOF); ValueNode object = frameState.apop(); if (type instanceof RiResolvedType) { - ConstantNode hub = appendConstant(((RiResolvedType) type).getEncoding(RiType.Representation.ObjectHub)); - frameState.ipush(append(MaterializeNode.create(currentGraph.unique(new InstanceOfNode(hub, (RiResolvedType) type, object, false)), currentGraph))); + RiResolvedType resolvedType = (RiResolvedType) type; + ConstantNode hub = appendConstant(resolvedType.getEncoding(RiType.Representation.ObjectHub)); + + RiResolvedType[] hints = getTypeCheckHints(resolvedType, 1); + InstanceOfNode instanceOfNode = new InstanceOfNode(hub, (RiResolvedType) type, object, hints, Util.isFinalClass(resolvedType), false); + frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph))); } else { PlaceholderNode trueSucc = currentGraph.add(new PlaceholderNode()); DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptAction.InvalidateRecompile)); @@ -1419,6 +1454,23 @@ } } + private static boolean isBlockEnd(Node n) { + return trueSuccessorCount(n) > 1 || n instanceof ReturnNode || n instanceof UnwindNode || n instanceof DeoptimizeNode; + } + + private static int trueSuccessorCount(Node n) { + if (n == null) { + return 0; + } + int i = 0; + for (Node s : n.successors()) { + if (Util.isFixed(s)) { + i++; + } + } + return i; + } + private void iterateBytecodesForBlock(Block block) { assert frameState != null; @@ -1435,7 +1487,7 @@ traceInstruction(bci, opcode, bci == block.startBci); processBytecode(bci, opcode); - if (lastInstr == null || IdentifyBlocksPhase.isBlockEnd(lastInstr) || lastInstr.next() != null) { + if (lastInstr == null || isBlockEnd(lastInstr) || lastInstr.next() != null) { break; } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/ConstantNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/ConstantNode.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/ConstantNode.java Sun Feb 05 05:40:36 2012 +0100 @@ -33,11 +33,11 @@ * long, float, object reference, address, etc. */ @NodeInfo(shortName = "Const") -public final class ConstantNode extends BooleanNode implements LIRLowerable { +public class ConstantNode extends BooleanNode implements LIRLowerable { @Data public final CiConstant value; - private ConstantNode(CiConstant value) { + protected ConstantNode(CiConstant value) { this(value, null); } @@ -45,7 +45,7 @@ * Constructs a new ConstantNode representing the specified constant. * @param value the constant */ - private ConstantNode(CiConstant value, RiRuntime runtime) { + protected ConstantNode(CiConstant value, RiRuntime runtime) { super(StampFactory.forConstant(value, runtime)); this.value = value; } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/EndNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/EndNode.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/EndNode.java Sun Feb 05 05:40:36 2012 +0100 @@ -40,12 +40,7 @@ } public MergeNode merge() { - if (usages().size() == 0) { - return null; - } else { - assert usages().size() == 1; - return (MergeNode) usages().iterator().next(); - } + return (MergeNode) usages().first(); } @Override diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FrameState.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FrameState.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/FrameState.java Sun Feb 05 05:40:36 2012 +0100 @@ -27,6 +27,7 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.graph.iterators.*; import com.oracle.max.graal.nodes.PhiNode.PhiType; import com.oracle.max.graal.nodes.spi.*; import com.oracle.max.graal.nodes.virtual.*; @@ -74,27 +75,6 @@ @Input private final NodeInputList virtualObjectMappings; - public FrameState outerFrameState() { - return outerFrameState; - } - - public void setOuterFrameState(FrameState x) { - updateUsages(this.outerFrameState, x); - this.outerFrameState = x; - } - - public FrameState outermostFrameState() { - FrameState fs = this; - while (fs.outerFrameState() != null) { - fs = fs.outerFrameState(); - } - return fs; - } - - public void setValueAt(int i, ValueNode x) { - values.set(i, x); - } - /** * The bytecode index to which this frame state applies. This will be {@code -1} * iff this state is mutable. @@ -142,6 +122,27 @@ assert !rethrowException || stackSize == 1 : "must have exception on top of the stack"; } + public FrameState outerFrameState() { + return outerFrameState; + } + + public void setOuterFrameState(FrameState x) { + updateUsages(this.outerFrameState, x); + this.outerFrameState = x; + } + + public FrameState outermostFrameState() { + FrameState fs = this; + while (fs.outerFrameState() != null) { + fs = fs.outerFrameState(); + } + return fs; + } + + public void setValueAt(int i, ValueNode x) { + values.set(i, x); + } + public boolean rethrowException() { return rethrowException; } @@ -455,9 +456,8 @@ public void deleteRedundantPhi(PhiNode redundantPhi, ValueNode phiValue) { Collection phiUsages = redundantPhi.usages().filter(PhiNode.class).snapshot(); ((StructuredGraph) graph()).replaceFloating(redundantPhi, phiValue); - for (Node n : phiUsages) { - PhiNode phiNode = (PhiNode) n; - checkRedundantPhi(phiNode); + for (PhiNode phi : phiUsages) { + checkRedundantPhi(phi); } } @@ -488,48 +488,11 @@ } public StateSplit stateSplit() { - for (Node n : usages()) { - if (n instanceof StateSplit) { - return (StateSplit) n; - } - } - return null; + return (StateSplit) usages().filterInterface(StateSplit.class).first(); } - public Iterable innerFrameStates() { - final Iterator iterator = usages().iterator(); - return new Iterable() { - @Override - public Iterator iterator() { - return new Iterator() { - private Node next; - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - @Override - public FrameState next() { - forward(); - if (!hasNext()) { - throw new NoSuchElementException(); - } - FrameState res = (FrameState) next; - next = null; - return res; - } - @Override - public boolean hasNext() { - forward(); - return next != null; - } - private void forward() { - while (!(next instanceof FrameState) && iterator.hasNext()) { - next = iterator.next(); - } - } - }; - } - }; + public NodeIterable innerFrameStates() { + return usages().filter(FrameState.class); } /** diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/LoopBeginNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/LoopBeginNode.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/LoopBeginNode.java Sun Feb 05 05:40:36 2012 +0100 @@ -45,12 +45,7 @@ } public LoopEndNode loopEnd() { - for (LoopEndNode end : usages().filter(LoopEndNode.class)) { - if (end.loopBegin() == this) { - return end; - } - } - return null; + return usages().filter(LoopEndNode.class).first(); } @Override @@ -83,11 +78,6 @@ throw ValueUtil.shouldNotReachHere(); } - @Override - public Iterable phiPredecessors() { - return Arrays.asList(new Node[]{this.forwardEdge(), this.loopEnd()}); - } - public EndNode forwardEdge() { return this.endAt(0); } @@ -96,7 +86,7 @@ public boolean verify() { assertTrue(loopEnd() != null, "missing loopEnd"); assertTrue(forwardEdge() != null, "missing forwardEdge"); - assertTrue(usages().filter(LoopEndNode.class).snapshot().size() == 1, "multiple loop ends"); + assertTrue(usages().filter(LoopEndNode.class).count() == 1, "multiple loop ends"); return super.verify(); } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/MergeNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/MergeNode.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/MergeNode.java Sun Feb 05 05:40:36 2012 +0100 @@ -59,12 +59,8 @@ return ends.get(index); } - public Iterable phiPredecessors() { - return ends; - } - @Override - public Iterable cfgPredecessors() { + public NodeIterable cfgPredecessors() { return ends; } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/StructuredGraph.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/StructuredGraph.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/StructuredGraph.java Sun Feb 05 05:40:36 2012 +0100 @@ -173,6 +173,7 @@ public void replaceFixedWithFixed(FixedWithNextNode node, FixedWithNextNode replacement) { assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement; + replacement.setProbability(node.probability()); FixedNode next = node.next(); node.setNext(null); replacement.setNext(next); @@ -268,6 +269,7 @@ public void addAfterFixed(FixedWithNextNode node, FixedWithNextNode newNode) { assert node != null && newNode != null && node.isAlive() && newNode.isAlive() : "cannot add " + newNode + " after " + node; assert newNode.next() == null; + newNode.setProbability(node.probability()); FixedNode next = node.next(); node.setNext(newNode); newNode.setNext(next); @@ -277,6 +279,7 @@ assert node != null && newNode != null && node.isAlive() && newNode.isAlive() : "cannot add " + newNode + " before " + node; assert node.predecessor() != null && node.predecessor() instanceof FixedWithNextNode : "cannot add " + newNode + " before " + node; assert newNode.next() == null; + newNode.setProbability(node.probability()); FixedWithNextNode pred = (FixedWithNextNode) node.predecessor(); pred.setNext(newNode); newNode.setNext(node); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/CheckCastNode.java Sun Feb 05 05:40:36 2012 +0100 @@ -24,6 +24,7 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.extended.*; import com.oracle.max.graal.nodes.spi.*; @@ -31,11 +32,17 @@ /** * The {@code CheckCastNode} represents a {@link Bytecodes#CHECKCAST}. + * + * The {@link #targetClass()} of a CheckCastNode can be null for array store checks! */ -public final class CheckCastNode extends TypeCheckNode implements Canonicalizable, LIRLowerable { +public final class CheckCastNode extends TypeCheckNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType { @Input protected final AnchorNode anchor; + public AnchorNode anchor() { + return anchor; + } + /** * Creates a new CheckCast instruction. * @@ -44,7 +51,11 @@ * @param object the instruction producing the object */ public CheckCastNode(AnchorNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object) { - super(targetClassInstruction, targetClass, object, targetClass == null ? StampFactory.forKind(CiKind.Object) : StampFactory.declared(targetClass)); + this(anchor, targetClassInstruction, targetClass, object, EMPTY_HINTS, false); + } + + public CheckCastNode(AnchorNode anchor, ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiResolvedType[] hints, boolean hintsExact) { + super(targetClassInstruction, targetClass, object, hints, hintsExact, targetClass == null ? StampFactory.forKind(CiKind.Object) : StampFactory.declared(targetClass)); this.anchor = anchor; } @@ -69,6 +80,13 @@ return object(); } } + + if (tool.assumptions() != null && hints() != null && targetClass() != null) { + if (!hintsExact() && hints().length == 1 && hints()[0] == targetClass().uniqueConcreteSubtype()) { + tool.assumptions().recordConcreteSubtype(targetClass(), hints()[0]); + return graph().unique(new CheckCastNode(anchor, targetClassInstruction(), targetClass(), object(), hints(), true)); + } + } return this; } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/InstanceOfNode.java Sun Feb 05 05:40:36 2012 +0100 @@ -48,7 +48,11 @@ * @param object the instruction producing the object input to this instruction */ public InstanceOfNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, boolean negated) { - super(targetClassInstruction, targetClass, object, StampFactory.illegal()); + this(targetClassInstruction, targetClass, object, EMPTY_HINTS, false, negated); + } + + public InstanceOfNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiResolvedType[] hints, boolean hintsExact, boolean negated) { + super(targetClassInstruction, targetClass, object, hints, hintsExact, StampFactory.illegal()); this.negated = negated; assert targetClass != null; } @@ -59,8 +63,9 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - if (object().exactType() != null) { - boolean result = object().exactType().isSubtypeOf(targetClass()); + RiResolvedType exact = object().exactType(); + if (exact != null) { + boolean result = exact.isSubtypeOf(targetClass()); if (result != negated) { // The instanceof check reduces to a null check. return graph().unique(new NullCheckNode(object(), false)); @@ -78,11 +83,17 @@ assert false : "non-null constants are always expected to provide an exactType"; } } + if (tool.assumptions() != null && hints() != null && targetClass() != null) { + if (!hintsExact() && hints().length == 1 && hints()[0] == targetClass().uniqueConcreteSubtype()) { + tool.assumptions().recordConcreteSubtype(targetClass(), hints()[0]); + return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), hints(), true, negated)); + } + } return this; } @Override public BooleanNode negate() { - return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), !negated)); + return graph().unique(new InstanceOfNode(targetClassInstruction(), targetClass(), object(), hints(), hintsExact(), !negated)); } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/MethodCallTargetNode.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/MethodCallTargetNode.java Sun Feb 05 05:40:36 2012 +0100 @@ -106,10 +106,7 @@ } public Invoke invoke() { - if (this.usages().size() == 0) { - return null; - } - return (Invoke) this.usages().iterator().next(); + return (Invoke) this.usages().first(); } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/TypeCheckNode.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/TypeCheckNode.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/java/TypeCheckNode.java Sun Feb 05 05:40:36 2012 +0100 @@ -31,9 +31,12 @@ */ public abstract class TypeCheckNode extends BooleanNode { + protected static final RiResolvedType[] EMPTY_HINTS = new RiResolvedType[0]; @Input private ValueNode object; @Input private ValueNode targetClassInstruction; @Data private final RiResolvedType targetClass; + @Data private final RiResolvedType[] hints; + @Data private final boolean hintsExact; /** * Creates a new TypeCheckNode. @@ -42,11 +45,13 @@ * @param object the node which produces the object * @param kind the result type of this node */ - public TypeCheckNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, Stamp stamp) { + public TypeCheckNode(ValueNode targetClassInstruction, RiResolvedType targetClass, ValueNode object, RiResolvedType[] hints, boolean hintsExact, Stamp stamp) { super(stamp); this.targetClassInstruction = targetClassInstruction; this.targetClass = targetClass; this.object = object; + this.hints = hints; + this.hintsExact = hintsExact; } public ValueNode object() { @@ -64,4 +69,12 @@ public RiResolvedType targetClass() { return targetClass; } + + public RiResolvedType[] hints() { + return hints; + } + + public boolean hintsExact() { + return hintsExact; + } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/EscapeOp.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/EscapeOp.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/nodes/spi/EscapeOp.java Sun Feb 05 05:40:36 2012 +0100 @@ -44,7 +44,7 @@ assert ((IsTypeNode) usage).object() == node; return false; } else if (usage instanceof FrameState) { - assert ((FrameState) usage).inputs().contains(node); + assert usage.inputs().contains(node); return true; } else if (usage instanceof AccessMonitorNode) { assert ((AccessMonitorNode) usage).object() == node; diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/util/NodeIterators.java --- a/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/util/NodeIterators.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.nodes/src/com/oracle/max/graal/util/NodeIterators.java Sun Feb 05 05:40:36 2012 +0100 @@ -33,7 +33,7 @@ return new NodeIterable() { @Override public Iterator iterator() { - return new NodeIterator(until){ + return new NodeIterator(){ FixedNode p = n; @Override protected void forward() { diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java --- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java Sun Feb 05 05:40:36 2012 +0100 @@ -33,6 +33,7 @@ import com.oracle.max.graal.alloc.util.*; import com.oracle.max.graal.compiler.alloc.*; import com.oracle.max.graal.compiler.alloc.Interval.UsePosList; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.schedule.*; @@ -73,10 +74,10 @@ * @param label A label describing the compilation phase that produced the control flow graph. * @param blockMap A data structure describing the blocks in a method and how they are connected. */ - public void printCFG(String label, BlockMap blockMap) { + public void printCFG(String label, BciBlockMapping blockMap) { begin("cfg"); out.print("name \"").print(label).println('"'); - for (BlockMap.Block block : blockMap.blocks) { + for (BciBlockMapping.Block block : blockMap.blocks) { begin("block"); printBlock(block); end("block"); @@ -84,7 +85,7 @@ end("cfg"); } - private void printBlock(BlockMap.Block block) { + private void printBlock(BciBlockMapping.Block block) { out.print("name \"B").print(block.startBci).println('"'); out.print("from_bci ").println(block.startBci); out.print("to_bci ").println(block.endBci); @@ -92,7 +93,7 @@ out.println("predecessors "); out.print("successors "); - for (BlockMap.Block succ : block.successors) { + for (BciBlockMapping.Block succ : block.successors) { if (!succ.isExceptionEntry) { out.print("\"B").print(succ.startBci).print("\" "); } @@ -100,7 +101,7 @@ out.println(); out.print("xhandlers"); - for (BlockMap.Block succ : block.successors) { + for (BciBlockMapping.Block succ : block.successors) { if (succ.isExceptionEntry) { out.print("\"B").print(succ.startBci).print("\" "); } @@ -126,16 +127,16 @@ * @param label A label describing the compilation phase that produced the control flow graph. * @param blocks The list of blocks to be printed. */ - public void printCFG(String label, List blocks) { + public void printCFG(String label, List blocks, SchedulePhase schedule) { begin("cfg"); out.print("name \"").print(label).println('"'); for (Block block : blocks) { - printBlock(block); + printBlock(block, schedule); } end("cfg"); } - private void printBlock(Block block) { + private void printBlock(Block block, SchedulePhase schedule) { begin("block"); out.print("name \"").print(blockToString(block)).println('"'); @@ -150,7 +151,7 @@ out.print("successors "); for (Block succ : block.getSuccessors()) { - if (!succ.isExceptionBlock()) { + if (!succ.isExceptionEntry()) { out.print("\"").print(blockToString(succ)).print("\" "); } } @@ -158,7 +159,7 @@ out.print("xhandlers"); for (Block succ : block.getSuccessors()) { - if (succ.isExceptionBlock()) { + if (succ.isExceptionEntry()) { out.print("\"").print(blockToString(succ)).print("\" "); } } @@ -171,42 +172,43 @@ if (block.isLoopEnd()) { out.print("\"lle\" "); } - if (block.isExceptionBlock()) { + if (block.isExceptionEntry()) { out.print("\"ex\" "); } out.println(); - out.print("loop_index ").println(block.loopIndex()); - out.print("loop_depth ").println(block.loopDepth()); - - printNodes(block); - - if (block instanceof LIRBlock) { - printLIR((LIRBlock) block); + if (block.getLoop() != null) { + out.print("loop_index ").println(block.getLoop().index); + out.print("loop_depth ").println(block.getLoop().depth); } + printNodes(block, schedule); + printLIR(block); end("block"); } - private void printNodes(Block block) { + private void printNodes(Block block, SchedulePhase schedule) { + if (schedule == null) { + return; + } begin("IR"); out.println("HIR"); out.disableIndentation(); if (block.getPredecessors().size() == 0) { // Currently method parameters are not in the schedule, so print them separately here. - for (ValueNode param : block.firstNode().graph().getNodes(LocalNode.class)) { + for (ValueNode param : block.getBeginNode().graph().getNodes(LocalNode.class)) { printNode(param); } } - if (block.firstNode() instanceof MergeNode) { + if (block.getBeginNode() instanceof MergeNode) { // Currently phi functions are not in the schedule, so print them separately here. - for (ValueNode phi : ((MergeNode) block.firstNode()).phis()) { + for (ValueNode phi : ((MergeNode) block.getBeginNode()).phis()) { printNode(phi); } } - for (Node node : block.getInstructions()) { + for (Node node : schedule.nodesFor(block)) { printNode(node); } out.enableIndentation(); @@ -336,8 +338,8 @@ * * @param block the block to print */ - private void printLIR(LIRBlock block) { - List lirInstructions = block.lir(); + private void printLIR(Block block) { + List lirInstructions = block.lir; if (lirInstructions == null) { return; } @@ -349,11 +351,11 @@ CiValue[] results = block.phis.results(); for (int i = 0; i < results.length; i++) { if (i == 0) { - out.printf("nr %4d ", block.firstLirInstructionId()).print(COLUMN_END); + out.printf("nr %4d ", block.getFirstLirInstructionId()).print(COLUMN_END); } out.print("instruction PHI ").print(results[i].toString()).print(" = ("); String sep = ""; - for (LIRBlock pred : block.getLIRPredecessors()) { + for (Block pred : block.getPredecessors()) { out.print(sep).print(block.phis.inputs(pred)[i].toString()); sep = ", "; } @@ -410,10 +412,10 @@ if (lir == null) { // During all the front-end phases, the block schedule is built only for the debug output. // Therefore, the block numbers would be different for every CFG printed -> use the id of the first instruction. - return "B" + block.firstNode().toString(Verbosity.Id); + return "B" + block.getBeginNode().toString(Verbosity.Id); } else { // LIR instructions contain references to blocks and these blocks are printed as the blockID -> use the blockID. - return "B" + block.blockID(); + return "B" + block.getId(); } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java --- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java Sun Feb 05 05:40:36 2012 +0100 @@ -85,9 +85,9 @@ cfgPrinter.lirGenerator = event.debugObject(LIRGenerator.class); } - BlockMap blockMap = event.debugObject(BlockMap.class); + BciBlockMapping blockMap = event.debugObject(BciBlockMapping.class); Graph graph = event.debugObject(Graph.class); - IdentifyBlocksPhase schedule = event.debugObject(IdentifyBlocksPhase.class); + SchedulePhase schedule = event.debugObject(SchedulePhase.class); LinearScan allocator = event.debugObject(LinearScan.class); Interval[] intervals = event.debugObject(Interval[].class); IntervalPrinter.Interval[] printIntervals = event.debugObject(IntervalPrinter.Interval[].class); @@ -98,27 +98,20 @@ cfgPrinter.printBytecodes(runtime.disassemble(blockMap.method)); } if (cfgPrinter.lir != null) { - cfgPrinter.printCFG(event.label, cfgPrinter.lir.codeEmittingOrder()); + cfgPrinter.printCFG(event.label, cfgPrinter.lir.codeEmittingOrder(), schedule); if (targetMethod != null) { cfgPrinter.printMachineCode(runtime.disassemble(targetMethod), null); } } else if (graph != null) { - List blocks = null; if (schedule == null) { try { - schedule = new IdentifyBlocksPhase(true, LIRBlock.FACTORY); + schedule = new SchedulePhase(); schedule.apply((StructuredGraph) graph); - blocks = schedule.getBlocks(); - - ComputeLinearScanOrder clso = new ComputeLinearScanOrder(schedule.getBlocks().size(), schedule.loopCount(), (LIRBlock) schedule.getStartBlock()); - blocks = clso.codeEmittingOrder(); } catch (Throwable t) { // nothing to do here... } } - if (blocks != null) { - cfgPrinter.printCFG(event.label, blocks); - } + cfgPrinter.printCFG(event.label, Arrays.asList(schedule.getCFG().getBlocks()), schedule); } if (allocator != null && intervals != null) { cfgPrinter.printIntervals(event.label, intervals); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinter.java --- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinter.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/IdealGraphPrinter.java Sun Feb 05 05:40:36 2012 +0100 @@ -27,6 +27,7 @@ import java.util.Map.Entry; import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.graph.Node.Verbosity; @@ -84,13 +85,13 @@ /** * Prints an entire {@link Graph} with the specified title, optionally using short names for nodes. */ - public void print(Graph graph, String title, IdentifyBlocksPhase predefinedSchedule) { + public void print(Graph graph, String title, SchedulePhase predefinedSchedule) { beginGraph(title); Set noBlockNodes = new HashSet<>(); - IdentifyBlocksPhase schedule = predefinedSchedule; + SchedulePhase schedule = predefinedSchedule; if (schedule == null) { try { - schedule = new IdentifyBlocksPhase(true); + schedule = new SchedulePhase(); schedule.apply((StructuredGraph) graph); } catch (Throwable t) { // nothing to do here... @@ -98,7 +99,7 @@ } beginNodes(); - List edges = printNodes(graph, schedule == null ? null : schedule.getNodeToBlock(), noBlockNodes); + List edges = printNodes(graph, schedule == null ? null : schedule.getCFG().getNodeToBlock(), noBlockNodes); endNodes(); beginEdges(); @@ -109,8 +110,8 @@ if (schedule != null) { beginControlFlow(); - for (Block block : schedule.getBlocks()) { - printBlock(graph, block, schedule.getNodeToBlock()); + for (Block block : schedule.getCFG().getBlocks()) { + printBlock(graph, block, schedule.getCFG().getNodeToBlock()); } printNoBlock(noBlockNodes); endControlFlow(); @@ -141,10 +142,10 @@ printProperty("class", node.getClass().getSimpleName()); Block block = nodeToBlock == null ? null : nodeToBlock.get(node); if (block != null) { - printProperty("block", Integer.toString(block.blockID())); - if (!(node instanceof PhiNode || node instanceof FrameState || node instanceof LocalNode) && !block.getInstructions().contains(node)) { - printProperty("notInOwnBlock", "true"); - } + printProperty("block", Integer.toString(block.getId())); +// if (!(node instanceof PhiNode || node instanceof FrameState || node instanceof LocalNode) && !block.nodes().contains(node)) { +// printProperty("notInOwnBlock", "true"); +// } } else { printProperty("block", "noBlock"); noBlockNodes.add(node); @@ -201,7 +202,7 @@ Position position = inputIter.nextPosition(); Node input = node.getNodeClass().get(node, position); if (input != null) { - edges.add(new Edge(input.toString(Verbosity.Id), input.successors().explicitCount(), node.toString(Verbosity.Id), toIndex, node.getNodeClass().getName(position))); + edges.add(new Edge(input.toString(Verbosity.Id), input.successors().count(), node.toString(Verbosity.Id), toIndex, node.getNodeClass().getName(position))); } toIndex++; } @@ -211,17 +212,17 @@ } private void printBlock(Graph graph, Block block, NodeMap nodeToBlock) { - beginBlock(Integer.toString(block.blockID())); + beginBlock(Integer.toString(block.getId())); beginSuccessors(); for (Block sux : block.getSuccessors()) { if (sux != null) { - printSuccessor(Integer.toString(sux.blockID())); + printSuccessor(Integer.toString(sux.getId())); } } endSuccessors(); beginBlockNodes(); - Set nodes = new HashSet<>(block.getInstructions()); + Set nodes = new HashSet<>(); if (nodeToBlock != null) { for (Node n : graph.getNodes()) { @@ -234,7 +235,7 @@ if (nodes.size() > 0) { // if this is the first block: add all locals to this block - if (block.getInstructions().size() > 0 && block.getInstructions().get(0) == ((StructuredGraph) graph).start()) { + if (block.getBeginNode() == ((StructuredGraph) graph).start()) { for (Node node : graph.getNodes()) { if (node instanceof LocalNode) { nodes.add(node); @@ -242,8 +243,9 @@ } } + Set snapshot = new HashSet<>(nodes); // add all framestates and phis to their blocks - for (Node node : block.getInstructions()) { + for (Node node : snapshot) { if (node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) { nodes.add(((StateSplit) node).stateAfter()); } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/ArrayCopySnippets.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,258 +0,0 @@ -/* - * 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.oracle.max.graal.snippets; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.nodes.extended.*; -import com.oracle.max.graal.snippets.nodes.*; - - -public class ArrayCopySnippets implements SnippetsInterface{ - - @Snippet - public static void arraycopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) { - if (src == null || dest == null) { - throw new NullPointerException(); - } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { - throw new IndexOutOfBoundsException(); - } - if (src == dest && srcPos < destPos) { // bad aliased case - if ((length & 0x01) == 0) { - if ((length & 0x02) == 0) { - if ((length & 0x04) == 0) { - copyLongsDown(src, srcPos, dest, destPos, length >> 3); - } else { - copyIntsDown(src, srcPos, dest, destPos, length >> 2); - } - } else { - copyShortsDown(src, srcPos, dest, destPos, length >> 1); - } - } else { - copyBytesDown(src, srcPos, dest, destPos, length); - } - } else { - if ((length & 0x01) == 0) { - if ((length & 0x02) == 0) { - if ((length & 0x04) == 0) { - copyLongsUp(src, srcPos, dest, destPos, length >> 3); - } else { - copyIntsUp(src, srcPos, dest, destPos, length >> 2); - } - } else { - copyShortsUp(src, srcPos, dest, destPos, length >> 1); - } - } else { - copyBytesUp(src, srcPos, dest, destPos, length); - } - } - } - - @Snippet - public static void arraycopy(char[] src, int srcPos, char[] dest, int destPos, int length) { - if (src == null || dest == null) { - throw new NullPointerException(); - } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { - throw new IndexOutOfBoundsException(); - } - if (src == dest && srcPos < destPos) { // bad aliased case - if ((length & 0x01) == 0) { - if ((length & 0x02) == 0) { - copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2); - } else { - copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1); - } - } else { - copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length); - } - } else { - if ((length & 0x01) == 0) { - if ((length & 0x02) == 0) { - copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2); - } else { - copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1); - } - } else { - copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length); - } - } - } - - @Snippet - public static void arraycopy(short[] src, int srcPos, short[] dest, int destPos, int length) { - if (src == null || dest == null) { - throw new NullPointerException(); - } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { - throw new IndexOutOfBoundsException(); - } - if (src == dest && srcPos < destPos) { // bad aliased case - if ((length & 0x01) == 0) { - if ((length & 0x02) == 0) { - copyLongsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 2); - } else { - copyIntsDown(src, srcPos * 2L, dest, destPos * 2L, length >> 1); - } - } else { - copyShortsDown(src, srcPos * 2L, dest, destPos * 2L, length); - } - } else { - if ((length & 0x01) == 0) { - if ((length & 0x02) == 0) { - copyLongsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 2); - } else { - copyIntsUp(src, srcPos * 2L, dest, destPos * 2L, length >> 1); - } - } else { - copyShortsUp(src, srcPos * 2L, dest, destPos * 2L, length); - } - } - } - - @Snippet - public static void arraycopy(int[] src, int srcPos, int[] dest, int destPos, int length) { - if (src == null || dest == null) { - throw new NullPointerException(); - } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { - throw new IndexOutOfBoundsException(); - } - if (src == dest && srcPos < destPos) { // bad aliased case - if ((length & 0x01) == 0) { - copyLongsDown(src, srcPos * 4L, dest, destPos * 4L, length >> 1); - } else { - copyIntsDown(src, srcPos * 4L, dest, destPos * 4L, length); - } - } else { - if ((length & 0x01) == 0) { - copyLongsUp(src, srcPos * 4L, dest, destPos * 4L, length >> 1); - } else { - copyIntsUp(src, srcPos * 4L, dest, destPos * 4L, length); - } - } - } - - @Snippet - public static void arraycopy(long[] src, int srcPos, long[] dest, int destPos, int length) { - if (src == null || dest == null) { - throw new NullPointerException(); - } - if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > src.length || destPos + length > dest.length) { - throw new IndexOutOfBoundsException(); - } - if (src == dest && srcPos < destPos) { // bad aliased case - copyLongsDown(src, srcPos * 8L, dest, destPos * 8L, length); - } else { - copyLongsUp(src, srcPos * 8L, dest, destPos * 8L, length); - } - } - - @Snippet - public static void copyBytesDown(Object src, int srcPos, Object dest, int destPos, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte); - for (long i = length - 1; i >= 0; i--) { - Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte); - UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte); - } - } - - @Snippet - public static void copyShortsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); - for (long i = (length - 1) * 2; i >= 0; i -= 2) { - Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short); - UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short); - } - } - - @Snippet - public static void copyIntsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); - for (long i = (length - 1) * 4; i >= 0; i -= 4) { - Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int); - UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int); - } - } - - @Snippet - public static void copyLongsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); - for (long i = (length - 1) * 8; i >= 0; i -= 8) { - Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long); - UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long); - } - } - - /** - * Copies {@code length} bytes from {@code src} starting at {@code srcPos} to {@code dest} starting at {@code destPos}. - * @param src source object - * @param srcPos source offset - * @param dest destination object - * @param destPos destination offset - * @param length number of bytes to copy - */ - @Snippet - public static void copyBytesUp(Object src, int srcPos, Object dest, int destPos, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Byte); - for (long i = 0; i < length; i++) { - Byte a = UnsafeLoadNode.load(src, i + (srcPos + header), CiKind.Byte); - UnsafeStoreNode.store(dest, i + (destPos + header), a.byteValue(), CiKind.Byte); - } - } - - /** - * Copies {@code length} shorts from {@code src} starting at offset {@code srcOffset} (in bytes) to {@code dest} starting at offset {@code destOffset} (in bytes). - * @param src - * @param srcOffset (in bytes) - * @param dest - * @param destOffset (in bytes) - * @param length (in shorts) - */ - @Snippet - public static void copyShortsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Short); - for (long i = 0; i < length * 2L; i += 2) { - Character a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Short); - UnsafeStoreNode.store(dest, i + (destOffset + header), a.charValue(), CiKind.Short); - } - } - - @Snippet - public static void copyIntsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Int); - for (long i = 0; i < length * 4L; i += 4) { - Integer a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Int); - UnsafeStoreNode.store(dest, i + (destOffset + header), a.intValue(), CiKind.Int); - } - } - - @Snippet - public static void copyLongsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { - long header = ArrayHeaderSizeNode.sizeFor(CiKind.Long); - for (long i = 0; i < length * 8L; i += 8) { - Long a = UnsafeLoadNode.load(src, i + (srcOffset + header), CiKind.Long); - UnsafeStoreNode.store(dest, i + (destOffset + header), a.longValue(), CiKind.Long); - } - } -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/GraalIntrinsics.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/GraalIntrinsics.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/GraalIntrinsics.java Sun Feb 05 05:40:36 2012 +0100 @@ -25,7 +25,6 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.phases.*; -import com.oracle.max.graal.compiler.phases.PhasePlan.PhasePosition; import com.oracle.max.graal.cri.*; /** @@ -38,8 +37,6 @@ Snippets.install(runtime, target, new DoubleSnippets(), plan); Snippets.install(runtime, target, new FloatSnippets(), plan); Snippets.install(runtime, target, new NodeClassSnippets(), plan); - Snippets.install(runtime, target, new ArrayCopySnippets(), plan); - plan.addPhase(PhasePosition.HIGH_LEVEL, new IntrinsifyArrayCopyPhase(runtime)); } } } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/IntrinsifyArrayCopyPhase.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/* - * 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.oracle.max.graal.snippets; - -import java.lang.reflect.*; - -import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.compiler.phases.*; -import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.cri.*; -import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.nodes.*; -import com.oracle.max.graal.nodes.java.*; - -public class IntrinsifyArrayCopyPhase extends Phase { - private final GraalRuntime runtime; - private RiResolvedMethod arrayCopy; - private RiResolvedMethod byteArrayCopy; - private RiResolvedMethod shortArrayCopy; - private RiResolvedMethod charArrayCopy; - private RiResolvedMethod intArrayCopy; - private RiResolvedMethod longArrayCopy; - - public IntrinsifyArrayCopyPhase(GraalRuntime runtime) { - this.runtime = runtime; - try { - byteArrayCopy = getArrayCopySnippet(runtime, byte.class); - charArrayCopy = getArrayCopySnippet(runtime, char.class); - shortArrayCopy = getArrayCopySnippet(runtime, short.class); - intArrayCopy = getArrayCopySnippet(runtime, int.class); - longArrayCopy = getArrayCopySnippet(runtime, long.class); - arrayCopy = runtime.getRiMethod(System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class)); - } catch (SecurityException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - } - - private static RiResolvedMethod getArrayCopySnippet(RiRuntime runtime, Class componentClass) throws NoSuchMethodException { - Class arrayClass = Array.newInstance(componentClass, 0).getClass(); - return runtime.getRiMethod(ArrayCopySnippets.class.getDeclaredMethod("arraycopy", arrayClass, int.class, arrayClass, int.class, int.class)); - } - - @Override - protected void run(StructuredGraph graph) { - for (MethodCallTargetNode methodCallTarget : graph.getNodes(MethodCallTargetNode.class)) { - RiResolvedMethod targetMethod = methodCallTarget.targetMethod(); - RiResolvedMethod snippetMethod = null; - if (targetMethod == arrayCopy) { - ValueNode src = methodCallTarget.arguments().get(0); - ValueNode dest = methodCallTarget.arguments().get(2); - if (src == null || dest == null) { //TODO (gd) this should never be null : check - return; - } - RiResolvedType srcDeclaredType = src.declaredType(); - RiResolvedType destDeclaredType = dest.declaredType(); - if (srcDeclaredType != null - && srcDeclaredType.isArrayClass() - && destDeclaredType != null - && destDeclaredType.isArrayClass() - && srcDeclaredType.componentType() == destDeclaredType.componentType()) { - Class componentType = srcDeclaredType.componentType().toJava(); - if (componentType.equals(int.class)) { - snippetMethod = intArrayCopy; - } else if (componentType.equals(char.class)) { - snippetMethod = charArrayCopy; - } else if (componentType.equals(long.class)) { - snippetMethod = longArrayCopy; - } else if (componentType.equals(byte.class)) { - snippetMethod = byteArrayCopy; - } else if (componentType.equals(short.class)) { - snippetMethod = shortArrayCopy; - } - } - } - - if (snippetMethod != null) { - StructuredGraph snippetGraph = (StructuredGraph) snippetMethod.compilerStorage().get(Graph.class); - assert snippetGraph != null : "ArrayCopySnippets should be installed"; - //TTY.println(" > Intinsify"); - InliningUtil.inline(methodCallTarget.invoke(), snippetGraph, false); - } - } - new CanonicalizerPhase(null, runtime, null).apply(graph); - } -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/Snippets.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/Snippets.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/Snippets.java Sun Feb 05 05:40:36 2012 +0100 @@ -121,6 +121,7 @@ for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) { end.setSafepointPolling(false); } + new InsertStateAfterPlaceholderPhase().apply(graph); Debug.dump(graph, "%s: Final", snippetRiMethod.name()); @@ -128,5 +129,4 @@ return graph; } - } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/SystemSnippets.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/SystemSnippets.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * 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.oracle.max.graal.snippets; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.graal.nodes.extended.*; - -/** - * Snippets for {@link java.lang.System} methods. - */ -@ClassSubstitution(java.lang.System.class) -public class SystemSnippets implements SnippetsInterface { - - // TODO: public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) { } - - public static long currentTimeMillis() { - return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeMillis); - } - - public static long nanoTime() { - return RuntimeCallNode.performCall(CiRuntimeCall.JavaTimeNanos); - } - -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/UnsafeSnippets.java --- a/graal/com.oracle.max.graal.snippets/src/com/oracle/max/graal/snippets/UnsafeSnippets.java Sun Feb 05 05:37:52 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,251 +0,0 @@ -/* - * 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.oracle.max.graal.snippets; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.util.*; -import com.oracle.max.graal.nodes.extended.*; -import com.oracle.max.graal.nodes.java.*; - -/** - * Snippets for {@link sun.misc.Unsafe} methods. - */ -@ClassSubstitution(sun.misc.Unsafe.class) -public class UnsafeSnippets implements SnippetsInterface { - - public boolean compareAndSwapObject(Object o, long offset, Object expected, Object x) { - return CompareAndSwapNode.compareAndSwap(o, offset, expected, x); - } - - public boolean compareAndSwapInt(Object o, long offset, int expected, int x) { - return CompareAndSwapNode.compareAndSwap(o, offset, expected, x); - } - - public boolean compareAndSwapLong(Object o, long offset, long expected, long x) { - return CompareAndSwapNode.compareAndSwap(o, offset, expected, x); - } - - public Object getObject(Object o, long offset) { - return UnsafeLoadNode.load(o, offset, CiKind.Object); - } - - public Object getObjectVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - Object result = getObject(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putObject(Object o, long offset, Object x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Object); - } - - public void putObjectVolatile(Object o, long offset, Object x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putObject(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public int getInt(Object o, long offset) { - Integer value = UnsafeLoadNode.load(o, offset, CiKind.Int); - return value; - } - - public int getIntVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - int result = getInt(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putInt(Object o, long offset, int x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Int); - } - - public void putIntVolatile(Object o, long offset, int x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putInt(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public boolean getBoolean(Object o, long offset) { - @JavacBug(id = 6995200) - Boolean result = UnsafeLoadNode.load(o, offset, CiKind.Boolean); - return result; - } - - public boolean getBooleanVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - boolean result = getBoolean(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putBoolean(Object o, long offset, boolean x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Boolean); - } - - public void putBooleanVolatile(Object o, long offset, boolean x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putBoolean(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public byte getByte(Object o, long offset) { - @JavacBug(id = 6995200) - Byte result = UnsafeLoadNode.load(o, offset, CiKind.Byte); - return result; - } - - public byte getByteVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - byte result = getByte(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putByte(Object o, long offset, byte x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Byte); - } - - public void putByteVolatile(Object o, long offset, byte x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putByte(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public short getShort(Object o, long offset) { - @JavacBug(id = 6995200) - Short result = UnsafeLoadNode.load(o, offset, CiKind.Short); - return result; - } - - public short getShortVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - short result = getShort(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putShort(Object o, long offset, short x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Short); - } - - public void putShortVolatile(Object o, long offset, short x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putShort(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public char getChar(Object o, long offset) { - @JavacBug(id = 6995200) - Character result = UnsafeLoadNode.load(o, offset, CiKind.Char); - return result; - } - - public char getCharVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - char result = getChar(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putChar(Object o, long offset, char x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Char); - } - - public void putCharVolatile(Object o, long offset, char x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putChar(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public long getLong(Object o, long offset) { - @JavacBug(id = 6995200) - Long result = UnsafeLoadNode.load(o, offset, CiKind.Long); - return result; - } - - public long getLongVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - long result = getLong(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putLong(Object o, long offset, long x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Long); - } - - public void putLongVolatile(Object o, long offset, long x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putLong(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public float getFloat(Object o, long offset) { - @JavacBug(id = 6995200) - Float result = UnsafeLoadNode.load(o, offset, CiKind.Float); - return result; - } - - public float getFloatVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - float result = getFloat(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putFloat(Object o, long offset, float x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Float); - } - - public void putFloatVolatile(Object o, long offset, float x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putFloat(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } - - public double getDouble(Object o, long offset) { - @JavacBug(id = 6995200) - Double result = UnsafeLoadNode.load(o, offset, CiKind.Double); - return result; - } - - public double getDoubleVolatile(Object o, long offset) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_READ); - double result = getDouble(o, offset); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_READ); - return result; - } - - public void putDouble(Object o, long offset, double x) { - UnsafeStoreNode.store(o, offset, x, CiKind.Double); - } - - public void putDoubleVolatile(Object o, long offset, double x) { - MembarNode.get(MemoryBarriers.JMM_PRE_VOLATILE_WRITE); - putDouble(o, offset, x); - MembarNode.get(MemoryBarriers.JMM_POST_VOLATILE_WRITE); - } -} diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/BoxingEliminationTest.java --- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/BoxingEliminationTest.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/BoxingEliminationTest.java Sun Feb 05 05:40:36 2012 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.compiler.tests; +import static com.oracle.max.graal.graph.iterators.NodePredicates.*; + import java.util.*; import org.junit.*; @@ -97,12 +99,8 @@ identifyBoxingPhase.apply(graph); LocalNode local = graph.getNodes(LocalNode.class).iterator().next(); ConstantNode constant = ConstantNode.forInt(0, graph); - for (Node n : local.usages().snapshot()) { - if (n instanceof FrameState) { - // Do not replace. - } else { - n.replaceFirstInput(local, constant); - } + for (Node n : local.usages().filter(isNotA(FrameState.class)).snapshot()) { + n.replaceFirstInput(local, constant); } Collection hints = new ArrayList<>(); for (Invoke invoke : graph.getInvokes()) { diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/DegeneratedLoopsTest.java --- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/DegeneratedLoopsTest.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/DegeneratedLoopsTest.java Sun Feb 05 05:40:36 2012 +0100 @@ -22,9 +22,10 @@ */ package com.oracle.max.graal.compiler.tests; -import junit.framework.AssertionFailedError; +import static com.oracle.max.graal.graph.iterators.NodePredicates.*; +import junit.framework.*; -import org.junit.*; +import org.junit.Test; import com.oracle.max.graal.compiler.phases.*; import com.oracle.max.graal.debug.*; @@ -84,12 +85,8 @@ Debug.dump(graph, "Graph"); LocalNode local = graph.getNodes(LocalNode.class).iterator().next(); ConstantNode constant = ConstantNode.forInt(0, graph); - for (Node n : local.usages().snapshot()) { - if (n instanceof FrameState) { - // Do not replace. - } else { - n.replaceFirstInput(local, constant); - } + for (Node n : local.usages().filter(isNotA(FrameState.class)).snapshot()) { + n.replaceFirstInput(local, constant); } for (Invoke invoke : graph.getInvokes()) { invoke.intrinsify(null); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphScheduleTest.java --- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphScheduleTest.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphScheduleTest.java Sun Feb 05 05:40:36 2012 +0100 @@ -26,20 +26,21 @@ import org.junit.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; public class GraphScheduleTest extends GraphTest { protected void assertOrderedAfterSchedule(StructuredGraph graph, Node a, Node b) { - IdentifyBlocksPhase ibp = new IdentifyBlocksPhase(true); + SchedulePhase ibp = new SchedulePhase(); ibp.apply(graph); - NodeMap nodeToBlock = ibp.getNodeToBlock(); + NodeMap nodeToBlock = ibp.getCFG().getNodeToBlock(); Block bBlock = nodeToBlock.get(b); Block aBlock = nodeToBlock.get(a); if (bBlock == aBlock) { - List instructions = bBlock.getInstructions(); + List instructions = ibp.nodesFor(bBlock); Assert.assertTrue(instructions.indexOf(b) > instructions.indexOf(a)); } else { Block block = bBlock; @@ -47,7 +48,7 @@ if (block == aBlock) { break; } - block = block.dominator(); + block = block.getDominator(); } Assert.assertTrue(block == aBlock); } diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphTest.java --- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphTest.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/GraphTest.java Sun Feb 05 05:40:36 2012 +0100 @@ -48,7 +48,7 @@ *

* The tests can be run in Eclipse with the "Compiler Unit Test" Eclipse * launch configuration found in the top level of this project or by - * running {@code mx gcut} on the command line. + * running {@code mx unittest} on the command line. */ public abstract class GraphTest { diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/IfCanonicalizerTest.java --- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/IfCanonicalizerTest.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/IfCanonicalizerTest.java Sun Feb 05 05:40:36 2012 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.compiler.tests; +import static com.oracle.max.graal.graph.iterators.NodePredicates.*; + import org.junit.*; import com.oracle.max.graal.compiler.phases.*; @@ -137,12 +139,8 @@ StructuredGraph graph = parse(snippet); LocalNode local = graph.getNodes(LocalNode.class).iterator().next(); ConstantNode constant = ConstantNode.forInt(0, graph); - for (Node n : local.usages().snapshot()) { - if (n instanceof FrameState) { - // Do not replace. - } else { - n.replaceFirstInput(local, constant); - } + for (Node n : local.usages().filter(isNotA(FrameState.class)).snapshot()) { + n.replaceFirstInput(local, constant); } Debug.dump(graph, "Graph"); new CanonicalizerPhase(null, runtime(), null).apply(graph); diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/InvokeTest.java --- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/InvokeTest.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/InvokeTest.java Sun Feb 05 05:40:36 2012 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.compiler.tests; +import static com.oracle.max.graal.graph.iterators.NodePredicates.*; + import java.util.*; import org.junit.*; @@ -72,12 +74,8 @@ StructuredGraph graph = parse(snippet); LocalNode local = graph.getNodes(LocalNode.class).iterator().next(); ConstantNode constant = ConstantNode.forInt(0, graph); - for (Node n : local.usages().snapshot()) { - if (n instanceof FrameState) { - // Do not replace. - } else { - n.replaceFirstInput(local, constant); - } + for (Node n : local.usages().filter(isNotA(FrameState.class)).snapshot()) { + n.replaceFirstInput(local, constant); } Collection hints = new ArrayList<>(); for (Invoke invoke : graph.getInvokes()) { diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/MonitorTest.java --- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/MonitorTest.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/MonitorTest.java Sun Feb 05 05:40:36 2012 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.compiler.tests; +import static com.oracle.max.graal.graph.iterators.NodePredicates.*; + import java.util.*; import junit.framework.AssertionFailedError; @@ -30,6 +32,7 @@ import com.oracle.max.graal.compiler.phases.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.graph.iterators.*; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.java.*; @@ -64,10 +67,9 @@ @Test public void test2() { StructuredGraph graph = parseAndProcess("test2Snippet"); - Collection monitors = graph.getNodes(MonitorExitNode.class).snapshot(); - Assert.assertEquals(1, monitors.size()); - MonitorExitNode monitor = monitors.iterator().next(); - Assert.assertEquals(monitor.stateAfter().bci, 3); + NodeIterable monitors = graph.getNodes(MonitorExitNode.class); + Assert.assertEquals(1, monitors.count()); + Assert.assertEquals(monitors.first().stateAfter().bci, 3); } @SuppressWarnings("all") @@ -81,14 +83,10 @@ private StructuredGraph parseAndProcess(String snippet) { StructuredGraph graph = parse(snippet); - LocalNode local = graph.getNodes(LocalNode.class).iterator().next(); + LocalNode local = graph.getNodes(LocalNode.class).first(); ConstantNode constant = ConstantNode.forInt(0, graph); - for (Node n : local.usages().snapshot()) { - if (n instanceof FrameState) { - // Do not replace. - } else { - n.replaceFirstInput(local, constant); - } + for (Node n : local.usages().filter(isNotA(FrameState.class)).snapshot()) { + n.replaceFirstInput(local, constant); } Collection hints = new ArrayList<>(); for (Invoke invoke : graph.getInvokes()) { diff -r 5d9c4796912d -r ab7c258e1cef graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/NestedLoopTest.java --- a/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/NestedLoopTest.java Sun Feb 05 05:37:52 2012 +0100 +++ b/graal/com.oracle.max.graal.tests/src/com/oracle/max/graal/compiler/tests/NestedLoopTest.java Sun Feb 05 05:40:36 2012 +0100 @@ -24,8 +24,9 @@ import org.junit.*; -import com.oracle.max.graal.compiler.loop.*; +import com.oracle.max.graal.compiler.cfg.*; import com.oracle.max.graal.debug.*; +import com.oracle.max.graal.graph.*; import com.oracle.max.graal.nodes.*; public class NestedLoopTest extends GraphTest { @@ -144,24 +145,40 @@ private void test(String snippet, int rootExits, int nestedExits, int innerExits) { StructuredGraph graph = parse(snippet); Debug.dump(graph, "Graph"); - LoopInfo loopInfo = LoopUtil.computeLoopInfo(graph); - loopInfo.print(); - Loop rootLoop = loopInfo.rootLoops().get(0); - Loop nestedLoop = rootLoop.children().get(0); - Loop innerMostLoop = nestedLoop.children().get(0); + ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); + + Assert.assertTrue(cfg.getLoops().length == 3); + Loop rootLoop = cfg.getLoops()[0]; + Loop nestedLoop = cfg.getLoops()[1]; + Loop innerMostLoop = cfg.getLoops()[2]; Invoke a = getInvoke("a", graph); Invoke b = getInvoke("b", graph); Invoke c = getInvoke("c", graph); Invoke d = getInvoke("d", graph); - Assert.assertTrue(rootLoop.containsDirectFixed((FixedNode) a)); - Assert.assertTrue(nestedLoop.containsDirectFixed((FixedNode) b)); - Assert.assertTrue(innerMostLoop.containsDirectFixed((FixedNode) c)); - Assert.assertTrue(innerMostLoop.containsDirectFixed((FixedNode) d)); - Assert.assertTrue(rootLoop.containsFixed((FixedNode) d)); - Assert.assertTrue(nestedLoop.containsFixed((FixedNode) d)); - Assert.assertEquals(rootExits, rootLoop.exits().cardinality()); - Assert.assertEquals(nestedExits, nestedLoop.exits().cardinality()); - Assert.assertEquals(innerExits, innerMostLoop.exits().cardinality()); + Assert.assertTrue(containsDirect(rootLoop, a, cfg)); + Assert.assertTrue(containsDirect(nestedLoop, b, cfg)); + Assert.assertTrue(containsDirect(innerMostLoop, c, cfg)); + Assert.assertTrue(containsDirect(innerMostLoop, d, cfg)); + Assert.assertTrue(contains(rootLoop, d, cfg)); + Assert.assertTrue(contains(nestedLoop, d, cfg)); + Assert.assertEquals(rootExits, rootLoop.exits.size()); + Assert.assertEquals(nestedExits, nestedLoop.exits.size()); + Assert.assertEquals(innerExits, innerMostLoop.exits.size()); Debug.dump(graph, "Graph"); } + + private static boolean contains(Loop loop, Invoke node, ControlFlowGraph cfg) { + Block block = cfg.blockFor((Node) node); + Assert.assertNotNull(block); + return loop.blocks.contains(block); + } + + private static boolean containsDirect(Loop loop, Invoke node, ControlFlowGraph cfg) { + for (Loop child : loop.children) { + if (contains(child, node, cfg)) { + return false; + } + } + return contains(loop, node, cfg); + } } diff -r 5d9c4796912d -r ab7c258e1cef mx/commands.py --- a/mx/commands.py Sun Feb 05 05:37:52 2012 +0100 +++ b/mx/commands.py Sun Feb 05 05:40:36 2012 +0100 @@ -34,7 +34,16 @@ import json _graal_home = dirname(dirname(__file__)) + +""" Used to distinguish an exported GraalVM (see 'mx export'). """ _vmSourcesAvailable = exists(join(_graal_home, 'make')) and exists(join(_graal_home, 'src')) + +""" The VM that will be run by the 'vm' command: graal(default), client or server. + This can be set via the global '--vm' option. """ +_vm = 'graal' + +""" The VM build that will be run by the 'vm' command: product(default), fastdebug or debug. + This can be set via the global '--fastdebug' and '--debug' options. """ _vmbuild = 'product' _copyrightTemplate = """/* @@ -133,7 +142,7 @@ res = [] mx.log("=== Server VM ===") printArg = '-XX:+PrintCompilation' if verbose else '-XX:-PrintCompilation' - res.append(vm(['-cp', cp, printArg] + sharedArgs, vm="-server")) + res.append(vm(['-cp', cp, printArg] + sharedArgs, vm='server')) mx.log("=== Graal VM ===") printArg = '-G:+PrintCompilation' if verbose else '-G:-PrintCompilation' res.append(vm(['-cp', cp, printArg, '-G:-Extend', '-G:-Inline'] + sharedArgs)) @@ -204,7 +213,7 @@ failed = [] for (test, n) in numTests.items(): - if not sanitycheck.getDacapo(test, n, dacapoArgs).test('-graal', opts=vmOpts): + if not sanitycheck.getDacapo(test, n, dacapoArgs).test('graal', opts=vmOpts): failed.append(test) if len(failed) != 0: @@ -304,6 +313,7 @@ parser = ArgumentParser(prog='mx build'); + parser.add_argument('--vm', action='store', dest='vm', default='graal', choices=['graal', 'server', 'client'], help='the VM to be built') # Call mx.build to compile the Java sources opts = mx.build(['--source', '1.7'] + args, parser=parser) @@ -315,16 +325,25 @@ if len(builds) == 0: builds = ['product'] + vm = opts.vm + if vm == 'server': + buildSuffix = '' + elif vm == 'client': + buildSuffix = '1' + else: + assert vm is 'graal' + buildSuffix = 'graal' + for build in builds: jdk = _jdk(build, True) if build == 'debug': build = 'jvmg' - - graalVmDir = join(jdk, 'jre', 'lib', 'amd64', 'graal') - if not exists(graalVmDir): - mx.log('Creating Graal directory in JDK7: ' + graalVmDir) - os.makedirs(graalVmDir) + + vmDir = join(jdk, 'jre', 'lib', 'amd64', vm) + if not exists(vmDir): + mx.log('Creating VM directory in JDK7: ' + vmDir) + os.makedirs(vmDir) def filterXusage(line): if not 'Xusage.txt' in line: @@ -353,17 +372,20 @@ env.setdefault('HOTSPOT_BUILD_JOBS', '3') env['ALT_BOOTDIR'] = jdk env.setdefault('INSTALL', 'y') - mx.run([mx.gmake_cmd(), build + 'graal'], cwd=join(_graal_home, 'make'), err=filterXusage) + mx.run([mx.gmake_cmd(), build + buildSuffix], cwd=join(_graal_home, 'make'), err=filterXusage) -def vm(args, vm='-graal', nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, vmbuild=None): +def vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, vmbuild=None): """run the GraalVM""" + if vm is None: + vm = _vm + build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product' mx.expand_project_in_args(args) if mx.java().debug: args = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000'] + args exe = join(_jdk(build), 'bin', mx.exe_suffix('java')) - return mx.run([exe, vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout) + return mx.run([exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout) # Table of unit tests. @@ -429,43 +451,52 @@ def gate(args): """run the tests used to validate a push - If this commands exits with a 0 exit code, then the source code is in + If this command exits with a 0 exit code, then the source code is in a state that would be accepted for integration into the main repository.""" + + class Task: def __init__(self, title): self.start = time.time() self.title = title + self.end = None + self.duration = None mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title) def stop(self): - duration = datetime.timedelta(seconds=time.time() - self.start) - mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END: ') + self.title + ' [' + str(duration) + ']') + self.end = time.time() + self.duration = datetime.timedelta(seconds=self.end - self.start) + mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END: ') + self.title + ' [' + str(self.duration) + ']') + return self def abort(self, codeOrMessage): - duration = datetime.timedelta(seconds=time.time() - self.start) - mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(duration) + ']') + self.end = time.time() + self.duration = datetime.timedelta(seconds=self.end - self.start) + mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(self.duration) + ']') mx.abort(codeOrMessage) + return self + tasks = [] total = Task('Gate') try: - t = Task('CleanJava') - clean(['--no-native']) - t.stop() + t = Task('Clean') + clean([]) + tasks.append(t.stop()) t = Task('Checkstyle') if mx.checkstyle([]) != 0: t.abort('Checkstyle warnings were found') - t.stop() + tasks.append(t.stop()) t = Task('Canonicalization Check') mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...')) if mx.canonicalizeprojects([]) != 0: t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.') - t.stop() + tasks.append(t.stop()) t = Task('BuildJava') build(['--no-native']) - t.stop() + tasks.append(t.stop()) for vmbuild in ['product', 'fastdebug']: global _vmbuild @@ -473,21 +504,21 @@ t = Task('BuildHotSpot:' + vmbuild) build(['--no-java', vmbuild]) - t.stop() + tasks.append(t.stop()) t = Task('BootstrapWithSystemAssertions:' + vmbuild) vm(['-esa', '-version']) - t.stop() + tasks.append(t.stop()) t = Task('UnitTests:' + vmbuild) unittest([]) - t.stop() + tasks.append(t.stop()) for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild): t = Task(str(test) + ':' + vmbuild) - if not test.test('-graal'): + if not test.test('graal'): t.abort(test.group + ' ' + test.name + ' Failed') - t.stop() + tasks.append(t.stop()) except KeyboardInterrupt: total.abort(1) @@ -497,6 +528,12 @@ total.abort(str(e)) total.stop() + + mx.log('Gate task times:') + for t in tasks: + mx.log(' ' + str(t.duration) + '\t' + t.title) + mx.log(' =======') + mx.log(' ' + str(total.duration)) def bench(args): """run benchmarks and parse their output for results @@ -549,7 +586,7 @@ for test in benchmarks: if not results.has_key(test.group): results[test.group] = {} - results[test.group].update(test.bench('-' + vm)) + results[test.group].update(test.bench(vm)) mx.log(json.dumps(results)) if resultFile: with open(resultFile, 'w') as f: @@ -558,7 +595,7 @@ def specjvm2008(args): benchArgs = [a[1:] for a in args if a[0] == '@'] vmArgs = [a for a in args if a[0] != '@'] - sanitycheck.getSPECjvm2008(benchArgs).bench('-graal', opts=vmArgs) + sanitycheck.getSPECjvm2008(benchArgs).bench('graal', opts=vmArgs) def mx_init(): _vmbuild = 'product' @@ -576,9 +613,10 @@ } if (_vmSourcesAvailable): - mx.add_argument('--product', action='store_const', dest='vmbuild', const='product', help='select the product VM') - mx.add_argument('--debug', action='store_const', dest='vmbuild', const='debug', help='select the debug VM') - mx.add_argument('--fastdebug', action='store_const', dest='vmbuild', const='fastdebug', help='select the fast debug VM') + mx.add_argument('--vm', action='store', dest='vm', default='graal', choices=['graal', 'server', 'client'], help='the VM to run (default: graal)') + mx.add_argument('--product', action='store_const', dest='vmbuild', const='product', help='select the product build of the VM') + mx.add_argument('--debug', action='store_const', dest='vmbuild', const='debug', help='select the debug build of the VM') + mx.add_argument('--fastdebug', action='store_const', dest='vmbuild', const='fastdebug', help='select the fast debug build of the VM') commands.update({ 'export': [export, '[-options] [zipfile]'], @@ -597,6 +635,8 @@ mx.abort('Requires Java version 1.7 or greater, got version ' + version) if (_vmSourcesAvailable): + global _vm + _vm = opts.vm if hasattr(opts, 'vmbuild') and opts.vmbuild is not None: global _vmbuild _vmbuild = opts.vmbuild diff -r 5d9c4796912d -r ab7c258e1cef mx/sanitycheck.py --- a/mx/sanitycheck.py Sun Feb 05 05:37:52 2012 +0100 +++ b/mx/sanitycheck.py Sun Feb 05 05:40:36 2012 +0100 @@ -134,7 +134,7 @@ self.name = name self.group = group self.successREs = successREs - self.failureREs = failureREs + self.failureREs = failureREs + [re.compile(r"Exception occured in scope: ")] self.scoreMatchers = scoreMatchers self.vmOpts = vmOpts self.cmd = cmd diff -r 5d9c4796912d -r ab7c258e1cef src/share/vm/code/debugInfoRec.hpp --- a/src/share/vm/code/debugInfoRec.hpp Sun Feb 05 05:37:52 2012 +0100 +++ b/src/share/vm/code/debugInfoRec.hpp Sun Feb 05 05:40:36 2012 +0100 @@ -101,7 +101,7 @@ methodHandle method, int bci, bool reexecute, - bool rethrow_exception, + bool rethrow_exception = false, bool is_method_handle_invoke = false, bool return_oop = false, DebugToken* locals = NULL,