Mercurial > hg > graal-jvmci-8
changeset 19633:cb701331de39
Merge.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Fri, 27 Feb 2015 16:36:38 +0100 |
parents | afad10e79e13 (diff) 73811d1b4cd0 (current diff) |
children | 7b42a78ea270 |
files | graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMonitorValue.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java |
diffstat | 24 files changed, 731 insertions(+), 125 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/BytecodeFrame.java Fri Feb 27 16:36:38 2015 +0100 @@ -170,7 +170,7 @@ Kind kind = values[i].getKind(); if (kind.needsTwoSlots()) { assert values.length > i + 1 : String.format("missing second word %s", this); - assert values[i + 1] == null || values[i + 1].getKind() == Kind.Illegal; + assert values[i + 1] == null || values[i + 1].getKind() == Kind.Illegal : this; } } }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Fri Feb 27 16:36:38 2015 +0100 @@ -303,6 +303,7 @@ protected static String getCanonicalGraphString(StructuredGraph graph, boolean excludeVirtual, boolean checkConstants) { SchedulePhase schedule = new SchedulePhase(); + schedule.setScheduleConstants(true); schedule.apply(graph); NodeMap<Integer> canonicalId = graph.createNodeMap();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LongNodeChainTest.java Fri Feb 27 16:36:38 2015 +0100 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015, 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.graal.compiler.test; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.schedule.*; +import com.oracle.graal.phases.schedule.SchedulePhase.SchedulingStrategy; +import com.oracle.graal.phases.tiers.*; + +public class LongNodeChainTest extends GraalCompilerTest { + + public static final int N = 100000; + + @Ignore + @Test + public void testLongAddChain() { + longAddChain(true); + longAddChain(false); + } + + private void longAddChain(boolean reverse) { + HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); + StructuredGraph graph = new StructuredGraph(AllowAssumptions.NO); + ValueNode constant = graph.unique(ConstantNode.forPrimitive(JavaConstant.INT_1)); + ValueNode value = null; + if (reverse) { + AddNode addNode = graph.unique(new AddNode(constant, constant)); + value = addNode; + for (int i = 1; i < N; ++i) { + AddNode newAddNode = graph.addWithoutUnique(new AddNode(constant, constant)); + addNode.setY(newAddNode); + addNode = newAddNode; + } + } else { + value = constant; + for (int i = 0; i < N; ++i) { + value = graph.unique(new AddNode(constant, value)); + } + } + ReturnNode returnNode = graph.add(new ReturnNode(value)); + graph.start().setNext(returnNode); + + for (SchedulingStrategy s : SchedulingStrategy.values()) { + new SchedulePhase(s).apply(graph); + } + + new CanonicalizerPhase(false).apply(graph, context); + JavaConstant asConstant = (JavaConstant) returnNode.result().asConstant(); + Assert.assertEquals(N + 1, asConstant.asInt()); + } +}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Fri Feb 27 16:36:38 2015 +0100 @@ -113,6 +113,7 @@ } objectStates.clear(); + assert frame.validateFormat(); return newLIRFrameState(exceptionEdge, frame, virtualObjectsArray); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/NodeValidationChecksTest.java Fri Feb 27 16:36:38 2015 +0100 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015, 2015, 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.graal.graph.test; + +import org.junit.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; + +public class NodeValidationChecksTest { + + @NodeInfo + static final class TestNode extends Node { + public static final NodeClass<TestNode> TYPE = NodeClass.create(TestNode.class); + + @Input TestNode input; + @Successor TestNode successor; + + public TestNode(TestNode input, TestNode successor) { + super(TYPE); + this.input = input; + this.successor = successor; + } + } + + @Test + public void testInputNotAlive() { + Graph graph = new Graph(); + TestNode node = new TestNode(null, null); + try { + graph.add(new TestNode(node, null)); + Assert.fail("Exception expected."); + } catch (IllegalStateException e) { + Assert.assertTrue(e.getMessage().contains("Input")); + Assert.assertTrue(e.getMessage().contains("not alive")); + } + } + + @Test + public void testSuccessorNotAlive() { + Graph graph = new Graph(); + TestNode node = new TestNode(null, null); + try { + graph.add(new TestNode(null, node)); + Assert.fail("Exception expected."); + } catch (IllegalStateException e) { + Assert.assertTrue(e.getMessage().contains("Successor")); + Assert.assertTrue(e.getMessage().contains("not alive")); + } + } +}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java Fri Feb 27 16:36:38 2015 +0100 @@ -61,20 +61,20 @@ } } - private static Node getNode(Node node, long offset) { + private static Node getNodeUnsafe(Node node, long offset) { return (Node) unsafe.getObject(node, offset); } @SuppressWarnings("unchecked") - private static NodeList<Node> getNodeList(Node node, long offset) { + private static NodeList<Node> getNodeListUnsafe(Node node, long offset) { return (NodeList<Node>) unsafe.getObject(node, offset); } - private static void putNode(Node node, long offset, Node value) { + private static void putNodeUnsafe(Node node, long offset, Node value) { unsafe.putObject(node, offset, value); } - private static void putNodeList(Node node, long offset, NodeList<?> value) { + private static void putNodeListUnsafe(Node node, long offset, NodeList<?> value) { unsafe.putObject(node, offset, value); } @@ -93,9 +93,8 @@ * @param index the index of a non-list the edge (must be less than {@link #getDirectCount()}) * @return the Node at the other edge of the requested edge */ - public Node getNode(Node node, int index) { - assert index >= 0 && index < directCount; - return getNode(node, offsets[index]); + public static Node getNode(Node node, long[] offsets, int index) { + return getNodeUnsafe(node, offsets[index]); } /** @@ -106,9 +105,8 @@ * {@link #getDirectCount()}) * @return the {@link NodeList} at the other edge of the requested edge */ - public NodeList<Node> getNodeList(Node node, int index) { - assert index >= directCount && index < getCount(); - return getNodeList(node, offsets[index]); + public static NodeList<Node> getNodeList(Node node, long[] offsets, int index) { + return getNodeListUnsafe(node, offsets[index]); } /** @@ -119,18 +117,22 @@ * @param node the node whose edges are to be cleared */ public void clear(Node node) { + final long[] curOffsets = this.offsets; + final Type curType = this.type; int index = 0; - while (index < getDirectCount()) { - initializeNode(node, index++, null); + int curDirectCount = getDirectCount(); + while (index < curDirectCount) { + initializeNode(node, curOffsets, index++, null); } - while (index < getCount()) { - NodeList<Node> list = getNodeList(node, index); + int curCount = getCount(); + while (index < curCount) { + NodeList<Node> list = getNodeList(node, curOffsets, index); if (list != null) { int size = list.initialSize; - NodeList<Node> newList = type == Edges.Type.Inputs ? new NodeInputList<>(node, size) : new NodeSuccessorList<>(node, size); + NodeList<Node> newList = curType == Edges.Type.Inputs ? new NodeInputList<>(node, size) : new NodeSuccessorList<>(node, size); // replacing with a new list object is the expected behavior! - initializeList(node, index, newList); + initializeList(node, curOffsets, index, newList); } index++; } @@ -145,12 +147,14 @@ */ public void initializeLists(Node node, Node prototype) { int index = getDirectCount(); + final long[] curOffsets = this.offsets; + final Edges.Type curType = this.type; while (index < getCount()) { - NodeList<Node> list = getNodeList(prototype, index); + NodeList<Node> list = getNodeList(prototype, curOffsets, index); if (list != null) { int size = list.initialSize; - NodeList<Node> newList = type == Edges.Type.Inputs ? new NodeInputList<>(node, size) : new NodeSuccessorList<>(node, size); - initializeList(node, index, newList); + NodeList<Node> newList = curType == Edges.Type.Inputs ? new NodeInputList<>(node, size) : new NodeSuccessorList<>(node, size); + initializeList(node, curOffsets, index, newList); } index++; } @@ -167,16 +171,20 @@ assert fromNode != toNode; assert fromNode.getNodeClass().getClazz() == toNode.getNodeClass().getClazz(); int index = 0; - while (index < getDirectCount()) { - initializeNode(toNode, index, getNode(fromNode, index)); + final long[] curOffsets = this.offsets; + final Type curType = this.type; + int curDirectCount = getDirectCount(); + while (index < curDirectCount) { + initializeNode(toNode, curOffsets, index, getNode(fromNode, curOffsets, index)); index++; } - while (index < getCount()) { - NodeList<Node> list = getNodeList(toNode, index); - NodeList<Node> fromList = getNodeList(fromNode, index); + int curCount = getCount(); + while (index < curCount) { + NodeList<Node> list = getNodeList(toNode, curOffsets, index); + NodeList<Node> fromList = getNodeList(fromNode, curOffsets, index); if (list == null || list == fromList) { - list = type == Edges.Type.Inputs ? new NodeInputList<>(toNode, fromList) : new NodeSuccessorList<>(toNode, fromList); - initializeList(toNode, index, list); + list = curType == Edges.Type.Inputs ? new NodeInputList<>(toNode, fromList) : new NodeSuccessorList<>(toNode, fromList); + initializeList(toNode, curOffsets, index, list); } else { list.copy(fromList); } @@ -195,17 +203,20 @@ */ public boolean replaceFirst(Node node, Node key, Node replacement) { int index = 0; - while (index < getDirectCount()) { - Node edge = getNode(node, index); + final long[] curOffsets = this.getOffsets(); + int curDirectCount = getDirectCount(); + while (index < curDirectCount) { + Node edge = getNode(node, curOffsets, index); if (edge == key) { assert replacement == null || getType(index).isAssignableFrom(replacement.getClass()) : "Can not assign " + replacement.getClass() + " to " + getType(index) + " in " + node; - initializeNode(node, index, replacement); + initializeNode(node, curOffsets, index, replacement); return true; } index++; } - while (index < getCount()) { - NodeList<Node> list = getNodeList(node, index); + int curCount = getCount(); + while (index < curCount) { + NodeList<Node> list = getNodeList(node, curOffsets, index); if (list != null) { if (list.replaceFirst(key, replacement)) { return true; @@ -229,13 +240,12 @@ * @param index the index of the edge (between 0 and {@link #getCount()}) * @param value the node to be written to the edge */ - public void initializeNode(Node node, int index, Node value) { - putNode(node, offsets[index], value); + public static void initializeNode(Node node, long[] offsets, int index, Node value) { + putNodeUnsafe(node, offsets[index], value); } - public void initializeList(Node node, int index, NodeList<Node> value) { - assert index >= directCount; - putNodeList(node, offsets[index], value); + public static void initializeList(Node node, long[] offsets, int index, NodeList<Node> value) { + putNodeListUnsafe(node, offsets[index], value); } /** @@ -248,21 +258,22 @@ */ public void setNode(Node node, int index, Node value) { assert index < directCount; - Node old = getNode(node, offsets[index]); - putNode(node, offsets[index], value); + Node old = getNodeUnsafe(node, offsets[index]); + putNodeUnsafe(node, offsets[index], value); update(node, old, value); } protected abstract void update(Node node, Node oldValue, Node newValue); public boolean contains(Node node, Node value) { + final long[] curOffsets = this.offsets; for (int i = 0; i < directCount; i++) { - if (getNode(node, i) == value) { + if (getNode(node, curOffsets, i) == value) { return true; } } for (int i = directCount; i < getCount(); i++) { - NodeList<?> curList = getNodeList(node, i); + NodeList<?> curList = getNodeList(node, curOffsets, i); if (curList != null && curList.contains(value)) { return true; } @@ -276,15 +287,16 @@ public boolean areEqualIn(Node node, Node other) { assert node.getNodeClass().getClazz() == other.getNodeClass().getClazz(); int index = 0; + final long[] curOffsets = this.offsets; while (index < directCount) { - if (getNode(other, index) != getNode(node, index)) { + if (getNode(other, curOffsets, index) != getNode(node, curOffsets, index)) { return false; } index++; } while (index < getCount()) { - NodeList<Node> list = getNodeList(other, index); - if (!Objects.equals(list, getNodeList(node, index))) { + NodeList<Node> list = getNodeList(other, curOffsets, index); + if (!Objects.equals(list, getNodeList(node, curOffsets, index))) { return false; } index++; @@ -306,6 +318,9 @@ NodeList<Node> list; protected boolean needsForward; protected Node nextElement; + protected final int directCount; + protected final int count; + protected final long[] offsets; /** * Creates an iterator that will iterate over some given edges in a given node. @@ -316,14 +331,17 @@ index = NOT_ITERABLE; subIndex = 0; needsForward = true; + this.directCount = edges.getDirectCount(); + this.offsets = edges.getOffsets(); + this.count = edges.getCount(); } void forward() { needsForward = false; - if (index < edges.getDirectCount()) { + if (index < directCount) { index++; - while (index < edges.getDirectCount()) { - nextElement = edges.getNode(node, index); + while (index < directCount) { + nextElement = Edges.getNode(node, offsets, index); if (nextElement != null) { return; } @@ -340,7 +358,7 @@ private void forwardNodeList() { do { if (subIndex == 0) { - list = edges.getNodeList(node, index); + list = Edges.getNodeList(node, offsets, index); } if (list != null) { while (subIndex < list.size()) { @@ -361,7 +379,7 @@ forward(); } needsForward = true; - if (index < edges.getCount()) { + if (index < count) { return nextElement; } throw new NoSuchElementException(); @@ -385,7 +403,7 @@ forward(); } needsForward = true; - if (index < edges.getDirectCount()) { + if (index < directCount) { return new Position(edges, index, NOT_ITERABLE); } else { return new Position(edges, index, subIndex); @@ -399,6 +417,7 @@ } private static class AllEdgesIterator extends EdgesIterator { + AllEdgesIterator(Node node, Edges edges) { super(node, edges); } @@ -406,10 +425,10 @@ @Override void forward() { needsForward = false; - if (index < edges.getDirectCount()) { + if (index < directCount) { index++; if (index < edges.getDirectCount()) { - nextElement = edges.getNode(node, index); + nextElement = Edges.getNode(node, edges.getOffsets(), index); return; } } else { @@ -417,7 +436,7 @@ } while (index < edges.getCount()) { if (subIndex == 0) { - list = edges.getNodeList(node, index); + list = Edges.getNodeList(node, edges.getOffsets(), index); } if (list != null) { if (subIndex < list.size()) { @@ -468,6 +487,9 @@ } } + static int cnt1; + static int cnt2; + public NodeClassIterable getIterable(final Node node) { return new NodeClassIterable() { @@ -498,8 +520,9 @@ public void accept(Node node, BiConsumer<Node, Node> consumer) { int index = 0; int curDirectCount = this.directCount; + final long[] curOffsets = this.offsets; while (index < curDirectCount) { - Node curNode = getNode(node, index); + Node curNode = getNode(node, curOffsets, index); if (curNode != null) { consumer.accept(node, curNode); } @@ -507,7 +530,7 @@ } int count = getCount(); while (index < count) { - NodeList<Node> list = getNodeList(node, index); + NodeList<Node> list = getNodeList(node, curOffsets, index); if (list != null) { for (int i = 0; i < list.size(); ++i) { Node curNode = list.get(i); @@ -519,4 +542,8 @@ index++; } } + + public long[] getOffsets() { + return this.offsets; + } }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Feb 27 16:36:38 2015 +0100 @@ -521,8 +521,18 @@ assert assertTrue(id == INITIAL_ID, "unexpected id: %d", id); this.graph = newGraph; newGraph.register(this); - this.acceptInputs((n, i) -> n.updateUsages(null, i)); - this.acceptSuccessors((n, s) -> n.updatePredecessor(null, s)); + this.acceptInputs((n, i) -> { + if (!i.isAlive()) { + throw new IllegalStateException(String.format("Input %s of newly created node %s is not alive.", i, n)); + } + n.updateUsages(null, i); + }); + this.acceptSuccessors((n, s) -> { + if (!s.isAlive()) { + throw new IllegalStateException(String.format("Successor %s of newly created node %s is not alive.", s, n)); + } + n.updatePredecessor(null, s); + }); } public final NodeClass<? extends Node> getNodeClass() {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Fri Feb 27 16:36:38 2015 +0100 @@ -585,8 +585,9 @@ int index = 0; Type curType = edges.type(); int directCount = edges.getDirectCount(); + final long[] curOffsets = edges.getOffsets(); while (index < directCount) { - Node edge = edges.getNode(node, index); + Node edge = Edges.getNode(node, curOffsets, index); if (edge != null) { Node newEdge = duplicationReplacement.replacement(edge, curType); if (curType == Edges.Type.Inputs) { @@ -595,15 +596,15 @@ node.updatePredecessor(null, newEdge); } assert assertUpdateValid(node, edges, index, newEdge); - edges.initializeNode(node, index, newEdge); + Edges.initializeNode(node, curOffsets, index, newEdge); } index++; } while (index < edges.getCount()) { - NodeList<Node> list = edges.getNodeList(node, index); + NodeList<Node> list = Edges.getNodeList(node, curOffsets, index); if (list != null) { - edges.initializeList(node, index, updateEdgeListCopy(node, list, duplicationReplacement, curType)); + Edges.initializeList(node, curOffsets, index, updateEdgeListCopy(node, list, duplicationReplacement, curType)); } index++; } @@ -659,9 +660,10 @@ private void initNullEdgeLists(Node node, Edges.Type type) { Edges edges = getEdges(type); + final long[] curOffsets = edges.getOffsets(); for (int inputPos = edges.getDirectCount(); inputPos < edges.getCount(); inputPos++) { - if (edges.getNodeList(node, inputPos) == null) { - edges.initializeList(node, inputPos, type == Edges.Type.Inputs ? new NodeInputList<>(node) : new NodeSuccessorList<>(node)); + if (Edges.getNodeList(node, curOffsets, inputPos) == null) { + Edges.initializeList(node, curOffsets, inputPos, type == Edges.Type.Inputs ? new NodeInputList<>(node) : new NodeSuccessorList<>(node)); } } }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java Fri Feb 27 16:36:38 2015 +0100 @@ -53,9 +53,9 @@ public Node get(Node node) { if (index < edges.getDirectCount()) { - return edges.getNode(node, index); + return Edges.getNode(node, edges.getOffsets(), index); } else { - return edges.getNodeList(node, index).get(subIndex); + return Edges.getNodeList(node, edges.getOffsets(), index).get(subIndex); } } @@ -75,15 +75,15 @@ if (index < edges.getDirectCount()) { edges.setNode(node, index, value); } else { - edges.getNodeList(node, index).set(subIndex, value); + Edges.getNodeList(node, edges.getOffsets(), index).set(subIndex, value); } } public void initialize(Node node, Node value) { if (index < edges.getDirectCount()) { - edges.initializeNode(node, index, value); + Edges.initializeNode(node, edges.getOffsets(), index, value); } else { - edges.getNodeList(node, index).initialize(subIndex, value); + Edges.getNodeList(node, edges.getOffsets(), index).initialize(subIndex, value); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Feb 27 16:36:38 2015 +0100 @@ -251,7 +251,7 @@ /** * Computes the size of the memory chunk allocated for an array. This size accounts for the - * array header size, boy size and any padding after the last element to satisfy object + * array header size, body size and any padding after the last element to satisfy object * alignment requirements. * * @param length the number of elements in the array
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Feb 27 16:36:38 2015 +0100 @@ -179,7 +179,7 @@ private static class ExplodedLoopContext { private BciBlock header; - private int targetPeelIteration; + private int[] targetPeelIteration; private int peelIteration; } @@ -203,6 +203,8 @@ private FixedWithNextNode lastInstr; // the last instruction added private final boolean explodeLoops; + private final boolean mergeExplosions; + private final Map<HIRFrameStateBuilder, Integer> mergeExplosionsMap; private Stack<ExplodedLoopContext> explodeLoopsContext; private int nextPeelIteration = 1; private boolean controlFlowSplit; @@ -230,8 +232,17 @@ LoopExplosionPlugin loopExplosionPlugin = graphBuilderConfig.getLoopExplosionPlugin(); if (loopExplosionPlugin != null) { explodeLoops = loopExplosionPlugin.shouldExplodeLoops(method); + if (explodeLoops) { + mergeExplosions = loopExplosionPlugin.shouldMergeExplosions(method); + mergeExplosionsMap = new HashMap<>(); + } else { + mergeExplosions = false; + mergeExplosionsMap = null; + } } else { explodeLoops = false; + mergeExplosions = false; + mergeExplosionsMap = null; } } @@ -342,34 +353,49 @@ ExplodedLoopContext context = new ExplodedLoopContext(); context.header = header; context.peelIteration = this.getCurrentDimension(); - context.targetPeelIteration = -1; + if (this.mergeExplosions) { + this.addToMergeCache(getEntryState(context.header, context.peelIteration), context.peelIteration); + } explodeLoopsContext.push(context); if (Debug.isDumpEnabled() && DumpDuringGraphBuilding.getValue()) { Debug.dump(currentGraph, "before loop explosion dimension " + context.peelIteration); } + peelIteration(blocks, header, context); + explodeLoopsContext.pop(); + return header.loopEnd + 1; + } + + private void addToMergeCache(HIRFrameStateBuilder key, int dimension) { + mergeExplosionsMap.put(key, dimension); + } + + private void peelIteration(BciBlock[] blocks, BciBlock header, ExplodedLoopContext context) { while (true) { - processBlock(this, header); for (int j = header.getId() + 1; j <= header.loopEnd; ++j) { BciBlock block = blocks[j]; iterateBlock(blocks, block); } - if (context.targetPeelIteration != -1) { + int[] targets = context.targetPeelIteration; + if (targets != null) { // We were reaching the backedge during explosion. Explode further. - context.peelIteration = context.targetPeelIteration; - context.targetPeelIteration = -1; - if (Debug.isDumpEnabled() && DumpDuringGraphBuilding.getValue()) { - Debug.dump(currentGraph, "next loop explosion iteration " + context.peelIteration); + for (int i = 0; i < targets.length; ++i) { + context.peelIteration = targets[i]; + context.targetPeelIteration = null; + if (Debug.isDumpEnabled() && DumpDuringGraphBuilding.getValue()) { + Debug.dump(currentGraph, "next loop explosion iteration " + context.peelIteration); + } + if (i < targets.length - 1) { + peelIteration(blocks, header, context); + } } } else { // We did not reach the backedge. Exit. break; } } - explodeLoopsContext.pop(); - return header.loopEnd + 1; } /** @@ -1356,7 +1382,7 @@ assert block != null && state != null; assert !block.isExceptionEntry || state.stackSize() == 1; - int operatingDimension = findOperatingDimension(block); + int operatingDimension = findOperatingDimension(block, state); if (getFirstInstruction(block, operatingDimension) == null) { /* @@ -1401,8 +1427,8 @@ Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result); return result; } - assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch"; - assert getFirstInstruction(block, operatingDimension).next() == null : "bytecodes already parsed for block"; + assert currentBlock == null || currentBlock.getId() < block.getId() || this.mergeExplosions : "must not be backward branch"; + assert getFirstInstruction(block, operatingDimension).next() == null || this.mergeExplosions : "bytecodes already parsed for block"; if (getFirstInstruction(block, operatingDimension) instanceof AbstractBeginNode && !(getFirstInstruction(block, operatingDimension) instanceof AbstractMergeNode)) { /* @@ -1443,37 +1469,52 @@ return result; } - private int findOperatingDimension(BciBlock block) { + private int findOperatingDimension(BciBlock block, HIRFrameStateBuilder state) { if (this.explodeLoops && this.explodeLoopsContext != null && !this.explodeLoopsContext.isEmpty()) { - return findOperatingDimensionWithLoopExplosion(block); + return findOperatingDimensionWithLoopExplosion(block, state); } return this.getCurrentDimension(); } - private int findOperatingDimensionWithLoopExplosion(BciBlock block) { + private int findOperatingDimensionWithLoopExplosion(BciBlock block, HIRFrameStateBuilder state) { int i; for (i = explodeLoopsContext.size() - 1; i >= 0; --i) { ExplodedLoopContext context = explodeLoopsContext.elementAt(i); if (context.header == block) { + if (this.mergeExplosions) { + state.clearNonLiveLocals(block, liveness, true); + Integer cachedDimension = mergeExplosionsMap.get(state); + if (cachedDimension != null) { + return cachedDimension; + } + } + // We have a hit on our current explosion context loop begin. - if (context.targetPeelIteration == -1) { - // This is the first hit => allocate a new dimension and at the same - // time mark the context loop begin as hit during the current - // iteration. - context.targetPeelIteration = nextPeelIteration++; - if (nextPeelIteration > MaximumLoopExplosionCount.getValue()) { - String message = "too many loop explosion interations - does the explosion not terminate for method " + method + "?"; - if (FailedLoopExplosionIsFatal.getValue()) { - throw new RuntimeException(message); - } else { - throw bailout(message); - } + if (context.targetPeelIteration == null) { + context.targetPeelIteration = new int[1]; + } else { + context.targetPeelIteration = Arrays.copyOf(context.targetPeelIteration, context.targetPeelIteration.length + 1); + } + + // This is the first hit => allocate a new dimension and at the same + // time mark the context loop begin as hit during the current + // iteration. + if (this.mergeExplosions) { + this.addToMergeCache(state.copy(), nextPeelIteration); + } + context.targetPeelIteration[context.targetPeelIteration.length - 1] = nextPeelIteration++; + if (nextPeelIteration > MaximumLoopExplosionCount.getValue()) { + String message = "too many loop explosion interations - does the explosion not terminate for method " + method + "?"; + if (FailedLoopExplosionIsFatal.getValue()) { + throw new RuntimeException(message); + } else { + throw bailout(message); } } // Operate on the target dimension. - return context.targetPeelIteration; + return context.targetPeelIteration[context.targetPeelIteration.length - 1]; } else if (block.getId() > context.header.getId() && block.getId() <= context.header.loopEnd) { // We hit the range of this context. return context.peelIteration;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Fri Feb 27 16:36:38 2015 +0100 @@ -73,6 +73,8 @@ public interface LoopExplosionPlugin extends GraphBuilderPlugin { boolean shouldExplodeLoops(ResolvedJavaMethod method); + + boolean shouldMergeExplosions(ResolvedJavaMethod method); } public interface ParameterPlugin extends GraphBuilderPlugin {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Fri Feb 27 16:36:38 2015 +0100 @@ -873,4 +873,61 @@ assert xpeek() == null; return true; } + + @Override + public int hashCode() { + int result = hashCode(locals, locals.length); + result *= 13; + result += hashCode(stack, this.stackSize); + return result; + } + + private static int hashCode(Object[] a, int length) { + int result = 1; + for (int i = 0; i < length; ++i) { + Object element = a[i]; + result = 31 * result + (element == null ? 0 : System.identityHashCode(element)); + } + return result; + } + + private static boolean equals(ValueNode[] a, ValueNode[] b, int length) { + for (int i = 0; i < length; ++i) { + if (a[i] != b[i]) { + return false; + } + } + return true; + } + + @Override + public boolean equals(Object otherObject) { + if (otherObject instanceof HIRFrameStateBuilder) { + HIRFrameStateBuilder other = (HIRFrameStateBuilder) otherObject; + if (other.method != method) { + return false; + } + if (other.stackSize != stackSize) { + return false; + } + if (other.checkTypes != checkTypes) { + return false; + } + if (other.rethrowException != rethrowException) { + return false; + } + if (other.graph != graph) { + return false; + } + if (other.outerFrameStateSupplier != outerFrameStateSupplier) { + return false; + } + if (other.locals.length != locals.length) { + return false; + } + return equals(other.locals, locals, locals.length) && equals(other.stack, stack, stackSize) && equals(other.lockedObjects, lockedObjects, lockedObjects.length) && + equals(other.monitorIds, monitorIds, monitorIds.length); + } + return false; + } }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Fri Feb 27 16:36:38 2015 +0100 @@ -211,7 +211,7 @@ if (context.getGraphBuilderSuite() != null) { context.getGraphBuilderSuite().apply(newGraph, context); } - assert newGraph.start().next() != null : "graph needs to be populated by the GraphBuilderSuite"; + assert newGraph.start().next() != null : "graph needs to be populated by the GraphBuilderSuite " + method + ", " + method.canBeInlined(); new DeadCodeEliminationPhase(Optional).apply(newGraph);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Fri Feb 27 16:36:38 2015 +0100 @@ -441,11 +441,12 @@ private void writeEdges(Node node, Edges.Type type) throws IOException { NodeClass<?> nodeClass = node.getNodeClass(); Edges edges = nodeClass.getEdges(type); + final long[] curOffsets = edges.getOffsets(); for (int i = 0; i < edges.getDirectCount(); i++) { - writeNodeRef(edges.getNode(node, i)); + writeNodeRef(Edges.getNode(node, curOffsets, i)); } for (int i = edges.getDirectCount(); i < edges.getCount(); i++) { - NodeList<Node> list = edges.getNodeList(node, i); + NodeList<Node> list = Edges.getNodeList(node, curOffsets, i); if (list == null) { writeShort((char) 0); } else {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Fri Feb 27 16:36:38 2015 +0100 @@ -211,6 +211,8 @@ begin("block"); out.print("name \"").print(blockToString(block)).println('"'); + out.println("from_bci -1"); + out.println("to_bci -1"); out.print("predecessors "); for (AbstractBlockBase<?> pred : block.getPredecessors()) {
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java Fri Feb 27 16:36:38 2015 +0100 @@ -78,20 +78,20 @@ /** * Checks that there are no checkcasts in the compiled version of - * {@link Edges#getNode(Node, int)}. + * {@link Edges#getNode(Node, long[], int)}. */ @Test public void test0() { - testMethod(getMethod("getNode", Node.class, int.class), inputs, node, 0); + testMethod(getMethod("getNode", Node.class, long[].class, int.class), inputs, node, 0); } /** * Checks that there are no checkcasts in the compiled version of - * {@link Edges#getNodeList(Node, int)}. + * {@link Edges#getNodeList(Node, long[], int)}. */ @Test public void test1() { - testMethod(getMethod("getNodeList", Node.class, int.class), inputs, node, 2); + testMethod(getMethod("getNodeList", Node.class, long[].class, int.class), inputs, node, 2); } /**
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/EdgesSubstitutions.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/EdgesSubstitutions.java Fri Feb 27 16:36:38 2015 +0100 @@ -40,22 +40,12 @@ public class EdgesSubstitutions { @MethodSubstitution - private static Node getNode(Node node, long offset) { + private static Node getNodeUnsafe(Node node, long offset) { return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), Node.class); } @MethodSubstitution - private static NodeList<?> getNodeList(Node node, long offset) { + private static NodeList<?> getNodeListUnsafe(Node node, long offset) { return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), NodeList.class); } - - @MethodSubstitution - private static void putNode(Node node, long offset, Node value) { - UnsafeStoreNode.store(node, offset, value, Kind.Object, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution - private static void putNodeList(Node node, long offset, NodeList<?> value) { - UnsafeStoreNode.store(node, offset, value, Kind.Object, LocationIdentity.ANY_LOCATION); - } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/BytecodeInterpreterPartialEvaluationTest.java Fri Feb 27 16:36:38 2015 +0100 @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2015, 2015, 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.graal.truffle.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class BytecodeInterpreterPartialEvaluationTest extends PartialEvaluationTest { + + public static class Bytecode { + public static final byte CONST = 0; + public static final byte RETURN = 1; + public static final byte ADD = 2; + public static final byte IFZERO = 3; + public static final byte POP = 4; + public static final byte JMP = 5; + public static final byte DUP = 6; + } + + public static boolean TRACE = false; + + public static class Program extends RootNode { + private final String name; + @CompilationFinal private final byte[] bytecodes; + @CompilationFinal private final FrameSlot[] locals; + @CompilationFinal private final FrameSlot[] stack; + + public Program(String name, byte[] bytecodes, int maxLocals, int maxStack) { + this.name = name; + this.bytecodes = bytecodes; + locals = new FrameSlot[maxLocals]; + stack = new FrameSlot[maxStack]; + for (int i = 0; i < maxLocals; ++i) { + locals[i] = this.getFrameDescriptor().addFrameSlot("local" + i); + locals[i].setKind(FrameSlotKind.Int); + } + for (int i = 0; i < maxStack; ++i) { + stack[i] = this.getFrameDescriptor().addFrameSlot("stack" + i); + stack[i].setKind(FrameSlotKind.Int); + } + } + + protected void setInt(VirtualFrame frame, int stackIndex, int value) { + frame.setInt(stack[stackIndex], value); + } + + protected int getInt(VirtualFrame frame, int stackIndex) { + try { + return frame.getInt(stack[stackIndex]); + } catch (FrameSlotTypeException e) { + throw new IllegalStateException("Error accessing stack slot " + stackIndex); + } + } + + @Override + public String toString() { + return name; + } + + public void trace(String format, Object... args) { + if (CompilerDirectives.inInterpreter() && TRACE) { + System.out.println(String.format(format, args)); + } + } + + @Override + @ExplodeLoop(merge = true) + public Object execute(VirtualFrame frame) { + trace("Start program"); + int topOfStack = -1; + int bci = 0; + while (true) { + CompilerAsserts.partialEvaluationConstant(bci); + byte bc = bytecodes[bci]; + byte value = 0; + switch (bc) { + case Bytecode.CONST: + value = bytecodes[bci + 1]; + trace("%d: CONST %s", bci, value); + setInt(frame, ++topOfStack, value); + bci = bci + 2; + continue; + + case Bytecode.RETURN: + trace("%d: RETURN", bci); + return getInt(frame, topOfStack); + + case Bytecode.ADD: { + int left = getInt(frame, topOfStack); + int right = getInt(frame, topOfStack - 1); + trace("%d: ADD %d %d", bci, left, right); + setInt(frame, topOfStack - 1, left + right); + topOfStack--; + bci = bci + 1; + continue; + } + + case Bytecode.IFZERO: + trace("%d: IFZERO", bci); + if (getInt(frame, topOfStack--) == 0) { + bci = bytecodes[bci + 1]; + continue; + } else { + bci = bci + 2; + continue; + } + + case Bytecode.POP: + trace("%d: POP", bci); + topOfStack--; + bci++; + continue; + + case Bytecode.JMP: + trace("%d: JMP", bci); + bci = bytecodes[bci + 1]; + continue; + + case Bytecode.DUP: + trace("%d: DUP", bci); + setInt(frame, topOfStack + 1, getInt(frame, topOfStack)); + topOfStack++; + bci++; + continue; + } + } + } + } + + public static Object constant42() { + return 42; + } + + private static void assertReturns42(Program program) { + Assert.assertEquals(Integer.valueOf(42), Truffle.getRuntime().createCallTarget(program).call()); + } + + private void assertPartialEvalEqualsAndRunsCorrect(Program program) { + assertReturns42(program); + assertPartialEvalEquals("constant42", program); + } + + @Test + public void constReturnProgram() { + byte[] bytecodes = new byte[]{ + /* 0: */Bytecode.CONST, + /* 1: */42, + /* 2: */Bytecode.RETURN}; + assertPartialEvalEqualsAndRunsCorrect(new Program("constReturnProgram", bytecodes, 0, 2)); + } + + @Test + public void constAddProgram() { + byte[] bytecodes = new byte[]{ + /* 0: */Bytecode.CONST, + /* 1: */40, + /* 2: */Bytecode.CONST, + /* 3: */2, + /* 4: */Bytecode.ADD, + /* 5: */Bytecode.RETURN}; + assertPartialEvalEqualsAndRunsCorrect(new Program("constAddProgram", bytecodes, 0, 2)); + } + + @Test + public void simpleIfProgram() { + byte[] bytecodes = new byte[]{ + /* 0: */Bytecode.CONST, + /* 1: */40, + /* 2: */Bytecode.CONST, + /* 3: */1, + /* 4: */Bytecode.IFZERO, + /* 5: */8, + /* 6: */Bytecode.CONST, + /* 7: */42, + /* 8: */Bytecode.RETURN}; + assertPartialEvalEqualsAndRunsCorrect(new Program("simpleIfProgram", bytecodes, 0, 3)); + } + + @Test + public void ifAndPopProgram() { + byte[] bytecodes = new byte[]{ + /* 0: */Bytecode.CONST, + /* 1: */40, + /* 2: */Bytecode.CONST, + /* 3: */1, + /* 4: */Bytecode.IFZERO, + /* 5: */9, + /* 6: */Bytecode.POP, + /* 7: */Bytecode.CONST, + /* 8: */42, + /* 9: */Bytecode.RETURN}; + assertPartialEvalEqualsAndRunsCorrect(new Program("ifAndPopProgram", bytecodes, 0, 3)); + } + + @Test + @Ignore + public void simpleLoopProgram() { + byte[] bytecodes = new byte[]{ + /* 0: */Bytecode.CONST, + /* 1: */42, + /* 2: */Bytecode.CONST, + /* 3: */-12, + /* 4: */Bytecode.CONST, + /* 5: */1, + /* 6: */Bytecode.ADD, + /* 7: */Bytecode.DUP, + /* 8: */Bytecode.IFZERO, + /* 9: */12, + /* 10: */Bytecode.JMP, + /* 11: */4, + /* 12: */Bytecode.POP, + /* 13: */Bytecode.RETURN}; + assertPartialEvalEqualsAndRunsCorrect(new Program("ifAndPopProgram", bytecodes, 0, 3)); + } + + @Test(timeout = 1000) + public void manyIfsProgram() { + byte[] bytecodes = new byte[]{ + /* 0: */Bytecode.CONST, + /* 1: */40, + /* 2: */Bytecode.CONST, + /* 3: */1, + /* 4: */Bytecode.IFZERO, + /* 5: */8, + /* 6: */Bytecode.CONST, + /* 7: */1, + /* 8: */Bytecode.IFZERO, + /* 9: */12, + /* 10: */Bytecode.CONST, + /* 11: */1, + /* 12: */Bytecode.IFZERO, + /* 13: */16, + /* 14: */Bytecode.CONST, + /* 15: */1, + /* 16: */Bytecode.IFZERO, + /* 17: */20, + /* 18: */Bytecode.CONST, + /* 19: */1, + /* 20: */Bytecode.IFZERO, + /* 21: */24, + /* 22: */Bytecode.CONST, + /* 23: */1, + /* 24: */Bytecode.IFZERO, + /* 25: */28, + /* 26: */Bytecode.CONST, + /* 27: */1, + /* 28: */Bytecode.IFZERO, + /* 29: */32, + /* 30: */Bytecode.CONST, + /* 31: */1, + /* 32: */Bytecode.IFZERO, + /* 33: */36, + /* 34: */Bytecode.CONST, + /* 35: */1, + /* 36: */Bytecode.IFZERO, + /* 37: */40, + /* 38: */Bytecode.CONST, + /* 39: */1, + /* 40: */Bytecode.IFZERO, + /* 41: */44, + /* 42: */Bytecode.CONST, + /* 43: */42, + /* 44: */Bytecode.RETURN}; + assertPartialEvalEqualsAndRunsCorrect(new Program("manyIfsProgram", bytecodes, 0, 3)); + } +}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Fri Feb 27 16:36:38 2015 +0100 @@ -238,6 +238,14 @@ return method.getAnnotation(ExplodeLoop.class) != null; } + public boolean shouldMergeExplosions(ResolvedJavaMethod method) { + ExplodeLoop explodeLoop = method.getAnnotation(ExplodeLoop.class); + if (explodeLoop != null) { + return explodeLoop.merge(); + } + return false; + } + } @SuppressWarnings("unused") @@ -351,6 +359,13 @@ } } } + + if (!TruffleCompilerOptions.TruffleInlineAcrossTruffleBoundary.getValue()) { + // Do not inline across Truffle boundaries. + for (MethodCallTargetNode mct : graph.getNodes(MethodCallTargetNode.TYPE)) { + mct.invoke().setUseForInlining(false); + } + } } private void injectConstantCallTarget(final StructuredGraph graph, final OptimizedCallTarget constantCallTarget, PhaseContext baseContext) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Fri Feb 27 16:36:38 2015 +0100 @@ -43,7 +43,6 @@ import com.oracle.graal.lir.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; -import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; @@ -140,13 +139,6 @@ return; } - if (!TruffleCompilerOptions.TruffleInlineAcrossTruffleBoundary.getValue()) { - // Do not inline across Truffle boundaries. - for (MethodCallTargetNode mct : graph.getNodes(MethodCallTargetNode.TYPE)) { - mct.invoke().setUseForInlining(false); - } - } - compilationNotify.notifyCompilationTruffleTierFinished(compilable, graph); CompilationResult compilationResult = compileMethodHelper(graph, compilable.toString(), graphBuilderSuite, compilable.getSpeculationLog(), compilable); compilationNotify.notifyCompilationSuccess(compilable, graph, compilationResult);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Fri Feb 27 16:36:38 2015 +0100 @@ -186,6 +186,22 @@ return true; } }); + + r = new Registration(plugins, metaAccess, CompilerAsserts.class); + r.register1("partialEvaluationConstant", Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + ValueNode curValue = value; + if (curValue instanceof BoxNode) { + BoxNode boxNode = (BoxNode) curValue; + curValue = boxNode.getValue(); + } + if (curValue.isConstant()) { + return true; + } else { + throw builder.bailout("Partial evaluation did not reduce value to a constant, is a regular compiler node: " + curValue); + } + } + }); } public static void registerOptimizedCallTargetPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins) {
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerAsserts.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerAsserts.java Fri Feb 27 16:36:38 2015 +0100 @@ -64,4 +64,13 @@ neverPartOfCompilation("Value is not compilation constant"); } } + + /** + * Assertion that the corresponding value is reduced to a constant during the initial partial + * evaluation phase. + * + * @param value the value that must be constant during compilation + */ + public static <T> void partialEvaluationConstant(Object value) { + } }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExplodeLoop.java Fri Feb 27 14:57:27 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ExplodeLoop.java Fri Feb 27 16:36:38 2015 +0100 @@ -33,4 +33,5 @@ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ExplodeLoop { + boolean merge() default false; }