changeset 17008:81c9a1fc9072

select generated input and successor iterators if Node.USE_GENERATED_NODES
author Doug Simon <doug.simon@oracle.com>
date Tue, 02 Sep 2014 00:44:43 +0200
parents 9716891b7342
children 2c04d7665bf6
files graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodePosIterator.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterable.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterator.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeGenerator.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java
diffstat 18 files changed, 264 insertions(+), 107 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Sep 02 00:44:43 2014 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Node.ValueNumberable;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.iterators.*;
 
 /**
@@ -278,7 +277,7 @@
     }
 
     public <T extends Node> T addOrUniqueWithInputs(T node) {
-        NodeClassIterator iterator = node.inputs().iterator();
+        NodePosIterator iterator = node.inputs().iterator();
         while (iterator.hasNext()) {
             Position pos = iterator.nextPosition();
             Node input = pos.get(node);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Sep 02 00:44:43 2014 +0200
@@ -28,7 +28,6 @@
 import java.util.*;
 
 import com.oracle.graal.graph.Graph.NodeEventListener;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodeinfo.*;
@@ -197,6 +196,9 @@
      * @return an {@link NodeClassIterable iterable} for all non-null input edges.
      */
     public NodeClassIterable inputs() {
+        if (USE_GENERATED_NODES) {
+            return inputsV2();
+        }
         return getNodeClass().getInputIterable(this);
     }
 
@@ -207,6 +209,9 @@
      * @return an {@link NodeClassIterable iterable} for all non-null successor edges.
      */
     public NodeClassIterable successors() {
+        if (USE_GENERATED_NODES) {
+            return successorsV2();
+        }
         return getNodeClass().getSuccessorIterable(this);
     }
 
