# HG changeset patch # User Michael Van De Vanter # Date 1424396375 28800 # Node ID a015953a69f2668e5b9cdf9cdbc5d7a7f06903b6 # Parent d173a928cc15e5b9026833c100b4a7ab5e308931# Parent 108fbab4e0e84b394c05cee5b4343a816d61e82f Merge with 108fbab4e0e84b394c05cee5b4343a816d61e82f diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Thu Feb 19 17:39:35 2015 -0800 @@ -334,6 +334,9 @@ @Option(help = "Max number of loop explosions per method.", type = OptionType.Debug) public static final OptionValue MaximumLoopExplosionCount = new OptionValue<>(10000); + @Option(help = "Do not bail out but throw an exception on failed loop explosion.", type = OptionType.Debug) + public static final OptionValue FailedLoopExplosionIsFatal = new OptionValue<>(false); + /** * Counts the various paths taken through snippets. */ diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java Thu Feb 19 17:39:35 2015 -0800 @@ -43,8 +43,8 @@ public void testImplies() { StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES); - AbstractEndNode trueEnd = graph.add(new EndNode()); - AbstractEndNode falseEnd = graph.add(new EndNode()); + EndNode trueEnd = graph.add(new EndNode()); + EndNode falseEnd = graph.add(new EndNode()); AbstractBeginNode trueBegin = graph.add(new BeginNode()); trueBegin.setNext(trueEnd); diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Thu Feb 19 17:39:35 2015 -0800 @@ -98,7 +98,9 @@ } } if (pos != vobj.entryCount()) { - values = Arrays.copyOf(values, pos); + JavaValue[] newValues = new JavaValue[pos]; + System.arraycopy(values, 0, newValues, 0, pos); + values = newValues; } } entry.getValue().setValues(values); diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Thu Feb 19 17:39:35 2015 -0800 @@ -741,7 +741,9 @@ assert !isFrozen(); assert node.id() == Node.INITIAL_ID; if (nodes.length == nodesSize) { - nodes = Arrays.copyOf(nodes, (nodesSize * 2) + 1); + Node[] newNodes = new Node[(nodesSize * 2) + 1]; + System.arraycopy(nodes, 0, newNodes, 0, nodesSize); + nodes = newNodes; } int id = nodesSize; nodes[id] = node; diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Thu Feb 19 17:39:35 2015 -0800 @@ -342,7 +342,9 @@ if (length == 0) { extraUsages = new Node[4]; } else if (extraUsagesCount == length) { - extraUsages = Arrays.copyOf(extraUsages, length * 2 + 1); + Node[] newExtraUsages = new Node[length * 2 + 1]; + System.arraycopy(extraUsages, 0, newExtraUsages, 0, length); + extraUsages = newExtraUsages; } extraUsages[extraUsagesCount++] = node; } diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Thu Feb 19 17:39:35 2015 -0800 @@ -143,7 +143,9 @@ if (length == 0) { nodes = new Node[2]; } else if (size == length) { - nodes = Arrays.copyOf(nodes, nodes.length * 2 + 1); + Node[] newNodes = new Node[nodes.length * 2 + 1]; + System.arraycopy(nodes, 0, newNodes, 0, length); + nodes = newNodes; } nodes[size++] = node; update(null, (T) node); @@ -186,7 +188,9 @@ void copy(NodeList other) { self.incModCount(); incModCount(); - nodes = Arrays.copyOf(other.nodes, other.size); + Node[] newNodes = new Node[other.size]; + System.arraycopy(other.nodes, 0, newNodes, 0, newNodes.length); + nodes = newNodes; size = other.size; } diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Thu Feb 19 17:39:35 2015 -0800 @@ -861,12 +861,13 @@ int[] keySuccessors = new int[nofCases + 1]; int deoptSuccessorIndex = -1; int nextSuccessorIndex = 0; + boolean constantValue = ((ValueNode) value).isConstant(); for (int i = 0; i < nofCases + 1; i++) { if (i < nofCases) { keys[i] = bs.keyAt(i); } - if (isNeverExecutedCode(keyProbabilities[i])) { + if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) { if (deoptSuccessorIndex < 0) { deoptSuccessorIndex = nextSuccessorIndex++; actualSuccessors.add(null); diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Feb 19 17:39:35 2015 -0800 @@ -197,9 +197,9 @@ private boolean controlFlowSplit; private FixedWithNextNode[] firstInstructionArray; - private AbstractFrameStateBuilder[] entryStateArray; + private HIRFrameStateBuilder[] entryStateArray; private FixedWithNextNode[][] firstInstructionMatrix; - private AbstractFrameStateBuilder[][] entryStateMatrix; + private HIRFrameStateBuilder[][] entryStateMatrix; /** * @param isReplacement specifies if this object is being used to parse a method that @@ -253,7 +253,7 @@ BciBlockMapping newMapping = BciBlockMapping.create(stream, method); this.blockMap = newMapping; this.firstInstructionArray = new FixedWithNextNode[blockMap.getBlockCount()]; - this.entryStateArray = new AbstractFrameStateBuilder[blockMap.getBlockCount()]; + this.entryStateArray = new HIRFrameStateBuilder[blockMap.getBlockCount()]; if (graphBuilderConfig.doLivenessAnalysis()) { try (Scope s = Debug.scope("LivenessAnalysis")) { @@ -1103,11 +1103,23 @@ @Override protected void genIntegerSwitch(ValueNode value, ArrayList actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors) { - this.controlFlowSplit = true; - double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities); - IntegerSwitchNode switchNode = append(new IntegerSwitchNode(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors)); - for (int i = 0; i < actualSuccessors.size(); i++) { - switchNode.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState)); + if (value.isConstant()) { + JavaConstant constant = (JavaConstant) value.asConstant(); + int constantValue = constant.asInt(); + for (int i = 0; i < keys.length; ++i) { + if (keys[i] == constantValue) { + appendGoto(actualSuccessors.get(keySuccessors[i])); + return; + } + } + appendGoto(actualSuccessors.get(keySuccessors[keys.length])); + } else { + this.controlFlowSplit = true; + double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities); + IntegerSwitchNode switchNode = append(new IntegerSwitchNode(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors)); + for (int i = 0; i < actualSuccessors.size(); i++) { + switchNode.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState)); + } } } @@ -1248,7 +1260,7 @@ } } - private void setEntryState(BciBlock block, int dimension, AbstractFrameStateBuilder entryState) { + private void setEntryState(BciBlock block, int dimension, HIRFrameStateBuilder entryState) { int id = block.id; if (dimension == 0) { this.entryStateArray[id] = entryState; @@ -1257,9 +1269,9 @@ } } - private void setEntryStateMultiDimension(int dimension, AbstractFrameStateBuilder entryState, int id) { + private void setEntryStateMultiDimension(int dimension, HIRFrameStateBuilder entryState, int id) { if (entryStateMatrix == null) { - entryStateMatrix = new AbstractFrameStateBuilder[4][]; + entryStateMatrix = new HIRFrameStateBuilder[4][]; } if (dimension - 1 < entryStateMatrix.length) { // We are within bounds. @@ -1268,7 +1280,7 @@ entryStateMatrix = Arrays.copyOf(entryStateMatrix, Math.max(entryStateMatrix.length * 2, dimension)); } if (entryStateMatrix[dimension - 1] == null) { - entryStateMatrix[dimension - 1] = new AbstractFrameStateBuilder[blockMap.getBlockCount()]; + entryStateMatrix[dimension - 1] = new HIRFrameStateBuilder[blockMap.getBlockCount()]; } entryStateMatrix[dimension - 1][id] = entryState; } @@ -1355,7 +1367,7 @@ targetNode = getFirstInstruction(block, operatingDimension); Target target = checkLoopExit(targetNode, block, state); FixedNode result = target.fixed; - AbstractFrameStateBuilder currentEntryState = target.state == state ? state.copy() : target.state; + HIRFrameStateBuilder currentEntryState = target.state == state ? state.copy() : target.state; setEntryState(block, operatingDimension, currentEntryState); currentEntryState.clearNonLiveLocals(block, liveness, true); @@ -1394,7 +1406,7 @@ AbstractBeginNode placeholder = (AbstractBeginNode) getFirstInstruction(block, operatingDimension); // The EndNode for the already existing edge. - AbstractEndNode end = currentGraph.add(new EndNode()); + EndNode end = currentGraph.add(new EndNode()); // The MergeNode that replaces the placeholder. AbstractMergeNode mergeNode = currentGraph.add(new MergeNode()); FixedNode next = placeholder.next(); @@ -1415,7 +1427,7 @@ AbstractMergeNode mergeNode = (AbstractMergeNode) getFirstInstruction(block, operatingDimension); // The EndNode for the newly merged edge. - AbstractEndNode newEnd = currentGraph.add(new EndNode()); + EndNode newEnd = currentGraph.add(new EndNode()); Target target = checkLoopExit(newEnd, block, state); FixedNode result = target.fixed; ((HIRFrameStateBuilder) getEntryState(block, operatingDimension)).merge(mergeNode, target.state); @@ -1445,7 +1457,12 @@ // iteration. context.targetPeelIteration = nextPeelIteration++; if (nextPeelIteration > MaximumLoopExplosionCount.getValue()) { - throw new BailoutException("too many loop explosion interations - does the explosion not terminate?"); + String message = "too many loop explosion interations - does the explosion not terminate for method " + method + "?"; + if (FailedLoopExplosionIsFatal.getValue()) { + throw new RuntimeException(message); + } else { + throw new BailoutException(message); + } } } @@ -1635,7 +1652,7 @@ // Create the loop header block, which later will merge the backward branches of // the loop. controlFlowSplit = true; - AbstractEndNode preLoopEnd = currentGraph.add(new EndNode()); + EndNode preLoopEnd = currentGraph.add(new EndNode()); LoopBeginNode loopBegin = currentGraph.add(new LoopBeginNode()); lastInstr.setNext(preLoopEnd); // Add the single non-loop predecessor of the loop header. diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Thu Feb 19 17:39:35 2015 -0800 @@ -312,9 +312,9 @@ if (newEarlyExit == null) { continue; } - AbstractMergeNode merge = graph.add(new MergeNode()); - AbstractEndNode originalEnd = graph.add(new EndNode()); - AbstractEndNode newEnd = graph.add(new EndNode()); + MergeNode merge = graph.add(new MergeNode()); + EndNode originalEnd = graph.add(new EndNode()); + EndNode newEnd = graph.add(new EndNode()); merge.addForwardEnd(originalEnd); merge.addForwardEnd(newEnd); loopEarlyExit.setNext(originalEnd); diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Thu Feb 19 17:39:35 2015 -0800 @@ -293,14 +293,14 @@ private AbstractBeginNode mergeEnds() { assert isDuplicate(); - List endsToMerge = new LinkedList<>(); + List endsToMerge = new LinkedList<>(); // map peel exits to the corresponding loop exits Map reverseEnds = CollectionsFactory.newMap(); LoopBeginNode loopBegin = original().loop().loopBegin(); for (LoopEndNode le : loopBegin.loopEnds()) { AbstractEndNode duplicate = getDuplicatedNode(le); if (duplicate != null) { - endsToMerge.add(duplicate); + endsToMerge.add((EndNode) duplicate); reverseEnds.put(duplicate, le); } } @@ -323,7 +323,7 @@ duplicateState = state.duplicateWithVirtualState(); newExitMerge.setStateAfter(duplicateState); } - for (AbstractEndNode end : endsToMerge) { + for (EndNode end : endsToMerge) { newExitMerge.addForwardEnd(end); } diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMergeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMergeNode.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMergeNode.java Thu Feb 19 17:39:35 2015 -0800 @@ -45,18 +45,18 @@ super(c); } - @Input(InputType.Association) protected NodeInputList ends = new NodeInputList<>(this); + @Input(InputType.Association) protected NodeInputList ends = new NodeInputList<>(this); @Override public void generate(NodeLIRBuilderTool gen) { gen.visitMerge(this); } - public int forwardEndIndex(AbstractEndNode end) { + public int forwardEndIndex(EndNode end) { return ends.indexOf(end); } - public void addForwardEnd(AbstractEndNode end) { + public void addForwardEnd(EndNode end) { ends.add(end); } @@ -64,12 +64,12 @@ return ends.size(); } - public AbstractEndNode forwardEndAt(int index) { + public EndNode forwardEndAt(int index) { return ends.get(index); } @Override - public NodeIterable cfgPredecessors() { + public NodeIterable cfgPredecessors() { return ends; } @@ -113,7 +113,7 @@ ends.clear(); } - public NodeInputList forwardEnds() { + public NodeInputList forwardEnds() { return ends; } @@ -122,7 +122,7 @@ } public int phiPredecessorIndex(AbstractEndNode pred) { - return forwardEndIndex(pred); + return forwardEndIndex((EndNode) pred); } public AbstractEndNode phiPredecessorAt(int index) { @@ -176,8 +176,9 @@ if (merge instanceof LoopBeginNode) { newEnd = graph().add(new LoopEndNode((LoopBeginNode) merge)); } else { - newEnd = graph().add(new EndNode()); - merge.addForwardEnd(newEnd); + EndNode tmpEnd = graph().add(new EndNode()); + merge.addForwardEnd(tmpEnd); + newEnd = tmpEnd; } for (PhiNode phi : merge.phis()) { ValueNode v = phi.valueAt(origLoopEnd); @@ -213,8 +214,8 @@ } ValuePhiNode returnValuePhi = returnNode.result() == null || !isPhiAtMerge(returnNode.result()) ? null : (ValuePhiNode) returnNode.result(); - List endNodes = forwardEnds().snapshot(); - for (AbstractEndNode end : endNodes) { + List endNodes = forwardEnds().snapshot(); + for (EndNode end : endNodes) { ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end))); if (tool != null) { tool.addToWorkList(end.predecessor()); @@ -222,7 +223,7 @@ end.replaceAtPredecessor(newReturn); } GraphUtil.killCFG(this); - for (AbstractEndNode end : endNodes) { + for (EndNode end : endNodes) { end.safeDelete(); } for (PhiNode phi : phis) { diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Thu Feb 19 17:39:35 2015 -0800 @@ -750,7 +750,7 @@ MergeNode falseMerge = null; assert merge.stateAfter() == null; - for (AbstractEndNode end : merge.forwardEnds().snapshot()) { + for (EndNode end : merge.forwardEnds().snapshot()) { Node value = phi.valueAt(end); Node result = null; if (condition() instanceof Canonicalizable.Binary) { @@ -906,7 +906,7 @@ } } - List mergePredecessors = merge.cfgPredecessors().snapshot(); + List mergePredecessors = merge.cfgPredecessors().snapshot(); assert phi.valueCount() == merge.forwardEndCount(); Constant[] xs = constantValues(compare.getX(), merge, false); @@ -920,8 +920,8 @@ return false; } - List falseEnds = new ArrayList<>(mergePredecessors.size()); - List trueEnds = new ArrayList<>(mergePredecessors.size()); + List falseEnds = new ArrayList<>(mergePredecessors.size()); + List trueEnds = new ArrayList<>(mergePredecessors.size()); Map phiValues = CollectionsFactory.newMap(mergePredecessors.size()); AbstractBeginNode oldFalseSuccessor = falseSuccessor(); @@ -930,9 +930,9 @@ setFalseSuccessor(null); setTrueSuccessor(null); - Iterator ends = mergePredecessors.iterator(); + Iterator ends = mergePredecessors.iterator(); for (int i = 0; i < xs.length; i++) { - AbstractEndNode end = ends.next(); + EndNode end = ends.next(); phiValues.put(end, phi.valueAt(end)); if (compare.condition().foldCondition(xs[i], ys[i], tool.getConstantReflection(), compare.unorderedIsTrue())) { trueEnds.add(end); @@ -1062,7 +1062,7 @@ * @param oldMerge the merge being removed * @param phiValues the values of the phi at the merge, keyed by the merge ends */ - private void connectEnds(List ends, Map phiValues, AbstractBeginNode successor, AbstractMergeNode oldMerge, SimplifierTool tool) { + private void connectEnds(List ends, Map phiValues, AbstractBeginNode successor, AbstractMergeNode oldMerge, SimplifierTool tool) { if (!ends.isEmpty()) { if (ends.size() == 1) { AbstractEndNode end = ends.get(0); @@ -1076,7 +1076,7 @@ PhiNode oldPhi = (PhiNode) oldMerge.usages().first(); PhiNode newPhi = graph().addWithoutUnique(new ValuePhiNode(oldPhi.stamp(), newMerge)); - for (AbstractEndNode end : ends) { + for (EndNode end : ends) { newPhi.addInput(phiValues.get(end)); newMerge.addForwardEnd(end); } diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Thu Feb 19 17:39:35 2015 -0800 @@ -98,16 +98,12 @@ * * @return the set of {@code LoopEndNode} that correspond to back-edges for this loop */ - public List orderedLoopEnds() { - List snapshot = loopEnds().snapshot(); - Collections.sort(snapshot, new Comparator() { - - @Override - public int compare(LoopEndNode o1, LoopEndNode o2) { - return o1.endIndex() - o2.endIndex(); - } - }); - return snapshot; + public LoopEndNode[] orderedLoopEnds() { + LoopEndNode[] result = new LoopEndNode[this.getLoopEndCount()]; + for (LoopEndNode end : loopEnds()) { + result[end.endIndex()] = end; + } + return result; } public AbstractEndNode forwardEnd() { @@ -153,7 +149,7 @@ return loopEnd.endIndex() + forwardEndCount(); } } else { - return super.forwardEndIndex(pred); + return super.forwardEndIndex((EndNode) pred); } throw ValueNodeUtil.shouldNotReachHere("unknown pred : " + pred); } @@ -183,6 +179,10 @@ return nextEndIndex++; } + public int getLoopEndCount() { + return nextEndIndex; + } + public int unswitches() { return unswitches; } diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Thu Feb 19 17:39:35 2015 -0800 @@ -200,14 +200,19 @@ } // Connect blocks (including loop backward edges), but ignoring dead code (blocks with id < 0). + // Predecessors need to be in the order expected when iterating phi inputs. private void connectBlocks() { for (Block block : reversePostOrder) { - List predecessors = new ArrayList<>(4); + List predecessors = new ArrayList<>(1); double probability = block.getBeginNode() instanceof StartNode ? 1D : 0D; for (Node predNode : block.getBeginNode().cfgPredecessors()) { Block predBlock = nodeToBlock.get(predNode); if (predBlock.getId() >= 0) { predecessors.add(predBlock); + if (predBlock.getSuccessors() == null) { + predBlock.setSuccessors(new ArrayList<>(1)); + } + predBlock.getSuccessors().add(block); probability += predBlock.probability; } } @@ -222,6 +227,10 @@ assert predBlock != null : predNode; if (predBlock.getId() >= 0) { predecessors.add(predBlock); + if (predBlock.getSuccessors() == null) { + predBlock.setSuccessors(new ArrayList<>(1)); + } + predBlock.getSuccessors().add(block); } } } @@ -230,19 +239,9 @@ } block.setPredecessors(predecessors); block.setProbability(probability); - - List successors = new ArrayList<>(4); - for (Node suxNode : block.getEndNode().cfgSuccessors()) { - Block suxBlock = nodeToBlock.get(suxNode); - assert suxBlock.getId() >= 0; - successors.add(suxBlock); + if (block.getSuccessors() == null) { + block.setSuccessors(new ArrayList<>(1)); } - if (block.getEndNode() instanceof LoopEndNode) { - Block suxBlock = nodeToBlock.get(((LoopEndNode) block.getEndNode()).loopBegin()); - assert suxBlock.getId() >= 0; - successors.add(suxBlock); - } - block.setSuccessors(successors); } } @@ -266,29 +265,30 @@ computeLoopBlocks(exitBlock.getFirstPredecessor(), loop); loop.getExits().add(exitBlock); } - List unexpected = new LinkedList<>(); - for (Block b : loop.getBlocks()) { + + // The following loop can add new blocks to the end of the loop's block list. + int size = loop.getBlocks().size(); + for (int i = 0; i < size; ++i) { + Block b = loop.getBlocks().get(i); for (Block sux : b.getSuccessors()) { if (sux.loop != loop) { AbstractBeginNode begin = sux.getBeginNode(); if (!(begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == loopBegin)) { Debug.log(3, "Unexpected loop exit with %s, including whole branch in the loop", sux); - unexpected.add(sux); + addBranchToLoop(loop, sux); } } } } - for (Block b : unexpected) { - addBranchToLoop(loop, b); - } } } } private static void addBranchToLoop(Loop l, Block b) { - if (l.getBlocks().contains(b)) { + if (b.loop == l) { return; } + assert !(l.getBlocks().contains(b)); l.getBlocks().add(b); b.loop = l; for (Block sux : b.getSuccessors()) { diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java Thu Feb 19 17:39:35 2015 -0800 @@ -73,7 +73,7 @@ AbstractMergeNode merge = (AbstractMergeNode) pred; if (fixedGuard.condition() instanceof CompareNode) { CompareNode compare = (CompareNode) fixedGuard.condition(); - List mergePredecessors = merge.cfgPredecessors().snapshot(); + List mergePredecessors = merge.cfgPredecessors().snapshot(); Constant[] xs = IfNode.constantValues(compare.getX(), merge, true); if (xs == null) { diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Thu Feb 19 17:39:35 2015 -0800 @@ -280,11 +280,11 @@ mergeAfter.clearEnds(); expandDuplicated(duplicatedNodes, mergeAfter); - List endSnapshot = merge.forwardEnds().snapshot(); + List endSnapshot = merge.forwardEnds().snapshot(); List phiSnapshot = merge.phis().snapshot(); int endIndex = 0; - for (final AbstractEndNode forwardEnd : merge.forwardEnds()) { + for (final EndNode forwardEnd : merge.forwardEnds()) { Map duplicates; if (replacements == null || replacements.get(endIndex) == null) { duplicates = graph.addDuplicates(duplicatedNodes, graph, duplicatedNodes.size(), (DuplicationReplacement) null); @@ -296,7 +296,7 @@ for (Map.Entry phi : bottomPhis.entrySet()) { phi.getValue().initializeValueAt(merge.forwardEndIndex(forwardEnd), (ValueNode) duplicates.get(phi.getKey())); } - mergeAfter.addForwardEnd((AbstractEndNode) duplicates.get(endAfter)); + mergeAfter.addForwardEnd((EndNode) duplicates.get(endAfter)); // re-wire the duplicated ValueAnchorNode to the predecessor of the corresponding // EndNode @@ -452,8 +452,8 @@ * @return The newly created end node. */ private AbstractEndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) { - AbstractMergeNode newBottomMerge = graph.add(new MergeNode()); - AbstractEndNode newBottomEnd = graph.add(new EndNode()); + MergeNode newBottomMerge = graph.add(new MergeNode()); + EndNode newBottomEnd = graph.add(new EndNode()); newBottomMerge.addForwardEnd(newBottomEnd); newBottomMerge.setStateAfter(stateAfterMerge); ((FixedWithNextNode) successor.predecessor()).setNext(newBottomEnd); diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Thu Feb 19 17:39:35 2015 -0800 @@ -464,7 +464,7 @@ AbstractBeginNode calleeEntryNode = graph.add(new BeginNode()); calleeEntryNode.setNext(duplicatedInvoke.asNode()); - AbstractEndNode endNode = graph.add(new EndNode()); + EndNode endNode = graph.add(new EndNode()); duplicatedInvoke.setNext(endNode); returnMerge.addForwardEnd(endNode); @@ -499,7 +499,7 @@ // set new state (pop old exception object, push new one) newExceptionEdge.setStateAfter(stateAfterException.duplicateModified(Kind.Object, newExceptionEdge)); - AbstractEndNode endNode = graph.add(new EndNode()); + EndNode endNode = graph.add(new EndNode()); newExceptionEdge.setNext(endNode); exceptionMerge.addForwardEnd(endNode); exceptionObjectPhi.addInput(newExceptionEdge); diff -r d173a928cc15 -r a015953a69f2 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java Thu Feb 19 13:24:50 2015 -0800 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java Thu Feb 19 17:39:35 2015 -0800 @@ -101,7 +101,7 @@ if (current.predecessor() == null) { if (current instanceof AbstractMergeNode) { AbstractMergeNode currentMerge = (AbstractMergeNode) current; - NodeInputList currentForwardEnds = currentMerge.forwardEnds(); + NodeInputList currentForwardEnds = currentMerge.forwardEnds(); /* * Use simple iteration instead of streams, since the stream infrastructure adds * many frames which causes the recursion to overflow the stack earlier than it