Mercurial > hg > truffle
changeset 17210:ef64e2682bb6
added Edges class to consolidate code operating on set of input or successor edges and to better isolate magic used to access edges
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NodePosIteratorTest.java Thu Sep 25 10:27:17 2014 +0200 @@ -0,0 +1,220 @@ +/* + * 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.graal.compiler.test; + +import org.junit.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + +public class NodePosIteratorTest extends GraalCompilerTest { + + @NodeInfo + static class TestNode extends Node { + @Successor Node s1; + @Successor Node s2; + @Successor NodeSuccessorList<Node> stail; + + @Input NodeInputList<ValueNode> itail; + @Input ConstantNode i1; + @Input FloatingNode i2; + + public static TestNode create() { + return USE_GENERATED_NODES ? new NodePosIteratorTest_TestNodeGen() : new TestNode(); + } + } + + @Test + public void testInputs() { + TestNode n = TestNode.create(); + + ConstantNode i1 = ConstantNode.forInt(1); + ConstantNode i2 = ConstantNode.forDouble(1.0d); + ConstantNode i3 = ConstantNode.forInt(4); + ConstantNode i4 = ConstantNode.forInt(14); + n.itail = new NodeInputList<>(n, new ValueNode[]{i3, i4}); + n.i1 = i1; + n.i2 = i2; + + NodeClassIterable inputs = n.inputs(); + + NodePosIterator iterator = inputs.iterator(); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), i1); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), i2); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), i3); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), i4); + Assert.assertFalse(iterator.hasNext()); + Assert.assertFalse(iterator.hasNext()); + + iterator = inputs.iterator(); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals("ConstantNode:i1", iterator.nextPosition().toString()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals("FloatingNode:i2", iterator.nextPosition().toString()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals("NodeInputList:itail[0]", iterator.nextPosition().toString()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals("NodeInputList:itail[1]", iterator.nextPosition().toString()); + Assert.assertFalse(iterator.hasNext()); + Assert.assertFalse(iterator.hasNext()); + + iterator = inputs.iterator(); + n.i1 = i4; + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), i4); + n.i2 = i1; + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), i1); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), i3); + n.itail.initialize(1, i4); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), i4); + Assert.assertFalse(iterator.hasNext()); + + iterator = inputs.iterator(); + n.i1 = null; + n.i2 = i2; + n.itail.initialize(0, null); + n.itail.initialize(1, i4); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), i2); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), i4); + Assert.assertFalse(iterator.hasNext()); + + iterator = inputs.withNullIterator(); + n.i1 = null; + n.i2 = null; + n.itail.initialize(0, i3); + n.itail.initialize(1, null); + Assert.assertTrue(iterator.hasNext()); + Assert.assertNull(iterator.next()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertNull(iterator.next()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), i3); + Assert.assertTrue(iterator.hasNext()); + Assert.assertNull(iterator.next()); + Assert.assertFalse(iterator.hasNext()); + } + + @Test + public void testSuccessors() { + TestNode n = TestNode.create(); + EndNode s1 = EndNode.create(); + EndNode s2 = EndNode.create(); + EndNode s3 = EndNode.create(); + EndNode s4 = EndNode.create(); + n.s1 = s1; + n.s2 = s2; + n.stail = new NodeSuccessorList<>(n, new Node[]{s3, s4}); + + NodeClassIterable successors = n.successors(); + NodePosIterator iterator = successors.iterator(); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), s1); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), s2); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), s3); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), s4); + Assert.assertFalse(iterator.hasNext()); + Assert.assertFalse(iterator.hasNext()); + + iterator = successors.iterator(); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(Node.class.getSimpleName() + ":s1", iterator.nextPosition().toString()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(Node.class.getSimpleName() + ":s2", iterator.nextPosition().toString()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(NodeSuccessorList.class.getSimpleName() + ":stail[0]", iterator.nextPosition().toString()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(NodeSuccessorList.class.getSimpleName() + ":stail[1]", iterator.nextPosition().toString()); + Assert.assertFalse(iterator.hasNext()); + Assert.assertFalse(iterator.hasNext()); + + iterator = successors.iterator(); + n.s1 = s4; + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), s4); + n.s2 = s1; + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), s1); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), s3); + n.stail.initialize(1, s4); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), s4); + Assert.assertFalse(iterator.hasNext()); + + iterator = successors.iterator(); + n.s1 = null; + n.s2 = s2; + n.stail.initialize(0, null); + n.stail.initialize(1, s4); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), s2); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), s4); + Assert.assertFalse(iterator.hasNext()); + + iterator = successors.withNullIterator(); + n.s1 = null; + n.s2 = null; + n.stail.initialize(0, s3); + n.stail.initialize(1, null); + Assert.assertTrue(iterator.hasNext()); + Assert.assertNull(iterator.next()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertNull(iterator.next()); + Assert.assertTrue(iterator.hasNext()); + Assert.assertEquals(iterator.next(), s3); + Assert.assertTrue(iterator.hasNext()); + Assert.assertNull(iterator.next()); + Assert.assertFalse(iterator.hasNext()); + } +}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/NodeRefIteratorTest.java Wed Sep 24 17:17:27 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,219 +0,0 @@ -/* - * 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.graal.compiler.test; - -import org.junit.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; - -public class NodeRefIteratorTest extends GraalCompilerTest { - - @NodeInfo - static class TestNode extends Node { - @Successor Node s1; - @Successor Node s2; - @Successor NodeSuccessorList<Node> stail; - - @Input NodeInputList<ValueNode> itail; - @Input ValueNode i1; - @Input ValueNode i2; - - public static TestNode create() { - return USE_GENERATED_NODES ? new NodeRefIteratorTest_TestNodeGen() : new TestNode(); - } - } - - @Test - public void testInputs() { - TestNode n = TestNode.create(); - - ConstantNode i1 = ConstantNode.forInt(1); - ConstantNode i2 = ConstantNode.forDouble(1.0d); - ConstantNode i3 = ConstantNode.forInt(4); - ConstantNode i4 = ConstantNode.forInt(14); - n.itail = new NodeInputList<>(n, new ValueNode[]{i3, i4}); - n.i1 = i1; - n.i2 = i2; - - NodeClassIterable inputs = n.inputs(); - - NodePosIterator iterator = inputs.iterator(); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), i1); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), i2); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), i3); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), i4); - Assert.assertFalse(iterator.hasNext()); - Assert.assertFalse(iterator.hasNext()); - - iterator = inputs.iterator(); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.nextPosition().toString(), "input 0/-1"); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.nextPosition().toString(), "input 1/-1"); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.nextPosition().toString(), "input 2/0"); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.nextPosition().toString(), "input 2/1"); - Assert.assertFalse(iterator.hasNext()); - Assert.assertFalse(iterator.hasNext()); - - iterator = inputs.iterator(); - n.i1 = i4; - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), i4); - n.i2 = i1; - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), i1); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), i3); - n.itail.initialize(1, i4); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), i4); - Assert.assertFalse(iterator.hasNext()); - - iterator = inputs.iterator(); - n.i1 = null; - n.i2 = i2; - n.itail.initialize(0, null); - n.itail.initialize(1, i4); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), i2); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), i4); - Assert.assertFalse(iterator.hasNext()); - - iterator = inputs.withNullIterator(); - n.i1 = null; - n.i2 = null; - n.itail.initialize(0, i3); - n.itail.initialize(1, null); - Assert.assertTrue(iterator.hasNext()); - Assert.assertNull(iterator.next()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertNull(iterator.next()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), i3); - Assert.assertTrue(iterator.hasNext()); - Assert.assertNull(iterator.next()); - Assert.assertFalse(iterator.hasNext()); - } - - @Test - public void testSuccessors() { - TestNode n = TestNode.create(); - EndNode s1 = EndNode.create(); - EndNode s2 = EndNode.create(); - EndNode s3 = EndNode.create(); - EndNode s4 = EndNode.create(); - n.s1 = s1; - n.s2 = s2; - n.stail = new NodeSuccessorList<>(n, new Node[]{s3, s4}); - - NodeClassIterable successors = n.successors(); - NodePosIterator iterator = successors.iterator(); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), s1); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), s2); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), s3); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), s4); - Assert.assertFalse(iterator.hasNext()); - Assert.assertFalse(iterator.hasNext()); - - iterator = successors.iterator(); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.nextPosition().toString(), "successor 0/-1"); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.nextPosition().toString(), "successor 1/-1"); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.nextPosition().toString(), "successor 2/0"); - Assert.assertTrue(iterator.hasNext()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.nextPosition().toString(), "successor 2/1"); - Assert.assertFalse(iterator.hasNext()); - Assert.assertFalse(iterator.hasNext()); - - iterator = successors.iterator(); - n.s1 = s4; - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), s4); - n.s2 = s1; - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), s1); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), s3); - n.stail.initialize(1, s4); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), s4); - Assert.assertFalse(iterator.hasNext()); - - iterator = successors.iterator(); - n.s1 = null; - n.s2 = s2; - n.stail.initialize(0, null); - n.stail.initialize(1, s4); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), s2); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), s4); - Assert.assertFalse(iterator.hasNext()); - - iterator = successors.withNullIterator(); - n.s1 = null; - n.s2 = null; - n.stail.initialize(0, s3); - n.stail.initialize(1, null); - Assert.assertTrue(iterator.hasNext()); - Assert.assertNull(iterator.next()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertNull(iterator.next()); - Assert.assertTrue(iterator.hasNext()); - Assert.assertEquals(iterator.next(), s3); - Assert.assertTrue(iterator.hasNext()); - Assert.assertNull(iterator.next()); - Assert.assertFalse(iterator.hasNext()); - } -}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/match/MatchRuleRegistry.java Thu Sep 25 10:27:17 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.compiler.match; import static com.oracle.graal.compiler.GraalDebugConfig.*; +import static com.oracle.graal.graph.Edges.Type.*; import java.util.*; import java.util.Map.Entry; @@ -65,11 +66,10 @@ Position[] result = new Position[names.length]; NodeClass nodeClass = lookup.get(theClass); for (int i = 0; i < names.length; i++) { - for (Position position : nodeClass.getFirstLevelInputPositions()) { - String name = nodeClass.getName(position); - if (name.equals(names[i])) { - result[i] = position; - break; + Edges edges = nodeClass.getEdges(Inputs); + for (int e = 0; e < edges.getDirectCount(); e++) { + if (names[i].equals(edges.getName(e))) { + result[i] = new Position(edges, e, Node.NOT_ITERABLE); } } if (result[i] == null) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java Thu Sep 25 10:27:17 2014 +0200 @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2014, 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; + +import static com.oracle.graal.compiler.common.UnsafeAccess.*; +import static com.oracle.graal.graph.Graph.*; +import static com.oracle.graal.graph.Node.*; + +import java.util.*; + +/** + * Describes {@link Node} fields representing the set of inputs for the node or the set of the + * node's successors. + */ +public abstract class Edges { + + /** + * Constants denoting whether a set of edges are inputs or successors. + */ + public enum Type { + Inputs, + Successors; + } + + private final Class<? extends Node> nodeClass; + private final int directCount; + private final long[] offsets; + private final String[] names; + private final Class<?>[] types; + private final Type type; + + @SuppressWarnings("unchecked") + public Edges(Class<?> nodeClass, Type type, int directCount, long[] offsets, Map<Long, String> names, Map<Long, Class<?>> types) { + this.nodeClass = (Class<? extends Node>) nodeClass; + this.type = type; + this.directCount = directCount; + this.offsets = offsets; + + this.names = new String[offsets.length]; + this.types = new Class[offsets.length]; + for (int i = 0; i < offsets.length; i++) { + this.names[i] = names.get(offsets[i]); + this.types[i] = types.get(offsets[i]); + } + } + + /** + * Gets the number of edges represented by this object. + */ + public int getCount() { + return offsets.length; + } + + /** + * Get the number of direct edges represented by this object. A direct edge goes directly to + * another {@link Node}. An indirect edge goes via a {@link NodeList}. + */ + public int getDirectCount() { + return directCount; + } + + private static Node getNode(Node node, long offset) { + return (Node) unsafe.getObject(node, offset); + } + + @SuppressWarnings("unchecked") + private static NodeList<Node> getNodeList(Node node, long offset) { + return (NodeList<Node>) unsafe.getObject(node, offset); + } + + private static void putNode(Node node, long offset, Node value) { + unsafe.putObject(node, offset, value); + } + + private static void putNodeList(Node node, long offset, NodeList<?> value) { + unsafe.putObject(node, offset, value); + } + + /** + * Gets the {@link Node} at the end point of a {@linkplain #getDirectCount() direct} edge. + * + * @param node one end point of the edge + * @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]); + } + + /** + * Gets the {@link NodeList} at the end point of a {@linkplain #getDirectCount() direct} edge. + * + * @param node one end point of the edge + * @param index the index of a non-list the edge (must be equal to or greater than + * {@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 < offsets.length; + return getNodeList(node, offsets[index]); + } + + /** + * Clear edges in a given node. This is accomplished by setting {@linkplain #getDirectCount() + * direct} edges to null and replacing the lists containing indirect edges with new lists. The + * latter is important so that this method can be used to clear the edges of cloned nodes. + * + * @param node the node whose edges are to be cleared + */ + public void clear(Node node) { + int index = 0; + while (index < getDirectCount()) { + initializeNode(node, index++, null); + } + while (index < getCount()) { + NodeList<Node> list = getNodeList(node, index); + int size = list.initialSize; + NodeList<Node> newList = type == 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); + index++; + } + } + + /** + * Copies edges from {@code fromNode} to {@code toNode}. The nodes are expected to be of the + * exact same type. + * + * @param fromNode the node from which the edges should be copied. + * @param toNode the node to which the edges should be copied. + */ + public void copy(Node fromNode, Node toNode) { + assert fromNode.getNodeClass().getClazz() == nodeClass && toNode.getNodeClass().getClazz() == nodeClass; + int index = 0; + while (index < getDirectCount()) { + initializeNode(toNode, index, getNode(fromNode, index)); + index++; + } + while (index < getCount()) { + NodeList<Node> list = getNodeList(toNode, index); + list.copy(getNodeList(fromNode, index)); + index++; + } + } + + /** + * Searches for the first edge in a given node matching {@code key} and if found, replaces it + * with {@code replacement}. + * + * @param node the node whose edges are to be searched + * @param key the edge to search for + * @param replacement the replacement for {@code key} + * @return true if a replacement was made + */ + public boolean replaceFirst(Node node, Node key, Node replacement) { + int index = 0; + while (index < getDirectCount()) { + Node edge = getNode(node, 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); + return true; + } + index++; + } + while (index < getCount()) { + NodeList<Node> list = getNodeList(node, index); + assert list != null : nodeClass; + if (list.replaceFirst(key, replacement)) { + return true; + } + index++; + } + return false; + } + + public boolean isSameEdge(Edges other, int index) { + return offsets[index] == other.offsets[index]; + } + + /** + * Gets the name of an edge. + * + * @param index index of an edge + */ + public String getName(int index) { + return names[index]; + } + + /** + * Gets the type of the field storing the end point of an edge. + * + * @param index index of an edge + */ + public Class<?> getType(int index) { + return types[index]; + } + + private boolean checkAssignable(int index, Node value) { + assert value == null || getType(index).isAssignableFrom(value.getClass()) : String.format("%s.%s of type %s is not assignable from %s", nodeClass.getSimpleName(), getName(index), + getType(index).getSimpleName(), value.getClass().getSimpleName()); + return true; + } + + public void initializeNode(Node node, int index, Node value) { + assert checkAssignable(index, value); + putNode(node, offsets[index], value); + } + + public void initializeList(Node node, int index, NodeList<Node> value) { + assert index >= directCount; + putNodeList(node, offsets[index], value); + } + + public void setNode(Node node, int index, Node value) { + assert index < directCount; + long offset = offsets[index]; + Node old = getNode(node, offset); + assert checkAssignable(index, value); + putNode(node, offset, value); + update(node, old, value); + } + + protected abstract void update(Node node, Node oldValue, Node newValue); + + public boolean contains(Node node, Node value) { + for (int i = 0; i < directCount; i++) { + if (getNode(node, i) == value) { + return true; + } + } + for (int i = directCount; i < getCount(); i++) { + if (getNodeList(node, i).contains(value)) { + return true; + } + } + return false; + } + + /** + * Determines if the edges of two given nodes are the same. + */ + public boolean areEqualIn(Node node, Node other) { + assert node.getNodeClass().getClazz() == nodeClass && other.getNodeClass().getClazz() == nodeClass; + int index = 0; + while (index < directCount) { + if (getNode(other, index) != getNode(node, index)) { + return false; + } + index++; + } + while (index < getCount()) { + NodeList<Node> list = getNodeList(other, index); + if (!list.equals(getNodeList(node, index))) { + return false; + } + index++; + } + return true; + } + + /** + * An iterator that will iterate over edges. + * + * An iterator of this type will not return null values, unless edges are modified concurrently. + * Concurrent modifications are detected by an assertion on a best-effort basis. + */ + private static class EdgesIterator implements NodePosIterator { + protected final Node node; + protected final Edges edges; + protected int index; + protected int subIndex; + NodeList<Node> list; + protected boolean needsForward; + protected Node nextElement; + + /** + * Creates an iterator that will iterate over some given edges in a given node. + */ + EdgesIterator(Node node, Edges edges) { + this.node = node; + this.edges = edges; + index = NOT_ITERABLE; + subIndex = 0; + needsForward = true; + } + + void forward() { + needsForward = false; + if (index < edges.getDirectCount()) { + index++; + while (index < edges.getDirectCount()) { + nextElement = edges.getNode(node, index); + if (nextElement != null) { + return; + } + index++; + } + } else { + subIndex++; + } + while (index < edges.getCount()) { + if (subIndex == 0) { + list = edges.getNodeList(node, index); + } + while (subIndex < list.size()) { + nextElement = list.get(subIndex); + if (nextElement != null) { + return; + } + subIndex++; + } + subIndex = 0; + index++; + } + } + + private Node nextElement() { + if (needsForward) { + forward(); + } + needsForward = true; + if (index < edges.getCount()) { + return nextElement; + } + throw new NoSuchElementException(); + } + + @Override + public boolean hasNext() { + if (needsForward) { + forward(); + } + return index < edges.getCount(); + } + + @Override + public Node next() { + return nextElement(); + } + + public Position nextPosition() { + if (needsForward) { + forward(); + } + needsForward = true; + if (index < edges.getDirectCount()) { + return new Position(edges, index, NOT_ITERABLE); + } else { + return new Position(edges, index, subIndex); + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + private static class AllEdgesIterator extends EdgesIterator { + AllEdgesIterator(Node node, Edges edges) { + super(node, edges); + } + + @Override + void forward() { + needsForward = false; + if (index < edges.getDirectCount()) { + index++; + if (index < edges.getDirectCount()) { + nextElement = edges.getNode(node, index); + return; + } + } else { + subIndex++; + } + while (index < edges.getCount()) { + if (subIndex == 0) { + list = edges.getNodeList(node, index); + } + if (subIndex < list.size()) { + nextElement = list.get(subIndex); + return; + } + subIndex = 0; + index++; + } + } + } + + private static final class EdgesWithModCountIterator extends EdgesIterator { + private final int modCount; + + private EdgesWithModCountIterator(Node node, Edges edges) { + super(node, edges); + assert MODIFICATION_COUNTS_ENABLED; + this.modCount = node.modCount(); + } + + @Override + public boolean hasNext() { + try { + return super.hasNext(); + } finally { + assert modCount == node.modCount() : "must not be modified"; + } + } + + @Override + public Node next() { + try { + return super.next(); + } finally { + assert modCount == node.modCount() : "must not be modified"; + } + } + + @Override + public Position nextPosition() { + try { + return super.nextPosition(); + } finally { + assert modCount == node.modCount(); + } + } + } + + public NodeClassIterable getIterable(final Node node) { + return new NodeClassIterable() { + + @Override + public EdgesIterator iterator() { + if (MODIFICATION_COUNTS_ENABLED) { + return new EdgesWithModCountIterator(node, Edges.this); + } else { + return new EdgesIterator(node, Edges.this); + } + } + + public EdgesIterator withNullIterator() { + return new AllEdgesIterator(node, Edges.this); + } + + @Override + public boolean contains(Node other) { + return Edges.this.contains(node, other); + } + }; + } + + public Type type() { + return type; + } + + @Override + public String toString() { + return nodeClass.getSimpleName() + ":" + type; + } + + void appendOffsets(StringBuilder sb) { + for (int i = 0; i < offsets.length; i++) { + sb.append(i == 0 ? "" : ", ").append(offsets[i]); + } + } +}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FirstLevelPositionCollection.java Wed Sep 24 17:17:27 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2014, 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; - -import static com.oracle.graal.graph.Node.*; - -import java.util.*; - -import com.oracle.graal.graph.Node.Input; -import com.oracle.graal.graph.Node.Successor; - -/** - * A collection of the positions of the {@link Node} and {@link NodeList} fields in a node. - */ -public final class FirstLevelPositionCollection extends AbstractCollection<Position> implements Collection<Position> { - - public static final FirstLevelPositionCollection Empty = new FirstLevelPositionCollection(0, 0, false); - - /** - * The total number of {@link Node} and {@link NodeList} fields. - */ - protected final int allNodeRefFields; - - /** - * The number of {@link Node} fields. - */ - protected final int nodeFields; - - /** - * Specifies if this iterator iterates over {@linkplain Input inputs} or {@linkplain Successor - * successors}. - */ - private final boolean isInputs; - - /** - * Creates a collection of the positions of the {@link Node} and {@link NodeList} fields in a - * node. - */ - public FirstLevelPositionCollection(int nodeFields, int nodeListFields, boolean isInputs) { - this.allNodeRefFields = nodeListFields + nodeFields; - this.nodeFields = nodeFields; - this.isInputs = isInputs; - } - - @Override - public int size() { - return allNodeRefFields; - } - - @Override - public Iterator<Position> iterator() { - return new FirstLevelPositionIterator(nodeFields, allNodeRefFields - nodeFields, isInputs); - } -}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/FirstLevelPositionIterator.java Wed Sep 24 17:17:27 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2014, 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; - -import static com.oracle.graal.graph.Node.*; - -import java.util.*; - -import com.oracle.graal.graph.Node.Input; -import com.oracle.graal.graph.Node.Successor; - -/** - * An iterator over the {@link Node} and {@link NodeList} fields in a node. - */ -public class FirstLevelPositionIterator implements Iterator<Position> { - - public static final FirstLevelPositionIterator Empty = new FirstLevelPositionIterator(0, 0, false); - - /** - * The total number of {@link Node} and {@link NodeList} fields. - */ - protected final int allNodeRefFields; - - /** - * The number of {@link Node} fields. - */ - protected final int nodeFields; - - /** - * Specifies if this iterator iterates over {@linkplain Input inputs} or {@linkplain Successor - * successors}. - */ - private final boolean isInputs; - - /** - * Current field iteration index. - */ - protected int index; - - /** - * Creates an iterator over the {@link Node} and {@link NodeList} fields in a node. - * - * @param nodeFields the number of {@link Node} fields in the class hierarchy of the node being - * iterated - * @param nodeListFields the number of {@link NodeList} fields in the class hierarchy of the - * node being iterated - */ - protected FirstLevelPositionIterator(int nodeFields, int nodeListFields, boolean isInputs) { - this.allNodeRefFields = nodeListFields + nodeFields; - this.nodeFields = nodeFields; - this.isInputs = isInputs; - index = Node.NOT_ITERABLE; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - public Position next() { - Position pos = new Position(isInputs, index, index >= nodeFields ? NODE_LIST : NOT_ITERABLE); - index++; - return pos; - } - - public boolean hasNext() { - return index < allNodeRefFields; - } - - public int size() { - return allNodeRefFields; - } -}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Thu Sep 25 10:27:17 2014 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.graph; +import static com.oracle.graal.graph.Edges.Type.*; import static com.oracle.graal.graph.Node.*; import java.util.*; @@ -497,7 +498,8 @@ } if (minCountNode != null) { for (Node usage : minCountNode.usages()) { - if (usage != node && nodeClass == usage.getNodeClass() && nodeClass.valueEqual(node, usage) && nodeClass.edgesEqual(node, usage)) { + if (usage != node && nodeClass == usage.getNodeClass() && nodeClass.valueEqual(node, usage) && nodeClass.getEdges(Inputs).areEqualIn(node, usage) && + nodeClass.getEdges(Successors).areEqualIn(node, usage)) { return usage; } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputEdges.java Thu Sep 25 10:27:17 2014 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, 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; + +import static com.oracle.graal.graph.Edges.Type.*; + +import java.util.*; + +import com.oracle.graal.nodeinfo.*; + +public final class InputEdges extends Edges { + + private final InputType[] inputTypes; + private final boolean[] isOptional; + + public InputEdges(Class<?> nodeClass, int directCount, long[] offsets, Map<Long, String> names, Map<Long, Class<?>> types, Map<Long, InputType> inputTypes, Set<Long> isOptional) { + super(nodeClass, Inputs, directCount, offsets, names, types); + + this.inputTypes = new InputType[offsets.length]; + this.isOptional = new boolean[offsets.length]; + for (int i = 0; i < offsets.length; i++) { + this.inputTypes[i] = inputTypes.get(offsets[i]); + this.isOptional[i] = isOptional.contains(offsets[i]); + } + } + + public InputType getInputType(int index) { + return inputTypes[index]; + } + + public boolean isOptional(int index) { + return isOptional[index]; + } + + @Override + protected void update(Node node, Node oldValue, Node newValue) { + node.updateUsages(oldValue, newValue); + } +}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Thu Sep 25 10:27:17 2014 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.graph; +import static com.oracle.graal.graph.Edges.Type.*; import static com.oracle.graal.graph.Graph.*; import java.lang.annotation.*; @@ -196,7 +197,7 @@ * @return an {@link NodeClassIterable iterable} for all non-null input edges. */ public NodeClassIterable inputs() { - return getNodeClass().getInputIterable(this); + return getNodeClass().getEdges(Inputs).getIterable(this); } /** @@ -206,7 +207,7 @@ * @return an {@link NodeClassIterable iterable} for all non-null successor edges. */ public NodeClassIterable successors() { - return getNodeClass().getSuccessorIterable(this); + return getNodeClass().getEdges(Successors).getIterable(this); } /** @@ -545,7 +546,7 @@ public void replaceAtUsages(Node other) { assert checkReplaceWith(other); for (Node usage : usages()) { - boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); + boolean result = usage.getNodeClass().getEdges(Inputs).replaceFirst(usage, this, other); assert assertTrue(result, "not found in inputs, usage: %s", usage); if (other != null) { maybeNotifyInputChanged(usage); @@ -565,7 +566,7 @@ if (removeStart < 0) { removeStart = it.index - 1; } - boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); + boolean result = usage.getNodeClass().getEdges(Inputs).replaceFirst(usage, this, other); assert assertTrue(result, "not found in inputs, usage: %s", usage); if (other != null) { maybeNotifyInputChanged(usage); @@ -593,7 +594,7 @@ NodePosIterator iter = usage.inputs().iterator(); while (iter.hasNext()) { Position pos = iter.nextPosition(); - if (pos.getInputType(usage) == type && pos.get(usage) == this) { + if (pos.getInputType() == type && pos.get(usage) == this) { pos.set(usage, other); } } @@ -623,7 +624,7 @@ public void replaceAtPredecessor(Node other) { assert checkReplaceWith(other); if (predecessor != null) { - boolean result = predecessor.getNodeClass().replaceFirstSuccessor(predecessor, this, other); + boolean result = predecessor.getNodeClass().getEdges(Successors).replaceFirst(predecessor, this, other); assert assertTrue(result, "not found in successors, predecessor: %s", predecessor); predecessor.updatePredecessor(this, other); } @@ -640,13 +641,13 @@ } public void replaceFirstSuccessor(Node oldSuccessor, Node newSuccessor) { - if (getNodeClass().replaceFirstSuccessor(this, oldSuccessor, newSuccessor)) { + if (getNodeClass().getEdges(Successors).replaceFirst(this, oldSuccessor, newSuccessor)) { updatePredecessor(oldSuccessor, newSuccessor); } } public void replaceFirstInput(Node oldInput, Node newInput) { - if (getNodeClass().replaceFirstInput(this, oldInput, newInput)) { + if (getNodeClass().getEdges(Inputs).replaceFirst(this, oldInput, newInput)) { updateUsages(oldInput, newInput); } } @@ -664,7 +665,7 @@ assert assertFalse(isDeleted(), "cannot clear inputs of deleted node"); unregisterInputs(); - getNodeClass().clearInputs(this); + getNodeClass().getEdges(Inputs).clear(this); } private boolean removeThisFromUsages(Node n) { @@ -682,7 +683,7 @@ assert assertFalse(isDeleted(), "cannot clear successors of deleted node"); unregisterSuccessors(); - getNodeClass().clearSuccessors(this); + getNodeClass().getEdges(Successors).clear(this); } private boolean checkDeletion() { @@ -711,7 +712,7 @@ public final Node copyWithInputs(boolean addToGraph) { Node newNode = clone(addToGraph ? graph : null); NodeClass clazz = getNodeClass(); - clazz.copyInputs(this, newNode); + clazz.getEdges(Inputs).copy(this, newNode); if (addToGraph) { for (Node input : inputs()) { input.addUsage(newNode); @@ -751,8 +752,8 @@ throw new GraalGraphInternalError(e).addContext(this); } if (clearInputsAndSuccessors) { - nodeClass.clearInputs(newNode); - nodeClass.clearSuccessors(newNode); + nodeClass.getEdges(Inputs).clear(newNode); + nodeClass.getEdges(Successors).clear(newNode); } newNode.graph = into; newNode.typeCacheNext = null; @@ -798,15 +799,15 @@ NodePosIterator iterator = usage.inputs().iterator(); while (iterator.hasNext()) { Position pos = iterator.nextPosition(); - if (pos.get(usage) == this && pos.getInputType(usage) != InputType.Unchecked) { - assert isAllowedUsageType(pos.getInputType(usage)) : "invalid input of type " + pos.getInputType(usage) + " from " + usage + " to " + this + " (" + pos.getInputName(usage) + ")"; + if (pos.get(usage) == this && pos.getInputType() != InputType.Unchecked) { + assert isAllowedUsageType(pos.getInputType()) : "invalid input of type " + pos.getInputType() + " from " + usage + " to " + this + " (" + pos.getName() + ")"; } } } NodePosIterator iterator = inputs().withNullIterator(); while (iterator.hasNext()) { Position pos = iterator.nextPosition(); - assert pos.isInputOptional(this) || pos.get(this) != null : "non-optional input " + pos.getInputName(this) + " cannot be null in " + this + " (fix nullness or use @OptionalInput)"; + assert pos.isInputOptional() || pos.get(this) != null : "non-optional input " + pos.getName() + " cannot be null in " + this + " (fix nullness or use @OptionalInput)"; } if (predecessor != null) { assertFalse(predecessor.isDeleted(), "predecessor %s must never be deleted", predecessor); @@ -943,7 +944,6 @@ boolean neighborsAlternate = ((flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags.LEFT_JUSTIFY); int neighborsFlags = (neighborsAlternate ? FormattableFlags.ALTERNATE | FormattableFlags.LEFT_JUSTIFY : 0); - NodeClass nodeClass = getNodeClass(); if (width > 0) { if (this.predecessor != null) { formatter.format(" pred={"); @@ -954,10 +954,10 @@ NodePosIterator inputIter = inputs().iterator(); while (inputIter.hasNext()) { Position position = inputIter.nextPosition(); - Node input = nodeClass.get(this, position); + Node input = position.get(this); if (input != null) { formatter.format(" "); - formatter.format(nodeClass.getName(position)); + formatter.format(position.getName()); formatter.format("={"); input.formatTo(formatter, neighborsFlags, width - 1, 0); formatter.format("}"); @@ -982,10 +982,10 @@ NodePosIterator succIter = successors().iterator(); while (succIter.hasNext()) { Position position = succIter.nextPosition(); - Node successor = nodeClass.get(this, position); + Node successor = position.get(this); if (successor != null) { formatter.format(" "); - formatter.format(nodeClass.getName(position)); + formatter.format(position.getName()); formatter.format("={"); successor.formatTo(formatter, neighborsFlags, 0, precision - 1); formatter.format("}");
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Thu Sep 25 10:27:17 2014 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.graph; -import static com.oracle.graal.graph.Graph.*; import static com.oracle.graal.graph.Node.*; import static com.oracle.graal.graph.util.CollectionsAccess.*; import static java.lang.reflect.Modifier.*; @@ -54,7 +53,8 @@ // Timers for creation of a NodeClass instance private static final DebugTimer Init = Debug.timer("NodeClass.Init"); private static final DebugTimer Init_FieldScanning = Debug.timer("NodeClass.Init.FieldScanning"); - private static final DebugTimer Init_Offsets = Debug.timer("NodeClass.Init.Offsets"); + private static final DebugTimer Init_Edges = Debug.timer("NodeClass.Init.Edges"); + private static final DebugTimer Init_Data = Debug.timer("NodeClass.Init.Data"); private static final DebugTimer Init_Naming = Debug.timer("NodeClass.Init.Naming"); private static final DebugTimer Init_AllowedUsages = Debug.timer("NodeClass.Init.AllowedUsages"); private static final DebugTimer Init_IterableIds = Debug.timer("NodeClass.Init.IterableIds"); @@ -109,12 +109,9 @@ private static int nextIterableId = 0; - private final int directInputCount; - private final long[] inputOffsets; - private final InputType[] inputTypes; - private final boolean[] inputOptional; - private final int directSuccessorCount; - private final long[] successorOffsets; + private final Edges inputs; + private final Edges successors; + private final Class<?>[] dataTypes; private final boolean canGVN; private final int startGVNNumber; @@ -167,37 +164,26 @@ this.isSimplifiable = Simplifiable.class.isAssignableFrom(clazz); - FieldScanner scanner = new FieldScanner(calcOffset); + FieldScanner fs = new FieldScanner(calcOffset); try (TimerCloseable t = Init_FieldScanning.start()) { - scanner.scan(clazz); + fs.scan(clazz); } - try (TimerCloseable t1 = Init_Offsets.start()) { - directInputCount = scanner.inputOffsets.size(); - - isLeafNode = scanner.inputOffsets.isEmpty() && scanner.inputListOffsets.isEmpty() && scanner.successorOffsets.isEmpty() && scanner.successorListOffsets.isEmpty(); - - inputOffsets = sortedOffsets(scanner.inputOffsets, scanner.inputListOffsets); - - inputTypes = new InputType[inputOffsets.length]; - inputOptional = new boolean[inputOffsets.length]; - for (int i = 0; i < inputOffsets.length; i++) { - inputTypes[i] = scanner.types.get(inputOffsets[i]); - assert inputTypes[i] != null; - inputOptional[i] = scanner.optionalInputs.contains(inputOffsets[i]); - } - directSuccessorCount = scanner.successorOffsets.size(); - successorOffsets = sortedOffsets(scanner.successorOffsets, scanner.successorListOffsets); - - dataOffsets = sortedLongCopy(scanner.dataOffsets); + try (TimerCloseable t1 = Init_Edges.start()) { + successors = new SuccessorEdges(clazz, fs.successorOffsets.size(), sortedOffsets(fs.successorOffsets, fs.successorListOffsets), fs.fieldNames, fs.fieldTypes); + inputs = new InputEdges(clazz, fs.inputOffsets.size(), sortedOffsets(fs.inputOffsets, fs.inputListOffsets), fs.fieldNames, fs.fieldTypes, fs.types, fs.optionalInputs); + } + try (TimerCloseable t1 = Init_Data.start()) { + dataOffsets = sortedLongCopy(fs.dataOffsets); dataTypes = new Class[dataOffsets.length]; for (int i = 0; i < dataOffsets.length; i++) { - dataTypes[i] = scanner.fieldTypes.get(dataOffsets[i]); + dataTypes[i] = fs.fieldTypes.get(dataOffsets[i]); } } - fieldNames = scanner.fieldNames; - fieldTypes = scanner.fieldTypes; + isLeafNode = inputs.getCount() + successors.getCount() == 0; + fieldNames = fs.fieldNames; + fieldTypes = fs.fieldTypes; canGVN = Node.ValueNumberable.class.isAssignableFrom(clazz); startGVNNumber = clazz.hashCode(); @@ -297,22 +283,7 @@ @Override protected void rescanFieldOffsets(CalcOffset calc) { - FieldScanner scanner = new FieldScanner(calc); - scanner.scan(getClazz()); - assert directInputCount == scanner.inputOffsets.size(); - copyInto(inputOffsets, sortedLongCopy(scanner.inputOffsets, scanner.inputListOffsets)); - assert directSuccessorCount == scanner.successorOffsets.size(); - copyInto(successorOffsets, sortedLongCopy(scanner.successorOffsets, scanner.successorListOffsets)); - copyInto(dataOffsets, sortedLongCopy(scanner.dataOffsets)); - - for (int i = 0; i < dataOffsets.length; i++) { - dataTypes[i] = scanner.fieldTypes.get(dataOffsets[i]); - } - - fieldNames.clear(); - fieldNames.putAll(scanner.fieldNames); - fieldTypes.clear(); - fieldTypes.putAll(scanner.fieldTypes); + throw new UnsupportedOperationException(); } /** @@ -322,7 +293,7 @@ * * <pre> * if (node.getNodeClass().is(BeginNode.class)) { ... } - * + * * // Due to generated Node classes, the test below * // is *not* the same as the test above: * if (node.getClass() == BeginNode.class) { ... } @@ -436,13 +407,9 @@ public String toString() { StringBuilder str = new StringBuilder(); str.append("NodeClass ").append(getClazz().getSimpleName()).append(" ["); - for (int i = 0; i < inputOffsets.length; i++) { - str.append(i == 0 ? "" : ", ").append(inputOffsets[i]); - } + inputs.appendOffsets(str); str.append("] ["); - for (int i = 0; i < successorOffsets.length; i++) { - str.append(i == 0 ? "" : ", ").append(successorOffsets[i]); - } + successors.appendOffsets(str); str.append("] ["); for (int i = 0; i < dataOffsets.length; i++) { str.append(i == 0 ? "" : ", ").append(dataOffsets[i]); @@ -451,313 +418,6 @@ return str.toString(); } - private static Node getNode(Node node, long offset) { - return (Node) unsafe.getObject(node, offset); - } - - @SuppressWarnings("unchecked") - private static NodeList<Node> getNodeList(Node node, long offset) { - return (NodeList<Node>) unsafe.getObject(node, offset); - } - - private static void putNode(Node node, long offset, Node value) { - unsafe.putObject(node, offset, value); - } - - private static void putNodeList(Node node, long offset, NodeList<?> value) { - unsafe.putObject(node, offset, value); - } - - /** - * An iterator that will iterate over the fields given in {@link #getOffsets()}. The first - * {@link #getDirectCount()} offsets are treated as fields of type {@link Node}, while the rest - * of the fields are treated as {@link NodeList}s. All elements of these NodeLists will be - * visited by the iterator as well. This iterator can be used to iterate over the inputs or - * successors of a node. - * - * An iterator of this type will not return null values, unless the field values are modified - * concurrently. Concurrent modifications are detected by an assertion on a best-effort basis. - */ - public abstract static class NodeClassIterator implements NodePosIterator { - protected final Node node; - protected int index; - protected int subIndex; - NodeList<Node> list; - protected boolean needsForward; - protected Node nextElement; - - /** - * Creates an iterator that will iterate over fields in the given node. - * - * @param node the node which contains the fields. - */ - NodeClassIterator(Node node) { - this.node = node; - index = NOT_ITERABLE; - subIndex = 0; - needsForward = true; - } - - void forward() { - needsForward = false; - if (index < getDirectCount()) { - index++; - while (index < getDirectCount()) { - nextElement = getNode(node, getOffsets()[index]); - if (nextElement != null) { - return; - } - index++; - } - } else { - subIndex++; - } - while (index < getOffsets().length) { - if (subIndex == 0) { - list = getNodeList(node, getOffsets()[index]); - } - while (subIndex < list.size()) { - nextElement = list.get(subIndex); - if (nextElement != null) { - return; - } - subIndex++; - } - subIndex = 0; - index++; - } - } - - private Node nextElement() { - if (needsForward) { - forward(); - } - needsForward = true; - if (index < getOffsets().length) { - return nextElement; - } - throw new NoSuchElementException(); - } - - @Override - public boolean hasNext() { - if (needsForward) { - forward(); - } - return index < getOffsets().length; - } - - @Override - public Node next() { - return nextElement(); - } - - public Position nextPosition() { - if (needsForward) { - forward(); - } - needsForward = true; - if (index < getDirectCount()) { - return new Position(getOffsets() == getNodeClass().inputOffsets, index, NOT_ITERABLE); - } else { - return new Position(getOffsets() == getNodeClass().inputOffsets, index, subIndex); - } - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - protected abstract int getDirectCount(); - - protected abstract long[] getOffsets(); - - protected abstract NodeClass getNodeClass(); - } - - private class NodeClassInputsIterator extends NodeClassIterator { - - NodeClassInputsIterator(Node node) { - super(node); - assert NodeClass.this == node.getNodeClass(); - } - - @Override - protected int getDirectCount() { - return directInputCount; - } - - @Override - protected long[] getOffsets() { - return inputOffsets; - } - - @Override - protected NodeClass getNodeClass() { - return NodeClass.this; - } - } - - private class NodeClassAllInputsIterator extends NodeClassInputsIterator { - NodeClassAllInputsIterator(Node node) { - super(node); - } - - @Override - void forward() { - needsForward = false; - if (index < getDirectCount()) { - index++; - if (index < getDirectCount()) { - nextElement = getNode(node, getOffsets()[index]); - return; - } - } else { - subIndex++; - } - while (index < getOffsets().length) { - if (subIndex == 0) { - list = getNodeList(node, getOffsets()[index]); - } - if (subIndex < list.size()) { - nextElement = list.get(subIndex); - return; - } - subIndex = 0; - index++; - } - } - } - - private class NodeClassAllSuccessorsIterator extends NodeClassSuccessorsIterator { - NodeClassAllSuccessorsIterator(Node node) { - super(node); - } - - @Override - void forward() { - needsForward = false; - if (index < getDirectCount()) { - index++; - if (index < getDirectCount()) { - nextElement = getNode(node, getOffsets()[index]); - return; - } - } else { - subIndex++; - } - while (index < getOffsets().length) { - if (subIndex == 0) { - list = getNodeList(node, getOffsets()[index]); - } - if (subIndex < list.size()) { - nextElement = list.get(subIndex); - return; - } - subIndex = 0; - index++; - } - } - } - - private final class NodeClassInputsWithModCountIterator extends NodeClassInputsIterator { - private final int modCount; - - private NodeClassInputsWithModCountIterator(Node node) { - super(node); - assert MODIFICATION_COUNTS_ENABLED; - this.modCount = node.modCount(); - } - - @Override - public boolean hasNext() { - try { - return super.hasNext(); - } finally { - assert modCount == node.modCount() : "must not be modified"; - } - } - - @Override - public Node next() { - try { - return super.next(); - } finally { - assert modCount == node.modCount() : "must not be modified"; - } - } - - @Override - public Position nextPosition() { - try { - return super.nextPosition(); - } finally { - assert modCount == node.modCount(); - } - } - } - - private class NodeClassSuccessorsIterator extends NodeClassIterator { - - NodeClassSuccessorsIterator(Node node) { - super(node); - assert NodeClass.this == node.getNodeClass(); - } - - @Override - protected int getDirectCount() { - return directSuccessorCount; - } - - @Override - protected long[] getOffsets() { - return successorOffsets; - } - - @Override - protected NodeClass getNodeClass() { - return NodeClass.this; - } - } - - private final class NodeClassSuccessorsWithModCountIterator extends NodeClassSuccessorsIterator { - private final int modCount; - - private NodeClassSuccessorsWithModCountIterator(Node node) { - super(node); - assert MODIFICATION_COUNTS_ENABLED; - this.modCount = node.modCount(); - } - - @Override - public boolean hasNext() { - try { - return super.hasNext(); - } finally { - assert modCount == node.modCount() : "must not be modified"; - } - } - - @Override - public Node next() { - try { - return super.next(); - } finally { - assert modCount == node.modCount() : "must not be modified"; - } - } - - @Override - public Position nextPosition() { - try { - return super.nextPosition(); - } finally { - assert modCount == node.modCount(); - } - } - } - private static int deepHashCode0(Object o) { if (o instanceof Object[]) { return Arrays.deepHashCode((Object[]) o); @@ -933,48 +593,18 @@ return true; } - public boolean isValid(Position pos, NodeClass from) { + public boolean isValid(Position pos, NodeClass from, Edges fromEdges) { if (this == from) { return true; } - long[] offsets = pos.isInput() ? inputOffsets : successorOffsets; - if (pos.getIndex() >= offsets.length) { - return false; - } - long[] fromOffsets = pos.isInput() ? from.inputOffsets : from.successorOffsets; - if (pos.getIndex() >= fromOffsets.length) { + Edges toEdges = getEdges(fromEdges.type()); + if (pos.getIndex() >= toEdges.getCount()) { return false; } - return offsets[pos.getIndex()] == fromOffsets[pos.getIndex()]; - } - - public Node get(Node node, Position pos) { - long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]; - if (pos.getSubIndex() == NOT_ITERABLE) { - return getNode(node, offset); - } else { - return getNodeList(node, offset).get(pos.getSubIndex()); + if (pos.getIndex() >= fromEdges.getCount()) { + return false; } - } - - public InputType getInputType(Position pos) { - assert pos.isInput(); - return inputTypes[pos.getIndex()]; - } - - public boolean isInputOptional(Position pos) { - assert pos.isInput(); - return inputOptional[pos.getIndex()]; - } - - public NodeList<?> getNodeList(Node node, Position pos) { - long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]; - assert pos.getSubIndex() == Node.NODE_LIST; - return getNodeList(node, offset); - } - - public String getName(Position pos) { - return fieldNames.get(pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]); + return toEdges.isSameEdge(fromEdges, pos.getIndex()); } public String getPropertyName(int pos) { @@ -1044,446 +674,54 @@ } } - void updateInputSuccInPlace(Node node, InplaceUpdateClosure duplicationReplacement) { + static void updateEdgesInPlace(Node node, InplaceUpdateClosure duplicationReplacement, Edges edges) { int index = 0; - while (index < directInputCount) { - Node input = getNode(node, inputOffsets[index]); - if (input != null) { - Node newInput = duplicationReplacement.replacement(input, true); - node.updateUsages(null, newInput); - assert newInput == null || fieldTypes.get(inputOffsets[index]).isAssignableFrom(newInput.getClass()) : "Can not assign " + newInput.getClass() + " to " + - fieldTypes.get(inputOffsets[index]) + " in " + node; - putNode(node, inputOffsets[index], newInput); - } - index++; - } - - if (index < inputOffsets.length) { - updateInputLists(node, duplicationReplacement, index); - } - - index = 0; - while (index < directSuccessorCount) { - Node successor = getNode(node, successorOffsets[index]); - if (successor != null) { - Node newSucc = duplicationReplacement.replacement(successor, false); - node.updatePredecessor(null, newSucc); - assert newSucc == null || fieldTypes.get(successorOffsets[index]).isAssignableFrom(newSucc.getClass()) : fieldTypes.get(successorOffsets[index]) + " is not compatible with " + - newSucc.getClass(); - putNode(node, successorOffsets[index], newSucc); + while (index < edges.getDirectCount()) { + Node edge = edges.getNode(node, index); + if (edge != null) { + Node newEdge = duplicationReplacement.replacement(edge, edges.type()); + if (edges.type() == Edges.Type.Inputs) { + node.updateUsages(null, newEdge); + } else { + node.updatePredecessor(null, newEdge); + } + assert newEdge == null || edges.getType(index).isAssignableFrom(newEdge.getClass()) : "Can not assign " + newEdge.getClass() + " to " + edges.getType(index) + " in " + node; + edges.initializeNode(node, index, newEdge); } index++; } - if (index < successorOffsets.length) { - updateSuccLists(node, duplicationReplacement, index); - } - } - - private void updateInputLists(Node node, InplaceUpdateClosure duplicationReplacement, int startIndex) { - int index = startIndex; - while (index < inputOffsets.length) { - NodeList<Node> list = getNodeList(node, inputOffsets[index]); - assert list != null : getClazz(); - putNodeList(node, inputOffsets[index], updateInputListCopy(list, node, duplicationReplacement)); + while (index < edges.getCount()) { + NodeList<Node> list = edges.getNodeList(node, index); + assert list != null : edges; + edges.initializeList(node, index, updateEdgeListCopy(node, list, duplicationReplacement, edges.type())); index++; } } - private void updateSuccLists(Node node, InplaceUpdateClosure duplicationReplacement, int startIndex) { - int index = startIndex; - while (index < successorOffsets.length) { - NodeList<Node> list = getNodeList(node, successorOffsets[index]); - assert list != null : getClazz(); - putNodeList(node, successorOffsets[index], updateSuccListCopy(list, node, duplicationReplacement)); - index++; - } + void updateInputSuccInPlace(Node node, InplaceUpdateClosure duplicationReplacement) { + updateEdgesInPlace(node, duplicationReplacement, inputs); + updateEdgesInPlace(node, duplicationReplacement, successors); } - private static NodeInputList<Node> updateInputListCopy(NodeList<Node> list, Node node, InplaceUpdateClosure duplicationReplacement) { - int size = list.size(); - NodeInputList<Node> result = new NodeInputList<>(node, size); + private static NodeList<Node> updateEdgeListCopy(Node node, NodeList<Node> list, InplaceUpdateClosure duplicationReplacement, Edges.Type type) { + NodeList<Node> result = type == Edges.Type.Inputs ? new NodeInputList<>(node, list.size()) : new NodeSuccessorList<>(node, list.size()); + for (int i = 0; i < list.count(); ++i) { Node oldNode = list.get(i); if (oldNode != null) { - Node newNode = duplicationReplacement.replacement(oldNode, true); - result.set(i, newNode); - } - } - return result; - } - - private static NodeSuccessorList<Node> updateSuccListCopy(NodeList<Node> list, Node node, InplaceUpdateClosure duplicationReplacement) { - int size = list.size(); - NodeSuccessorList<Node> result = new NodeSuccessorList<>(node, size); - for (int i = 0; i < list.count(); ++i) { - Node oldNode = list.get(i); - if (oldNode != null) { - Node newNode = duplicationReplacement.replacement(oldNode, false); + Node newNode = duplicationReplacement.replacement(oldNode, type); result.set(i, newNode); } } return result; } - public void set(Node node, Position pos, Node x) { - long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]; - if (pos.getSubIndex() == NOT_ITERABLE) { - Node old = getNode(node, offset); - assert x == null || fieldTypes.get((pos.isInput() ? inputOffsets : successorOffsets)[pos.getIndex()]).isAssignableFrom(x.getClass()) : this + ".set(node, pos, " + x + ")"; - putNode(node, offset, x); - if (pos.isInput()) { - node.updateUsages(old, x); - } else { - node.updatePredecessor(old, x); - } - } else { - NodeList<Node> list = getNodeList(node, offset); - if (pos.getSubIndex() < list.size()) { - list.set(pos.getSubIndex(), x); - } else { - while (list.size() < pos.getSubIndex()) { - list.add(null); - } - list.add(x); - } - } - } - - public void initializePosition(Node node, Position pos, Node x) { - long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()]; - if (pos.getSubIndex() == NOT_ITERABLE) { - assert x == null || fieldTypes.get((pos.isInput() ? inputOffsets : successorOffsets)[pos.getIndex()]).isAssignableFrom(x.getClass()) : this + ".set(node, pos, " + x + ")"; - putNode(node, offset, x); - } else { - NodeList<Node> list = getNodeList(node, offset); - while (list.size() <= pos.getSubIndex()) { - list.add(null); - } - list.initialize(pos.getSubIndex(), x); - } - } - - public NodeClassIterable getInputIterable(final Node node) { - assert getClazz().isInstance(node); - return new NodeClassIterable() { - - @Override - public NodeClassIterator iterator() { - if (MODIFICATION_COUNTS_ENABLED) { - return new NodeClassInputsWithModCountIterator(node); - } else { - return new NodeClassInputsIterator(node); - } - } - - public NodeClassIterator withNullIterator() { - return new NodeClassAllInputsIterator(node); - } - - @Override - public boolean contains(Node other) { - return inputContains(node, other); - } - }; - } - - public NodeClassIterable getSuccessorIterable(final Node node) { - assert getClazz().isInstance(node); - return new NodeClassIterable() { - - @Override - public NodeClassIterator iterator() { - if (MODIFICATION_COUNTS_ENABLED) { - return new NodeClassSuccessorsWithModCountIterator(node); - } else { - return new NodeClassSuccessorsIterator(node); - } - } - - public NodeClassIterator withNullIterator() { - return new NodeClassAllSuccessorsIterator(node); - } - - @Override - public boolean contains(Node other) { - return successorContains(node, other); - } - }; - } - - public boolean replaceFirstInput(Node node, Node old, Node other) { - int index = 0; - while (index < directInputCount) { - Node input = getNode(node, inputOffsets[index]); - if (input == old) { - assert other == null || fieldTypes.get(inputOffsets[index]).isAssignableFrom(other.getClass()) : "Can not assign " + other.getClass() + " to " + fieldTypes.get(inputOffsets[index]) + - " in " + node; - putNode(node, inputOffsets[index], other); - return true; - } - index++; - } - while (index < inputOffsets.length) { - NodeList<Node> list = getNodeList(node, inputOffsets[index]); - assert list != null : getClazz(); - if (list.replaceFirst(old, other)) { - return true; - } - index++; - } - return false; - } - - public boolean replaceFirstSuccessor(Node node, Node old, Node other) { - int index = 0; - while (index < directSuccessorCount) { - Node successor = getNode(node, successorOffsets[index]); - if (successor == old) { - assert other == null || fieldTypes.get(successorOffsets[index]).isAssignableFrom(other.getClass()) : fieldTypes.get(successorOffsets[index]) + " is not compatible with " + - other.getClass(); - putNode(node, successorOffsets[index], other); - return true; - } - index++; - } - while (index < successorOffsets.length) { - NodeList<Node> list = getNodeList(node, successorOffsets[index]); - assert list != null : getClazz() + " " + successorOffsets[index] + " " + node; - if (list.replaceFirst(old, other)) { - return true; - } - index++; - } - return false; - } - /** - * Clear all inputs in the given node. This is accomplished by setting input fields to null and - * replacing input lists with new lists. (which is important so that this method can be used to - * clear the inputs of cloned nodes.) - * - * @param node the node to be cleared - */ - public void clearInputs(Node node) { - int index = 0; - while (index < directInputCount) { - putNode(node, inputOffsets[index++], null); - } - while (index < inputOffsets.length) { - long curOffset = inputOffsets[index++]; - int size = (getNodeList(node, curOffset)).initialSize; - // replacing with a new list object is the expected behavior! - putNodeList(node, curOffset, new NodeInputList<>(node, size)); - } - } - - /** - * Clear all successors in the given node. This is accomplished by setting successor fields to - * null and replacing successor lists with new lists. (which is important so that this method - * can be used to clear the successors of cloned nodes.) - * - * @param node the node to be cleared - */ - public void clearSuccessors(Node node) { - int index = 0; - while (index < directSuccessorCount) { - putNode(node, successorOffsets[index++], null); - } - while (index < successorOffsets.length) { - long curOffset = successorOffsets[index++]; - int size = getNodeList(node, curOffset).initialSize; - // replacing with a new list object is the expected behavior! - putNodeList(node, curOffset, new NodeSuccessorList<>(node, size)); - } - } - - /** - * Copies the inputs from node to newNode. The nodes are expected to be of the exact same - * NodeClass type. - * - * @param node the node from which the inputs should be copied. - * @param newNode the node to which the inputs should be copied. + * Gets the input or successor edges defined by this node class. */ - public void copyInputs(Node node, Node newNode) { - assert node.getNodeClass() == this && newNode.getNodeClass() == this; - - int index = 0; - while (index < directInputCount) { - putNode(newNode, inputOffsets[index], getNode(node, inputOffsets[index])); - index++; - } - while (index < inputOffsets.length) { - NodeList<Node> list = getNodeList(newNode, inputOffsets[index]); - list.copy(getNodeList(node, inputOffsets[index])); - index++; - } - } - - /** - * Copies the successors from node to newNode. The nodes are expected to be of the exact same - * NodeClass type. - * - * @param node the node from which the successors should be copied. - * @param newNode the node to which the successors should be copied. - */ - public void copySuccessors(Node node, Node newNode) { - assert node.getNodeClass() == this && newNode.getNodeClass() == this; - - int index = 0; - while (index < directSuccessorCount) { - putNode(newNode, successorOffsets[index], getNode(node, successorOffsets[index])); - index++; - } - while (index < successorOffsets.length) { - NodeList<Node> list = getNodeList(newNode, successorOffsets[index]); - list.copy(getNodeList(node, successorOffsets[index])); - index++; - } - } - - public boolean edgesEqual(Node node, Node other) { - return inputsEqual(node, other) && successorsEqual(node, other); - } - - public boolean inputsEqual(Node node, Node other) { - assert node.getNodeClass() == this && other.getNodeClass() == this; - int index = 0; - while (index < directInputCount) { - if (getNode(other, inputOffsets[index]) != getNode(node, inputOffsets[index])) { - return false; - } - index++; - } - while (index < inputOffsets.length) { - NodeList<Node> list = getNodeList(other, inputOffsets[index]); - if (!list.equals(getNodeList(node, inputOffsets[index]))) { - return false; - } - index++; - } - return true; - } - - public boolean successorsEqual(Node node, Node other) { - assert node.getNodeClass() == this && other.getNodeClass() == this; - int index = 0; - while (index < directSuccessorCount) { - if (getNode(other, successorOffsets[index]) != getNode(node, successorOffsets[index])) { - return false; - } - index++; - } - while (index < successorOffsets.length) { - NodeList<Node> list = getNodeList(other, successorOffsets[index]); - if (!list.equals(getNodeList(node, successorOffsets[index]))) { - return false; - } - index++; - } - return true; - } - - public boolean inputContains(Node node, Node other) { - assert node.getNodeClass() == this; - - int index = 0; - while (index < directInputCount) { - if (getNode(node, inputOffsets[index]) == other) { - return true; - } - index++; - } - while (index < inputOffsets.length) { - NodeList<Node> list = getNodeList(node, inputOffsets[index]); - if (list.contains(other)) { - return true; - } - index++; - } - return false; - } - - public boolean successorContains(Node node, Node other) { - assert node.getNodeClass() == this; - - int index = 0; - while (index < directSuccessorCount) { - if (getNode(node, successorOffsets[index]) == other) { - return true; - } - index++; - } - while (index < successorOffsets.length) { - NodeList<Node> list = getNodeList(node, successorOffsets[index]); - if (list.contains(other)) { - return true; - } - index++; - } - return false; - } - - public Collection<Position> getFirstLevelInputPositions() { - return new AbstractCollection<Position>() { - @Override - public Iterator<Position> iterator() { - return new Iterator<Position>() { - int i = 0; - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - public Position next() { - Position pos = new Position(true, i, i >= directInputCount ? Node.NODE_LIST : Node.NOT_ITERABLE); - i++; - return pos; - } - - public boolean hasNext() { - return i < inputOffsets.length; - } - }; - } - - @Override - public int size() { - return inputOffsets.length; - } - }; - } - - public Collection<Position> getFirstLevelSuccessorPositions() { - return new AbstractCollection<Position>() { - @Override - public Iterator<Position> iterator() { - return new Iterator<Position>() { - int i = 0; - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - public Position next() { - Position pos = new Position(false, i, i >= directSuccessorCount ? Node.NODE_LIST : Node.NOT_ITERABLE); - i++; - return pos; - } - - public boolean hasNext() { - return i < successorOffsets.length; - } - }; - } - - @Override - public int size() { - return successorOffsets.length; - } - }; + public Edges getEdges(Edges.Type type) { + return type == Edges.Type.Inputs ? inputs : successors; } public Collection<Integer> getPropertyPositions() { @@ -1522,14 +760,15 @@ */ public void initRawNode(Node node) { node.init(); - for (int inputPos = directInputCount; inputPos < inputOffsets.length; inputPos++) { - if (getNodeList(node, inputOffsets[inputPos]) == null) { - putNodeList(node, inputOffsets[inputPos], new NodeInputList<>(node)); - } - } - for (int successorPos = directSuccessorCount; successorPos < successorOffsets.length; successorPos++) { - if (getNodeList(node, successorOffsets[successorPos]) == null) { - putNodeList(node, successorOffsets[successorPos], new NodeSuccessorList<>(node)); + initNullEdgeLists(node, Edges.Type.Inputs); + initNullEdgeLists(node, Edges.Type.Successors); + } + + private void initNullEdgeLists(Node node, Edges.Type type) { + Edges edges = getEdges(type); + 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)); } } } @@ -1548,7 +787,7 @@ interface InplaceUpdateClosure { - Node replacement(Node node, boolean isInput); + Node replacement(Node node, Edges.Type type); } static Map<Node, Node> addGraphDuplicate(final Graph graph, final Graph oldGraph, int estimatedNodeCount, Iterable<Node> nodes, final DuplicationReplacement replacements) { @@ -1565,7 +804,7 @@ InplaceUpdateClosure replacementClosure = new InplaceUpdateClosure() { - public Node replacement(Node node, boolean isInput) { + public Node replacement(Node node, Edges.Type type) { Node target = newNodes.get(node); if (target == null) { Node replacement = node; @@ -1574,7 +813,7 @@ } if (replacement != node) { target = replacement; - } else if (node.graph() == graph && isInput) { + } else if (node.graph() == graph && type == Edges.Type.Inputs) { // patch to the outer world target = node; } @@ -1588,12 +827,11 @@ // re-wire inputs for (Node oldNode : nodes) { Node node = newNodes.get(oldNode); - NodeClass oldNodeClass = oldNode.getNodeClass(); NodeClass nodeClass = node.getNodeClass(); if (replacements == null || replacements.replacement(oldNode) == oldNode) { nodeClass.updateInputSuccInPlace(node, replacementClosure); } else { - transferValuesDifferentNodeClass(graph, replacements, newNodes, oldNode, node, oldNodeClass, nodeClass); + transferEdgesDifferentNodeClass(graph, replacements, newNodes, oldNode, node); } } @@ -1621,50 +859,36 @@ } } - private static void transferValuesDifferentNodeClass(final Graph graph, final DuplicationReplacement replacements, final Map<Node, Node> newNodes, Node oldNode, Node node, NodeClass oldNodeClass, - NodeClass nodeClass) { - for (NodePosIterator iter = oldNode.inputs().iterator(); iter.hasNext();) { - Position pos = iter.nextPosition(); - if (!nodeClass.isValid(pos, oldNodeClass)) { + private static void transferEdgesDifferentNodeClass(final Graph graph, final DuplicationReplacement replacements, final Map<Node, Node> newNodes, Node oldNode, Node node) { + transferEdges(graph, replacements, newNodes, oldNode, node, Edges.Type.Inputs); + transferEdges(graph, replacements, newNodes, oldNode, node, Edges.Type.Successors); + } + + private static void transferEdges(final Graph graph, final DuplicationReplacement replacements, final Map<Node, Node> newNodes, Node oldNode, Node node, Edges.Type type) { + NodeClass nodeClass = node.getNodeClass(); + NodeClass oldNodeClass = oldNode.getNodeClass(); + Edges oldEdges = oldNodeClass.getEdges(type); + for (NodePosIterator oldIter = oldEdges.getIterable(oldNode).iterator(); oldIter.hasNext();) { + Position pos = oldIter.nextPosition(); + if (!nodeClass.isValid(pos, oldNodeClass, oldEdges)) { continue; } - Node input = oldNodeClass.get(oldNode, pos); - Node target = newNodes.get(input); + Node oldEdge = pos.get(oldNode); + Node target = newNodes.get(oldEdge); if (target == null) { - Node replacement = input; + Node replacement = oldEdge; if (replacements != null) { - replacement = replacements.replacement(input); + replacement = replacements.replacement(oldEdge); } - if (replacement != input) { - assert isAssignable(nodeClass.fieldTypes.get(nodeClass.inputOffsets[pos.getIndex()]), replacement); + if (replacement != oldEdge) { target = replacement; - } else if (input.graph() == graph) { // patch to the outer world - target = input; + } else if (type == Edges.Type.Inputs && oldEdge.graph() == graph) { + // patch to the outer world + target = oldEdge; } } - nodeClass.set(node, pos, target); + pos.set(node, target); } - - for (NodePosIterator iter = oldNode.successors().iterator(); iter.hasNext();) { - Position pos = iter.nextPosition(); - if (!nodeClass.isValid(pos, oldNodeClass)) { - continue; - } - Node succ = oldNodeClass.get(oldNode, pos); - Node target = newNodes.get(succ); - if (target == null) { - Node replacement = replacements.replacement(succ); - if (replacement != succ) { - assert isAssignable(nodeClass.fieldTypes.get(node.getNodeClass().successorOffsets[pos.getIndex()]), replacement); - target = replacement; - } - } - nodeClass.set(node, pos, target); - } - } - - private static boolean isAssignable(Class<?> fieldType, Node replacement) { - return replacement == null || !NODE_CLASS.isAssignableFrom(fieldType) || fieldType.isAssignableFrom(replacement.getClass()); } public boolean isLeafNode() {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java Thu Sep 25 10:27:17 2014 +0200 @@ -25,7 +25,7 @@ import com.oracle.graal.graph.iterators.*; /** - * The iterator returned by this iterable can be used to access {@link Position Positions} during + * The iterator returned by this iterable can be used to access {@link Position positions} during * iteration using {@link NodePosIterator#nextPosition()}. */ public interface NodeClassIterable extends NodeIterable<Node> {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputList.java Thu Sep 25 10:27:17 2014 +0200 @@ -22,37 +22,35 @@ */ package com.oracle.graal.graph; +import static com.oracle.graal.graph.Edges.Type.*; + import java.util.*; +import com.oracle.graal.graph.Edges.*; + public final class NodeInputList<T extends Node> extends NodeList<T> { - private final Node self; - public NodeInputList(Node self, int initialSize) { - super(initialSize); - this.self = self; + super(self, initialSize); } public NodeInputList(Node self) { - this.self = self; + super(self); } public NodeInputList(Node self, T[] elements) { - super(elements); + super(self, elements); assert self.usages().isEmpty(); - this.self = self; } public NodeInputList(Node self, List<? extends T> elements) { - super(elements); + super(self, elements); assert self.usages().isEmpty(); - this.self = self; } public NodeInputList(Node self, Collection<? extends NodeInterface> elements) { - super(elements); + super(self, elements); assert self.usages().isEmpty(); - this.self = self; } @Override @@ -61,39 +59,7 @@ } @Override - public boolean add(Node node) { - assert node == null || !node.isDeleted(); - self.incModCount(); - return super.add(node); - } - - @Override - public T remove(int index) { - self.incModCount(); - return super.remove(index); - } - - @Override - public boolean remove(Object node) { - self.incModCount(); - return super.remove(node); - } - - @Override - public void clear() { - self.incModCount(); - super.clear(); - } - - @Override - void copy(NodeList<? extends Node> other) { - self.incModCount(); - super.copy(other); - } - - @Override - public void setAll(NodeList<T> values) { - self.incModCount(); - super.setAll(values); + public Type getEdgesType() { + return Inputs; } }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Thu Sep 25 10:27:17 2014 +0200 @@ -30,22 +30,26 @@ protected static final Node[] EMPTY_NODE_ARRAY = new Node[0]; + protected final Node self; protected Node[] nodes; private int size; protected final int initialSize; - protected NodeList() { + protected NodeList(Node self) { + this.self = self; this.nodes = EMPTY_NODE_ARRAY; this.initialSize = 0; } - protected NodeList(int initialSize) { + protected NodeList(Node self, int initialSize) { + this.self = self; this.size = initialSize; this.initialSize = initialSize; this.nodes = new Node[initialSize]; } - protected NodeList(T[] elements) { + protected NodeList(Node self, T[] elements) { + this.self = self; if (elements == null || elements.length == 0) { this.size = 0; this.nodes = EMPTY_NODE_ARRAY; @@ -61,7 +65,8 @@ } } - protected NodeList(List<? extends T> elements) { + protected NodeList(Node self, List<? extends T> elements) { + this.self = self; if (elements == null || elements.isEmpty()) { this.size = 0; this.nodes = EMPTY_NODE_ARRAY; @@ -77,7 +82,8 @@ } } - protected NodeList(Collection<? extends NodeInterface> elements) { + protected NodeList(Node self, Collection<? extends NodeInterface> elements) { + this.self = self; if (elements == null || elements.isEmpty()) { this.size = 0; this.nodes = EMPTY_NODE_ARRAY; @@ -95,8 +101,14 @@ } } + public boolean isList() { + return true; + } + protected abstract void update(T oldNode, T newNode); + public abstract Edges.Type getEdgesType(); + @Override public final int size() { return size; @@ -124,6 +136,8 @@ @SuppressWarnings("unchecked") @Override public boolean add(Node node) { + assert node == null || !node.isDeleted(); + self.incModCount(); incModCount(); if (size == nodes.length) { nodes = Arrays.copyOf(nodes, nodes.length * 2 + 1); @@ -162,6 +176,7 @@ } void copy(NodeList<? extends Node> other) { + self.incModCount(); incModCount(); nodes = Arrays.copyOf(other.nodes, other.size); size = other.size; @@ -182,6 +197,7 @@ @SuppressWarnings("unchecked") @Override public void clear() { + self.incModCount(); incModCount(); for (int i = 0; i < size; i++) { update((T) nodes[i], null); @@ -193,6 +209,7 @@ @Override @SuppressWarnings("unchecked") public boolean remove(Object node) { + self.incModCount(); int i = 0; incModCount(); while (i < size && nodes[i] != node) { @@ -216,6 +233,7 @@ @Override @SuppressWarnings("unchecked") public T remove(int index) { + self.incModCount(); T oldValue = (T) nodes[index]; int i = index + 1; incModCount(); @@ -290,6 +308,7 @@ @SuppressWarnings("unchecked") public void setAll(NodeList<T> values) { + self.incModCount(); incModCount(); for (int i = 0; i < size(); i++) { update((T) nodes[i], null);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java Thu Sep 25 10:27:17 2014 +0200 @@ -22,23 +22,23 @@ */ package com.oracle.graal.graph; +import static com.oracle.graal.graph.Edges.Type.*; + +import com.oracle.graal.graph.Edges.*; + public final class NodeSuccessorList<T extends Node> extends NodeList<T> { - private final Node self; - public NodeSuccessorList(Node self, int initialSize) { - super(initialSize); - this.self = self; + super(self, initialSize); } protected NodeSuccessorList(Node self) { - this.self = self; + super(self); } public NodeSuccessorList(Node self, T[] elements) { - super(elements); + super(self, elements); assert self.usages().isEmpty(); - this.self = self; } @Override @@ -47,38 +47,7 @@ } @Override - public boolean add(Node node) { - self.incModCount(); - return super.add(node); - } - - @Override - public T remove(int index) { - self.incModCount(); - return super.remove(index); - } - - @Override - public boolean remove(Object node) { - self.incModCount(); - return super.remove(node); - } - - @Override - public void clear() { - self.incModCount(); - super.clear(); - } - - @Override - void copy(NodeList<? extends Node> other) { - self.incModCount(); - super.copy(other); - } - - @Override - public void setAll(NodeList<T> values) { - self.incModCount(); - super.setAll(values); + public Type getEdgesType() { + return Successors; } }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java Thu Sep 25 10:27:17 2014 +0200 @@ -22,21 +22,17 @@ */ package com.oracle.graal.graph; -import com.oracle.graal.graph.Node.Input; -import com.oracle.graal.graph.Node.OptionalInput; import com.oracle.graal.nodeinfo.*; /** * Describes an edge slot for a {@link NodeClass}. - * - * @see NodeClass#getName(Position) */ public final class Position { /** - * Specifies if this position denotes an {@link Input} or {@link OptionalInput} field. + * The edges in which this position lies. */ - private final boolean input; + private final Edges edges; /** * Index of the {@link Node} or {@link NodeList} field denoted by this position. @@ -49,39 +45,55 @@ */ private final int subIndex; - public Position(boolean input, int index, int subIndex) { - this.input = input; + public Position(Edges edges, int index, int subIndex) { + this.edges = edges; this.index = index; this.subIndex = subIndex; } public Node get(Node node) { - return node.getNodeClass().get(node, this); - } - - public InputType getInputType(Node node) { - return node.getNodeClass().getInputType(this); + if (index < edges.getDirectCount()) { + return edges.getNode(node, index); + } else { + return edges.getNodeList(node, index).get(subIndex); + } } - public String getInputName(Node node) { - return node.getNodeClass().getName(this); + public InputType getInputType() { + return ((InputEdges) edges).getInputType(index); } - public boolean isInputOptional(Node node) { - return node.getNodeClass().isInputOptional(this); + public String getName() { + return edges.getName(index); + } + + public boolean isInputOptional() { + return ((InputEdges) edges).isOptional(index); } public void set(Node node, Node value) { - node.getNodeClass().set(node, this, value); + if (index < edges.getDirectCount()) { + edges.setNode(node, index, value); + } else { + edges.getNodeList(node, index).set(subIndex, value); + } } public void initialize(Node node, Node value) { - node.getNodeClass().initializePosition(node, this, value); + if (index < edges.getDirectCount()) { + edges.initializeNode(node, index, value); + } else { + edges.getNodeList(node, index).initialize(subIndex, value); + } } @Override public String toString() { - return (input ? "input " : "successor ") + index + "/" + subIndex; + String res = edges.getType(index).getSimpleName() + ":" + edges.getName(index); + if (subIndex != Node.NOT_ITERABLE) { + res += "[" + subIndex + "]"; + } + return res; } @Override @@ -89,7 +101,7 @@ final int prime = 31; int result = 1; result = prime * result + index; - result = prime * result + (input ? 1231 : 1237); + result = prime * result + edges.hashCode(); result = prime * result + subIndex; return result; } @@ -109,7 +121,7 @@ if (index != other.index) { return false; } - if (input != other.input) { + if (edges != other.edges) { return false; } if (subIndex != other.subIndex) { @@ -132,12 +144,4 @@ public int getIndex() { return index; } - - /** - * Returns true if this position denotes an {@link Input} or {@link OptionalInput} field, false - * otherwise. - */ - public boolean isInput() { - return input; - } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/SuccessorEdges.java Thu Sep 25 10:27:17 2014 +0200 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014, 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; + +import static com.oracle.graal.graph.Edges.Type.*; + +import java.util.*; + +public final class SuccessorEdges extends Edges { + + public SuccessorEdges(Class<?> nodeClass, int directCount, long[] offsets, Map<Long, String> names, Map<Long, Class<?>> types) { + super(nodeClass, Successors, directCount, offsets, names, types); + } + + @Override + protected void update(Node node, Node oldValue, Node newValue) { + node.updatePredecessor(oldValue, newValue); + } +}
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java Thu Sep 25 10:27:17 2014 +0200 @@ -89,22 +89,21 @@ assert successors.hasNext(); // original loop is used as first successor Position firstPosition = successors.nextPosition(); - NodeClass controlSplitClass = firstNode.getNodeClass(); BeginNode originalLoopBegin = BeginNode.begin(originalLoop.entryPoint()); - controlSplitClass.set(newControlSplit, firstPosition, originalLoopBegin); + firstPosition.set(newControlSplit, originalLoopBegin); while (successors.hasNext()) { Position position = successors.nextPosition(); // create a new loop duplicate and connect it. LoopFragmentWhole duplicateLoop = originalLoop.duplicate(); BeginNode newBegin = BeginNode.begin(duplicateLoop.entryPoint()); - controlSplitClass.set(newControlSplit, position, newBegin); + position.set(newControlSplit, newBegin); // For each cloned ControlSplitNode, simplify the proper path for (ControlSplitNode controlSplitNode : controlSplitNodeSet) { ControlSplitNode duplicatedControlSplit = duplicateLoop.getDuplicatedNode(controlSplitNode); if (duplicatedControlSplit.isAlive()) { - BeginNode survivingSuccessor = (BeginNode) controlSplitClass.get(duplicatedControlSplit, position); + BeginNode survivingSuccessor = (BeginNode) position.get(duplicatedControlSplit); survivingSuccessor.replaceAtUsages(InputType.Guard, newBegin); graph.removeSplitPropagate(duplicatedControlSplit, survivingSuccessor); } @@ -113,7 +112,7 @@ // original loop is simplified last to avoid deleting controlSplitNode too early for (ControlSplitNode controlSplitNode : controlSplitNodeSet) { if (controlSplitNode.isAlive()) { - BeginNode survivingSuccessor = (BeginNode) controlSplitClass.get(controlSplitNode, firstPosition); + BeginNode survivingSuccessor = (BeginNode) firstPosition.get(controlSplitNode); survivingSuccessor.replaceAtUsages(InputType.Guard, originalLoopBegin); graph.removeSplitPropagate(controlSplitNode, survivingSuccessor); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Thu Sep 25 10:27:17 2014 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes; +import static com.oracle.graal.graph.Edges.Type.*; + import java.util.*; import com.oracle.graal.api.meta.*; @@ -226,7 +228,7 @@ FixedWithNextNode falseNext = (FixedWithNextNode) falseSucc.next(); NodeClass nodeClass = trueNext.getNodeClass(); if (trueNext.getClass() == falseNext.getClass()) { - if (nodeClass.inputsEqual(trueNext, falseNext) && nodeClass.valueEqual(trueNext, falseNext)) { + if (nodeClass.getEdges(Inputs).areEqualIn(trueNext, falseNext) && nodeClass.valueEqual(trueNext, falseNext)) { falseNext.replaceAtUsages(trueNext); graph().removeFixed(falseNext); GraphUtil.unlinkFixedNode(trueNext);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Thu Sep 25 10:27:17 2014 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.calc; +import static com.oracle.graal.graph.Edges.Type.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -97,7 +99,7 @@ if (next() instanceof IntegerDivNode) { NodeClass nodeClass = getNodeClass(); - if (next().getClass() == this.getClass() && nodeClass.inputsEqual(this, next()) && nodeClass.valueEqual(this, next())) { + if (next().getClass() == this.getClass() && nodeClass.getEdges(Inputs).areEqualIn(this, next()) && nodeClass.valueEqual(this, next())) { return next(); } }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java Thu Sep 25 10:27:17 2014 +0200 @@ -500,7 +500,7 @@ while (iter.hasNext()) { Position pos = iter.nextPosition(); if (pos.get(usage) == duplicated) { - switch (pos.getInputType(usage)) { + switch (pos.getInputType()) { case Extension: case Condition: case State: @@ -549,7 +549,7 @@ Position pos = iter.nextPosition(); Node input = pos.get(duplicated); if (input != null && !duplicatedNodes.contains(input)) { - switch (pos.getInputType(duplicated)) { + switch (pos.getInputType()) { case Extension: case Condition: case State:
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java Thu Sep 25 10:27:17 2014 +0200 @@ -95,11 +95,11 @@ } else { /* * Not comparable, two cases: - * + * * Example 1: 'a' standing for j.l.Number and 'b' for j.l.String We return null for lack * of a value representing NullType, the right answer. Same goes when both arguments are * non-comparable interfaces. - * + * * Example 2: 'a' standing for sun/nio/ch/DirectBuffer (an interface) and b for * java/nio/Buffer (an abstract class). The class always takes precedence. */ @@ -232,7 +232,7 @@ NodePosIterator iter = n.inputs().iterator(); while (iter.hasNext()) { Position pos = iter.nextPosition(); - InputType inputType = pos.getInputType(n); + InputType inputType = pos.getInputType(); boolean isReducibleInput = (inputType == InputType.Value || inputType == InputType.Condition); if (isReducibleInput) { ValueNode i = (ValueNode) pos.get(n);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Thu Sep 25 10:27:17 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.printer; import static com.oracle.graal.compiler.common.GraalOptions.*; +import static com.oracle.graal.graph.Edges.Type.*; import java.io.*; import java.nio.*; @@ -297,19 +298,8 @@ writeByte(POOL_NODE_CLASS); writeString(nodeClass.getJavaClass().getSimpleName()); writeString(nodeClass.getNameTemplate()); - Collection<Position> directInputPositions = nodeClass.getFirstLevelInputPositions(); - writeShort((char) directInputPositions.size()); - for (Position pos : directInputPositions) { - writeByte(pos.getSubIndex() == Node.NOT_ITERABLE ? 0 : 1); - writePoolObject(nodeClass.getName(pos)); - writePoolObject(nodeClass.getInputType(pos)); - } - Collection<Position> directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions(); - writeShort((char) directSuccessorPositions.size()); - for (Position pos : directSuccessorPositions) { - writeByte(pos.getSubIndex() == Node.NOT_ITERABLE ? 0 : 1); - writePoolObject(nodeClass.getName(pos)); - } + writeEdgesInfo(nodeClass, Inputs); + writeEdgesInfo(nodeClass, Successors); } else if (object instanceof ResolvedJavaMethod) { writeByte(POOL_METHOD); ResolvedJavaMethod method = ((ResolvedJavaMethod) object); @@ -340,6 +330,18 @@ } } + private void writeEdgesInfo(NodeClass nodeClass, Edges.Type type) throws IOException { + Edges edges = nodeClass.getEdges(type); + writeShort((char) edges.getCount()); + for (int i = 0; i < edges.getCount(); i++) { + writeByte(i < edges.getDirectCount() ? 0 : 1); + writePoolObject(edges.getName(i)); + if (type == Inputs) { + writePoolObject(((InputEdges) edges).getInputType(i)); + } + } + } + private void writePropertyObject(Object obj) throws IOException { if (obj instanceof Integer) { writeByte(PROPERTY_INT); @@ -429,32 +431,29 @@ writePoolObject(key); writePropertyObject(entry.getValue()); } - // inputs - writeEdges(node, nodeClass.getFirstLevelInputPositions()); - // successors - writeEdges(node, nodeClass.getFirstLevelSuccessorPositions()); + writeEdges(node, Inputs); + writeEdges(node, Successors); props.clear(); } } - private void writeEdges(Node node, Collection<Position> positions) throws IOException { + private void writeEdges(Node node, Edges.Type type) throws IOException { NodeClass nodeClass = node.getNodeClass(); - for (Position pos : positions) { - if (pos.getSubIndex() == Node.NOT_ITERABLE) { - Node edge = nodeClass.get(node, pos); - writeNodeRef(edge); + Edges edges = nodeClass.getEdges(type); + for (int i = 0; i < edges.getDirectCount(); i++) { + writeNodeRef(edges.getNode(node, i)); + } + for (int i = edges.getDirectCount(); i < edges.getCount(); i++) { + NodeList<Node> list = edges.getNodeList(node, i); + if (list == null) { + writeShort((char) 0); } else { - NodeList<?> list = nodeClass.getNodeList(node, pos); - if (list == null) { - writeShort((char) 0); - } else { - int listSize = list.count(); - assert listSize == ((char) listSize); - writeShort((char) listSize); - for (Node edge : list) { - writeNodeRef(edge); - } + int listSize = list.count(); + assert listSize == ((char) listSize); + writeShort((char) listSize); + for (Node edge : list) { + writeNodeRef(edge); } } }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Thu Sep 25 10:27:17 2014 +0200 @@ -370,7 +370,7 @@ int lastIndex = -1; while (iter.hasNext()) { Position pos = iter.nextPosition(); - if (hideSuffix != null && node.getNodeClass().getName(pos).endsWith(hideSuffix)) { + if (hideSuffix != null && pos.getName().endsWith(hideSuffix)) { continue; } @@ -378,10 +378,10 @@ if (lastIndex != -1) { out.print(suffix); } - out.print(prefix).print(node.getNodeClass().getName(pos)).print(": "); + out.print(prefix).print(pos.getName()).print(": "); lastIndex = pos.getIndex(); } - out.print(nodeToString(node.getNodeClass().get(node, pos))).print(" "); + out.print(nodeToString(pos.get(node))).print(" "); } if (lastIndex != -1) { out.print(suffix);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Wed Sep 24 17:17:27 2014 -0700 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Thu Sep 25 10:27:17 2014 +0200 @@ -215,9 +215,9 @@ NodePosIterator succIter = node.successors().iterator(); while (succIter.hasNext()) { Position position = succIter.nextPosition(); - Node successor = node.getNodeClass().get(node, position); + Node successor = position.get(node); if (successor != null) { - edges.add(new Edge(node.toString(Verbosity.Id), fromIndex, successor.toString(Verbosity.Id), 0, node.getNodeClass().getName(position))); + edges.add(new Edge(node.toString(Verbosity.Id), fromIndex, successor.toString(Verbosity.Id), 0, position.getName())); } fromIndex++; } @@ -227,9 +227,9 @@ NodePosIterator inputIter = node.inputs().iterator(); while (inputIter.hasNext()) { Position position = inputIter.nextPosition(); - Node input = node.getNodeClass().get(node, position); + Node input = position.get(node); if (input != null) { - edges.add(new Edge(input.toString(Verbosity.Id), input.successors().count(), 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, position.getName())); } toIndex++; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/EdgesSubstitutions.java Thu Sep 25 10:27:17 2014 +0200 @@ -0,0 +1,61 @@ +/* + * 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.graal.replacements; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; + +/** + * Substitutions for improving the performance of some critical methods in {@link Edges}. These + * substitutions improve the performance by forcing the relevant methods to be inlined + * (intrinsification being a special form of inlining) and removing a checked cast. The latter + * cannot be done directly in Java code as {@link PiNode} is not available to the project containing + * {@link Edges}. + */ +@ClassSubstitution(Edges.class) +public class EdgesSubstitutions { + + @MethodSubstitution + private static Node getNode(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) { + 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); + } + +}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java Wed Sep 24 17:17:27 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +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.graal.replacements; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; - -/** - * Substitutions for improving the performance of some critical methods in {@link NodeClass} - * methods. These substitutions improve the performance by forcing the relevant methods to be - * inlined (intrinsification being a special form of inlining) and removing a checked cast. The - * latter cannot be done directly in Java code as {@link PiNode} is not available to the project - * containing {@link NodeClass}. - */ -@ClassSubstitution(NodeClass.class) -public class NodeClassSubstitutions { - - @MethodSubstitution - private static Node getNode(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) { - 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); - } - -}