@@ -610,7 +615,7 @@
     public void replaceAtUsages(InputType type, Node other) {
         assert checkReplaceWith(other);
         for (Node usage : usages().snapshot()) {
-            NodeClassIterator iter = usage.inputs().iterator();
+            NodePosIterator iter = usage.inputs().iterator();
             while (iter.hasNext()) {
                 Position pos = iter.nextPosition();
                 if (pos.getInputType(usage) == type && pos.get(usage) == this) {
@@ -822,7 +827,7 @@
             for (Node usage : usages()) {
                 assertFalse(usage.isDeleted(), "usage %s must never be deleted", usage);
                 assertTrue(usage.inputs().contains(this), "missing input in usage %s", usage);
-                NodeClassIterator iterator = usage.inputs().iterator();
+                NodePosIterator iterator = usage.inputs().iterator();
                 while (iterator.hasNext()) {
                     Position pos = iterator.nextPosition();
                     if (pos.get(usage) == this && pos.getInputType(usage) != InputType.Unchecked) {
@@ -832,7 +837,7 @@
                 }
             }
         }
-        NodeClassIterator iterator = inputs().withNullIterator();
+        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)";
@@ -980,7 +985,7 @@
                 formatter.format("}");
             }
 
-            NodeClassIterator inputIter = inputs().iterator();
+            NodePosIterator inputIter = inputs().iterator();
             while (inputIter.hasNext()) {
                 Position position = inputIter.nextPosition();
                 Node input = nodeClass.get(this, position);
@@ -1008,7 +1013,7 @@
                 formatter.format("}");
             }
 
-            NodeClassIterator succIter = successors().iterator();
+            NodePosIterator succIter = successors().iterator();
             while (succIter.hasNext()) {
                 Position position = succIter.nextPosition();
                 Node successor = nodeClass.get(this, position);
@@ -1025,8 +1030,12 @@
 
     // NEW API IMPLEMENTED BY GENERATED METHODS - NOT YET USED
 
-    public NodeRefIterable inputsV2() {
-        return NodeRefIterable.Empty;
+    public NodeClassIterable inputsV2() {
+        return NodeClassIterable.Empty;
+    }
+
+    public NodeClassIterable successorsV2() {
+        return NodeClassIterable.Empty;
     }
 
     public Collection<Position> getFirstLevelInputs() {
@@ -1038,6 +1047,57 @@
     }
 
     /**
+     * Gets an input or successor of this node at a given position.
+     *
+     * @param pos
+     */
+    public Node getNodeAt(Position pos) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * Gets an input or successor list at a given position.
+     *
+     * @param position
+     */
+    public NodeList<? extends Node> getNodeListAt(Position position) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * Sets an input or successor list at a given position.
+     *
+     * @param position
+     * @param list
+     */
+    public void setNodeListAt(Position position, NodeList<? extends Node> list) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * Updates an input or successor of this node at a given position. The existing, non-null input
+     * or successor at {@code position} is notified of the change via
+     * {@link #updateUsages(Node, Node)} or {@link #updatePredecessor(Node, Node)}.
+     *
+     * @param position
+     * @param value
+     */
+    public void updateNodeAt(Position position, Node value) {
+        throw new NoSuchElementException();
+    }
+
+    /**
+     * Sets an input or successor of this node at a given position without notifying the existing
+     * input or successor at {@code position} of the change.
+     *
+     * @param position
+     * @param value
+     */
+    public void initializeNodeAt(Position position, Node value) {
+        throw new NoSuchElementException();
+    }
+
+    /**
      * @param pos
      */
     public InputType getInputTypeAt(Position pos) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Tue Sep 02 00:44:43 2014 +0200
@@ -133,6 +133,39 @@
         this(clazz, new DefaultCalcOffset(), null, 0);
     }
 
+    /**
+     * Defines the order of fields in a node class that accessed via {@link Position}s.
+     */
+    public interface PositionFieldOrder {
+        /**
+         * Gets a field ordering specified by an ordered field name list. The only guarantee
+         * provided by this method is that all {@link NodeList} fields are preceded by all non
+         * {@link NodeList} fields.
+         *
+         * @param input specified whether input or successor field order is being requested
+         */
+        String[] getOrderedFieldNames(boolean input);
+    }
+
+    private static long[] sortedOffsets(boolean input, PositionFieldOrder pfo, Map<Long, String> names, ArrayList<Long> list1, ArrayList<Long> list2) {
+        if (list1.isEmpty() && list2.isEmpty()) {
+            return new long[0];
+        }
+        if (pfo != null) {
+            List<String> fields = Arrays.asList(pfo.getOrderedFieldNames(input));
+            long[] offsets = new long[fields.size()];
+            assert list1.size() + list2.size() == fields.size();
+            for (Map.Entry<Long, String> e : names.entrySet()) {
+                int index = fields.indexOf(e.getValue());
+                if (index != -1) {
+                    offsets[index] = e.getKey();
+                }
+            }
+            return offsets;
+        }
+        return sortedLongCopy(list1, list2);
+    }
+
     public NodeClass(Class<?> clazz, CalcOffset calcOffset, int[] presetIterableIds, int presetIterableId) {
         super(clazz);
         assert NODE_CLASS.isAssignableFrom(clazz);
@@ -148,7 +181,13 @@
         scanner.scan(clazz);
 
         directInputCount = scanner.inputOffsets.size();
-        inputOffsets = sortedLongCopy(scanner.inputOffsets, scanner.inputListOffsets);
+
+        isLeafNode = scanner.inputOffsets.isEmpty() && scanner.inputListOffsets.isEmpty() && scanner.successorOffsets.isEmpty() && scanner.successorListOffsets.isEmpty();
+
+        PositionFieldOrder pfo = lookupPositionFieldOrder(clazz);
+
+        inputOffsets = sortedOffsets(true, pfo, scanner.fieldNames, scanner.inputOffsets, scanner.inputListOffsets);
+
         inputTypes = new InputType[inputOffsets.length];
         inputOptional = new boolean[inputOffsets.length];
         for (int i = 0; i < inputOffsets.length; i++) {
@@ -157,7 +196,7 @@
             inputOptional[i] = scanner.optionalInputs.contains(inputOffsets[i]);
         }
         directSuccessorCount = scanner.successorOffsets.size();
-        successorOffsets = sortedLongCopy(scanner.successorOffsets, scanner.successorListOffsets);
+        successorOffsets = sortedOffsets(false, pfo, scanner.fieldNames, scanner.successorOffsets, scanner.successorListOffsets);
 
         dataOffsets = sortedLongCopy(scanner.dataOffsets);
         dataTypes = new Class[dataOffsets.length];
@@ -232,10 +271,21 @@
             this.iterableId = Node.NOT_ITERABLE;
             this.iterableIds = null;
         }
-        isLeafNode = (this.inputOffsets.length == 0 && this.successorOffsets.length == 0);
         nodeIterableCount = Debug.metric("NodeIterable_%s", shortName);
     }
 
+    private PositionFieldOrder lookupPositionFieldOrder(Class<?> clazz) throws GraalInternalError {
+        if (USE_GENERATED_NODES && !isAbstract(clazz.getModifiers()) && !isLeafNode) {
+            String name = clazz.getName().replace('$', '_') + "Gen$FieldOrder";
+            try {
+                return (PositionFieldOrder) Class.forName(name).newInstance();
+            } catch (Exception e) {
+                throw new GraalInternalError("Could not find generated class " + name + " for " + getClazz());
+            }
+        }
+        return null;
+    }
+
     /**
      * Gets the {@linkplain GeneratedNode generated} node class (if any) described by the object.
      */
@@ -345,7 +395,6 @@
         public final ArrayList<Long> successorOffsets = new ArrayList<>();
         public final ArrayList<Long> successorListOffsets = new ArrayList<>();
         public final HashMap<Long, InputType> types = new HashMap<>();
-        public final HashMap<Long, String> names = new HashMap<>();
         public final HashSet<Long> optionalInputs = new HashSet<>();
 
         protected FieldScanner(CalcOffset calc) {
@@ -373,7 +422,6 @@
                 } else {
                     types.put(offset, field.getAnnotation(Node.OptionalInput.class).value());
                 }
-                names.put(offset, field.getName());
                 if (field.isAnnotationPresent(Node.OptionalInput.class)) {
                     optionalInputs.add(offset);
                 }
@@ -389,7 +437,6 @@
                     GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "Node successor field %s should not be final", field);
                     successorOffsets.add(offset);
                 }
-                names.put(offset, field.getName());
             } else {
                 GraalInternalError.guarantee(!NODE_CLASS.isAssignableFrom(type) || field.getName().equals("Null"), "suspicious node field: %s", field);
                 GraalInternalError.guarantee(!INPUT_LIST_CLASS.isAssignableFrom(type), "suspicious node input list field: %s", field);
@@ -445,7 +492,7 @@
      * 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 Iterator<Node> {
+    public abstract static class NodeClassIterator implements NodePosIterator {
         protected final Node node;
         protected int index;
         protected int subIndex;
@@ -912,6 +959,9 @@
     }
 
     public Node get(Node node, Position pos) {
+        if (Node.USE_GENERATED_NODES) {
+            return node.getNodeAt(pos);
+        }
         long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()];
         if (pos.getSubIndex() == NOT_ITERABLE) {
             return getNode(node, offset);
@@ -931,6 +981,9 @@
     }
 
     public NodeList<?> getNodeList(Node node, Position pos) {
+        if (Node.USE_GENERATED_NODES) {
+            return node.getNodeListAt(pos);
+        }
         long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()];
         assert pos.getSubIndex() == Node.NODE_LIST;
         return getNodeList(node, offset);
@@ -1090,6 +1143,11 @@
     }
 
     public void set(Node node, Position pos, Node x) {
+        if (Node.USE_GENERATED_NODES) {
+            node.updateNodeAt(pos, x);
+            return;
+        }
+
         long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()];
         if (pos.getSubIndex() == NOT_ITERABLE) {
             Node old = getNode(node, offset);
@@ -1114,6 +1172,10 @@
     }
 
     public void initializePosition(Node node, Position pos, Node x) {
+        if (Node.USE_GENERATED_NODES) {
+            node.initializeNodeAt(pos, x);
+            return;
+        }
         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 + ")";
@@ -1586,7 +1648,7 @@
 
     private static void transferValuesDifferentNodeClass(final Graph graph, final DuplicationReplacement replacements, final Map<Node, Node> newNodes, Node oldNode, Node node, NodeClass oldNodeClass,
                     NodeClass nodeClass) {
-        for (NodeClassIterator iter = oldNode.inputs().iterator(); iter.hasNext();) {
+        for (NodePosIterator iter = oldNode.inputs().iterator(); iter.hasNext();) {
             Position pos = iter.nextPosition();
             if (!nodeClass.isValid(pos, oldNodeClass)) {
                 continue;
@@ -1608,7 +1670,7 @@
             nodeClass.set(node, pos, target);
         }
 
-        for (NodeClassIterator iter = oldNode.successors().iterator(); iter.hasNext();) {
+        for (NodePosIterator iter = oldNode.successors().iterator(); iter.hasNext();) {
             Position pos = iter.nextPosition();
             if (!nodeClass.isValid(pos, oldNodeClass)) {
                 continue;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClassIterable.java	Tue Sep 02 00:44:43 2014 +0200
@@ -22,12 +22,11 @@
  */
 package com.oracle.graal.graph;
 
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.iterators.*;
 
 /**
  * The iterator returned by this iterable can be used to access {@link Position Positions} during
- * iteration using {@link NodeClassIterator#nextPosition()}.
+ * iteration using {@link NodePosIterator#nextPosition()}.
  */
 public interface NodeClassIterable extends NodeIterable<Node> {
 
@@ -35,10 +34,21 @@
      * Returns an iterator that produces all non-null values.
      */
     @Override
-    NodeClassIterator iterator();
+    NodePosIterator iterator();
 
     /**
      * Returns an iterator that produces all values, including null values.
      */
-    NodeClassIterator withNullIterator();
+    NodePosIterator withNullIterator();
+
+    NodeClassIterable Empty = new NodeClassIterable() {
+
+        public NodeRefIterator withNullIterator() {
+            return NodeRefIterator.Empty;
+        }
+
+        public NodeRefIterator iterator() {
+            return NodeRefIterator.Empty;
+        }
+    };
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodePosIterator.java	Tue Sep 02 00:44:43 2014 +0200
@@ -0,0 +1,32 @@
+/*
+ * 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 java.util.*;
+
+/**
+ * Describes an edge slot for a {@link NodeClass}.
+ */
+public interface NodePosIterator extends Iterator<Node> {
+    Position nextPosition();
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterable.java	Mon Sep 01 16:46:59 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +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 com.oracle.graal.graph.iterators.*;
-
-/**
- * The iterator returned by this iterable can be used to access {@link Position Positions} during
- * iteration using {@link NodeRefIterator#nextPosition()}.
- */
-public interface NodeRefIterable extends NodeIterable<Node> {
-    /**
-     * Returns an iterator that produces all non-null values.
-     */
-    @Override
-    NodeRefIterator iterator();
-
-    /**
-     * Returns an iterator that produces all values, including null values.
-     */
-    NodeRefIterator withNullIterator();
-
-    NodeRefIterable Empty = new NodeRefIterable() {
-
-        public NodeRefIterator withNullIterator() {
-            return NodeRefIterator.Empty;
-        }
-
-        public NodeRefIterator iterator() {
-            return NodeRefIterator.Empty;
-        }
-    };
-}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterator.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeRefIterator.java	Tue Sep 02 00:44:43 2014 +0200
@@ -34,7 +34,7 @@
  * 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 class NodeRefIterator implements Iterator<Node> {
+public class NodeRefIterator implements NodePosIterator {
 
     public static final NodeRefIterator Empty = new NodeRefIterator(0, 0, false);
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Position.java	Tue Sep 02 00:44:43 2014 +0200
@@ -56,27 +56,47 @@
     }
 
     public Node get(Node node) {
+        if (Node.USE_GENERATED_NODES) {
+            return node.getNodeAt(this);
+        }
         return node.getNodeClass().get(node, this);
     }
 
     public InputType getInputType(Node node) {
+        if (Node.USE_GENERATED_NODES) {
+            return node.getInputTypeAt(this);
+        }
         return node.getNodeClass().getInputType(this);
     }
 
     public String getInputName(Node node) {
+        if (Node.USE_GENERATED_NODES) {
+            return node.getNameOf(this);
+        }
         return node.getNodeClass().getName(this);
     }
 
     public boolean isInputOptional(Node node) {
+        if (Node.USE_GENERATED_NODES) {
+            return node.isOptionalInputAt(this);
+        }
         return node.getNodeClass().isInputOptional(this);
     }
 
     public void set(Node node, Node value) {
-        node.getNodeClass().set(node, this, value);
+        if (Node.USE_GENERATED_NODES) {
+            node.updateNodeAt(this, value);
+        } else {
+            node.getNodeClass().set(node, this, value);
+        }
     }
 
     public void initialize(Node node, Node value) {
-        node.getNodeClass().initializePosition(node, this, value);
+        if (Node.USE_GENERATED_NODES) {
+            node.initializeNodeAt(this, value);
+        } else {
+            node.getNodeClass().initializePosition(node, this, value);
+        }
     }
 
     @Override
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Tue Sep 02 00:44:43 2014 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -86,7 +85,7 @@
          * The code below assumes that all of the control split nodes have the same successor
          * structure, which should have been enforced by findUnswitchable.
          */
-        NodeClassIterator successors = firstNode.successors().iterator();
+        NodePosIterator successors = firstNode.successors().iterator();
         assert successors.hasNext();
         // original loop is used as first successor
         Position firstPosition = successors.nextPosition();
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Tue Sep 02 00:44:43 2014 +0200
@@ -28,7 +28,7 @@
 
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.*;
@@ -84,7 +84,7 @@
         sb.append(loop).append(" at ");
         for (ControlSplitNode controlSplit : controlSplits) {
             sb.append(controlSplit).append(" [");
-            NodeClassIterator it = controlSplit.successors().iterator();
+            NodePosIterator it = controlSplit.successors().iterator();
             while (it.hasNext()) {
                 sb.append(controlSplit.probability((BeginNode) it.next()));
                 if (it.hasNext()) {
--- a/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeGenerator.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeGenerator.java	Tue Sep 02 00:44:43 2014 +0200
@@ -119,12 +119,16 @@
         return typeElement;
     }
 
+    public TypeElement getTypeElement(Class<?> cls) {
+        return getTypeElement(cls.getName());
+    }
+
     public TypeMirror getType(String name) {
         return getTypeElement(name).asType();
     }
 
-    public TypeMirror getType(Class<?> primitiveClass) {
-        return ElementUtils.getType(getProcessingEnv(), primitiveClass);
+    public TypeMirror getType(Class<?> cls) {
+        return ElementUtils.getType(getProcessingEnv(), cls);
     }
 
     public ProcessingEnvironment getProcessingEnv() {
@@ -325,7 +329,8 @@
                 createGetNameOfMethod();
                 createUpdateOrInitializeNodeAtMethod(false);
                 createUpdateOrInitializeNodeAtMethod(true);
-                createIsLeafNodeMethod(genClass);
+                createIsLeafNodeMethod();
+                createPositionAccessibleFieldOrderClass(packageElement);
 
                 if (!inputListFields.isEmpty() || !successorListFields.isEmpty()) {
                     createGetNodeListAtMethod();
@@ -431,10 +436,10 @@
         }
     }
 
-    private void createIsLeafNodeMethod(CodeTypeElement cls) {
+    private void createIsLeafNodeMethod() {
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(boolean.class), "isLeafNode");
         method.createBuilder().startReturn().string("false").end();
-        cls.add(method);
+        genClass.add(method);
         checkOnlyInGenNode(method);
     }
 
@@ -609,6 +614,29 @@
         b.end();
     }
 
+    private void createPositionAccessibleFieldOrderClass(PackageElement packageElement) {
+        CodeTypeElement cls = new CodeTypeElement(modifiers(PUBLIC, STATIC), ElementKind.CLASS, packageElement, "FieldOrder");
+        cls.getImplements().add(getType("com.oracle.graal.graph.NodeClass.PositionFieldOrder"));
+
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), getType(String[].class), "getOrderedFieldNames");
+
+        method.addParameter(new CodeVariableElement(getType(boolean.class), "input"));
+
+        CodeTreeBuilder b = method.createBuilder();
+        b.startIf().string("input").end().startBlock();
+        String initializer = concat(inputFields, inputListFields).stream().map(v -> v.getSimpleName().toString()).collect(Collectors.joining("\", \"", "\"", "\""));
+        b.startStatement().string("return new String[] {", initializer, "}").end();
+        b.end();
+        b.startElseBlock();
+        initializer = concat(successorFields, successorListFields).stream().map(v -> v.getSimpleName().toString()).collect(Collectors.joining("\", \"", "\"", "\""));
+        b.startStatement().string("return new String[] {", initializer, "}").end();
+        b.end();
+        cls.add(method);
+
+        genClass.add(cls);
+
+    }
+
     private void createAllIteratorClass(NodeRefsType nodeRefsType, TypeMirror inputsIteratorType, PackageElement packageElement, List<VariableElement> nodeFields, List<VariableElement> nodeListFields) {
 
         String name = "All" + nodeRefsType + "Iterator";
@@ -697,7 +725,7 @@
 
         String name = nodeRefsType + "Iterable";
         CodeTypeElement cls = new CodeTypeElement(modifiers(PRIVATE), ElementKind.CLASS, packageElement, name);
-        cls.getImplements().add(getType("com.oracle.graal.graph.NodeRefIterable"));
+        cls.getImplements().add(getType("com.oracle.graal.graph.NodeClassIterable"));
 
         // iterator() method
         CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeRefIterator"), "iterator");
@@ -711,7 +739,7 @@
         cls.add(method);
 
         // withNullIterator() method
-        method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeRefIterator"), "withNullIterator");
+        method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodePosIterator"), "withNullIterator");
         b = method.createBuilder();
         b.startStatement().string("return new All" + nodeRefsType + "Iterator()").end();
         cls.add(method);
@@ -747,7 +775,7 @@
     private static final String API_TAG = "V2";
 
     private void createIterableMethod(NodeRefsType nodeRefsType) {
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeRefIterable"), (nodeRefsType == Inputs ? "inputs" : "successors") +
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType("com.oracle.graal.graph.NodeClassIterable"), (nodeRefsType == Inputs ? "inputs" : "successors") +
                         API_TAG);
         CodeTreeBuilder b = method.createBuilder();
         b.startStatement().string("return new " + nodeRefsType + "Iterable()").end();
@@ -784,7 +812,7 @@
     }
 
     private void createSetNodeListAtMethod() {
-        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(void.class), "SetNodeListAt");
+        CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, FINAL), getType(void.class), "setNodeListAt");
 
         DeclaredType suppress = (DeclaredType) getType(SuppressWarnings.class);
         CodeAnnotationMirror suppressMirror = new CodeAnnotationMirror(suppress);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Tue Sep 02 00:44:43 2014 +0200
@@ -25,7 +25,7 @@
 import java.util.*;
 
 import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
@@ -127,7 +127,7 @@
     }
 
     private static BeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) {
-        NodeClassIterator successors = controlSplit.successors().iterator();
+        NodePosIterator successors = controlSplit.successors().iterator();
         BeginNode min = (BeginNode) successors.next();
         int minUsages = min.usages().count();
         while (successors.hasNext()) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Tue Sep 02 00:44:43 2014 +0200
@@ -33,7 +33,6 @@
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
@@ -497,7 +496,7 @@
             Node newOutsideClone = null;
             for (Node usage : unique) {
                 if (!duplicatedNodes.contains(usage)) {
-                    NodeClassIterator iter = usage.inputs().iterator();
+                    NodePosIterator iter = usage.inputs().iterator();
                     while (iter.hasNext()) {
                         Position pos = iter.nextPosition();
                         if (pos.get(usage) == duplicated) {
@@ -545,7 +544,7 @@
 
         private void processInputs(Node duplicated, HashSet<Node> duplicatedNodes, Deque<Node> worklist) {
             // check if this node has an input that lies outside and cannot be shared
-            NodeClassIterator iter = duplicated.inputs().iterator();
+            NodePosIterator iter = duplicated.inputs().iterator();
             while (iter.hasNext()) {
                 Position pos = iter.nextPosition();
                 Node input = pos.get(duplicated);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java	Tue Sep 02 00:44:43 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.
              */
@@ -229,7 +229,7 @@
     @SuppressWarnings("unchecked")
     public static List<ValueNode> distinctValueAndConditionInputs(Node n) {
         ArrayList<ValueNode> result = null;
-        NodeClass.NodeClassIterator iter = n.inputs().iterator();
+        NodePosIterator iter = n.inputs().iterator();
         while (iter.hasNext()) {
             Position pos = iter.nextPosition();
             InputType inputType = pos.getInputType(n);
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Tue Sep 02 00:44:43 2014 +0200
@@ -26,7 +26,7 @@
 
 import java.util.*;
 
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 
 public final class ReentrantNodeIterator {
@@ -110,7 +110,7 @@
                 state = closure.processNode(current, state);
 
                 if (closure.continueIteration(state)) {
-                    NodeClassIterator successors = current.successors().iterator();
+                    NodePosIterator successors = current.successors().iterator();
                     if (!successors.hasNext()) {
                         if (current instanceof LoopEndNode) {
                             blockEndStates.put(current, state);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Tue Sep 02 00:44:43 2014 +0200
@@ -34,7 +34,6 @@
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
 import com.oracle.graal.lir.*;
@@ -367,7 +366,7 @@
         out.print(COLUMN_END).print(' ').println(COLUMN_END);
     }
 
-    private void printNamedNodes(Node node, NodeClassIterator iter, String prefix, String suffix, String hideSuffix) {
+    private void printNamedNodes(Node node, NodePosIterator iter, String prefix, String suffix, String hideSuffix) {
         int lastIndex = -1;
         while (iter.hasNext()) {
             Position pos = iter.nextPosition();
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Tue Sep 02 00:44:43 2014 +0200
@@ -30,7 +30,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
@@ -213,7 +212,7 @@
 
             // successors
             int fromIndex = 0;
-            NodeClassIterator succIter = node.successors().iterator();
+            NodePosIterator succIter = node.successors().iterator();
             while (succIter.hasNext()) {
                 Position position = succIter.nextPosition();
                 Node successor = node.getNodeClass().get(node, position);
@@ -225,7 +224,7 @@
 
             // inputs
             int toIndex = 1;
-            NodeClassIterator inputIter = node.inputs().iterator();
+            NodePosIterator inputIter = node.inputs().iterator();
             while (inputIter.hasNext()) {
                 Position position = inputIter.nextPosition();
                 Node input = node.getNodeClass().get(node, position);
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Mon Sep 01 16:46:59 2014 +0200
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Tue Sep 02 00:44:43 2014 +0200
@@ -41,6 +41,9 @@
 public class ElementUtils {
 
     public static TypeMirror getType(ProcessingEnvironment processingEnv, Class<?> element) {
+        if (element.isArray()) {
+            return processingEnv.getTypeUtils().getArrayType(getType(processingEnv, element.getComponentType()));
+        }
         if (element.isPrimitive()) {
             if (element == void.class) {
                 return processingEnv.getTypeUtils().getNoType(TypeKind.VOID);