Mercurial > hg > truffle
diff graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java @ 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
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Thu, 25 Sep 2014 10:27:17 +0200 |
parents | 55a924683e72 |
children | f4b939d433a4 |
line wrap: on
line diff
--- 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() {