changeset 20129:5b7db8941fd7

Truffle: make NodeClass and NodeField a top-level class.
author Christian Humer <christian.humer@gmail.com>
date Thu, 02 Apr 2015 01:22:41 +0200
parents 7ad60a16bbb0
children 8dc73c226c63
files graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/TraceCompilationASTListener.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeFailure.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeFieldAccessor.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java
diffstat 11 files changed, 547 insertions(+), 485 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/TraceCompilationASTListener.java	Thu Apr 02 14:28:27 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/TraceCompilationASTListener.java	Thu Apr 02 01:22:41 2015 +0200
@@ -30,9 +30,8 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.truffle.*;
-import com.oracle.graal.truffle.TruffleInlining.*;
+import com.oracle.graal.truffle.TruffleInlining.CallTreeNodeVisitor;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeUtil.*;
 
 public final class TraceCompilationASTListener extends AbstractDebugCompilationListener {
 
@@ -65,8 +64,8 @@
                     p.println(node.getClass().getSimpleName());
                 } else {
                     String fieldName = "unknownField";
-                    NodeField[] fields = NodeClass.get(parent.getClass()).getFields();
-                    for (NodeField field : fields) {
+                    NodeFieldAccessor[] fields = NodeClass.get(parent.getClass()).getFields();
+                    for (NodeFieldAccessor field : fields) {
                         Object value = field.loadValue(parent);
                         if (value == node) {
                             fieldName = field.getName();
--- a/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java	Thu Apr 02 14:28:27 2015 +0200
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java	Thu Apr 02 01:22:41 2015 +0200
@@ -39,8 +39,7 @@
 import com.oracle.truffle.api.dsl.internal.SlowPathEvent.SlowPathEventN;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeClass;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeField;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor;
 
 /**
  * Internal implementation dependent base class for generated specialized nodes.
@@ -80,9 +79,9 @@
     }
 
     private static void updateRootImpl(SpecializationNode start, Node node) {
-        NodeField[] fields = NodeClass.get(start.getClass()).getFields();
+        NodeFieldAccessor[] fields = NodeClass.get(start.getClass()).getFields();
         for (int i = fields.length - 1; i >= 0; i--) {
-            NodeField f = fields[i];
+            NodeFieldAccessor f = fields[i];
             if (f.getName().equals("root")) {
                 f.putObject(start, node);
                 break;
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeFailure.java	Thu Apr 02 14:28:27 2015 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/ProbeFailure.java	Thu Apr 02 01:22:41 2015 +0200
@@ -26,7 +26,6 @@
 
 import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeField;
 
 /**
  * Description of a failed attempt to instrument an AST node.
@@ -125,7 +124,7 @@
             sb.append("parent=" + parent.getClass().getSimpleName() + " ");
             if (child != null) {
                 sb.append("child=" + child.getClass().getSimpleName() + " ");
-                final NodeField field = NodeUtil.findChildField(parent, child);
+                final NodeFieldAccessor field = NodeUtil.findChildField(parent, child);
                 if (field != null) {
                     sb.append("field=" + field.getName() + " ");
                 }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java	Thu Apr 02 14:28:27 2015 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java	Thu Apr 02 01:22:41 2015 +0200
@@ -29,9 +29,7 @@
 
 import com.oracle.truffle.api.instrument.*;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeClass;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeField;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
 import com.oracle.truffle.api.source.*;
 
 /**
@@ -76,9 +74,9 @@
 
         p.print(NodeUtil.printSyntaxTags(node));
 
-        ArrayList<NodeField> childFields = new ArrayList<>();
+        ArrayList<NodeFieldAccessor> childFields = new ArrayList<>();
 
-        for (NodeField field : NodeClass.get(node.getClass()).getFields()) {
+        for (NodeFieldAccessor field : NodeClass.get(node.getClass()).getFields()) {
             if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) {
                 childFields.add(field);
             } else if (field.getKind() == NodeFieldKind.DATA) {
@@ -100,7 +98,7 @@
 
             if (childFields.size() != 0) {
                 p.print(" {");
-                for (NodeField field : childFields) {
+                for (NodeFieldAccessor field : childFields) {
 
                     Object value = field.loadValue(node);
                     if (value == null) {
@@ -122,7 +120,7 @@
         }
     }
 
-    protected void printChildren(PrintWriter p, int maxDepth, Node markNode, int level, NodeField field, Object value) {
+    protected void printChildren(PrintWriter p, int maxDepth, Node markNode, int level, NodeFieldAccessor field, Object value) {
         printNewLine(p, level);
         p.print(field.getName());
         Node[] children = (Node[]) value;
@@ -136,7 +134,7 @@
         p.print("]");
     }
 
-    protected void printChild(PrintWriter p, int maxDepth, Node markNode, int level, NodeField field, Object value) {
+    protected void printChild(PrintWriter p, int maxDepth, Node markNode, int level, NodeFieldAccessor field, Object value) {
         final Node valueNode = (Node) value;
         printNewLine(p, level, valueNode == markNode);
         p.print(field.getName());
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Thu Apr 02 14:28:27 2015 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java	Thu Apr 02 01:22:41 2015 +0200
@@ -36,9 +36,7 @@
 
 import org.w3c.dom.*;
 
-import com.oracle.truffle.api.nodes.NodeUtil.NodeClass;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeField;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
 
 /**
  * Utility class for creating output for the ideal graph visualizer.
@@ -264,8 +262,8 @@
     }
 
     private void readNodeProperties(Node node) {
-        NodeField[] fields = NodeClass.get(node.getClass()).getFields();
-        for (NodeField field : fields) {
+        NodeFieldAccessor[] fields = NodeClass.get(node.getClass()).getFields();
+        for (NodeFieldAccessor field : fields) {
             if (field.getKind() == NodeFieldKind.DATA) {
                 String key = field.getName();
                 if (getPropertyElement(node, key) == null) {
@@ -343,7 +341,7 @@
         LinkedHashMap<String, Node> nodes = new LinkedHashMap<>();
         NodeClass nodeClass = NodeClass.get(node.getClass());
 
-        for (NodeField field : nodeClass.getFields()) {
+        for (NodeFieldAccessor field : nodeClass.getFields()) {
             NodeFieldKind kind = field.getKind();
             if (kind == NodeFieldKind.CHILD || kind == NodeFieldKind.CHILDREN) {
                 Object value = field.loadValue(node);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java	Thu Apr 02 01:22:41 2015 +0200
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.nodes;
+
+import java.lang.reflect.*;
+import java.security.*;
+import java.util.*;
+
+import com.oracle.truffle.api.nodes.Node.Child;
+import com.oracle.truffle.api.nodes.Node.Children;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
+
+/**
+ * Information about a {@link Node} class. A single instance of this class is allocated for every
+ * subclass of {@link Node} that is used.
+ */
+public final class NodeClass {
+    private static final ClassValue<NodeClass> nodeClasses = new ClassValue<NodeClass>() {
+        @SuppressWarnings("unchecked")
+        @Override
+        protected NodeClass computeValue(final Class<?> clazz) {
+            assert Node.class.isAssignableFrom(clazz);
+            return AccessController.doPrivileged(new PrivilegedAction<NodeClass>() {
+                public NodeClass run() {
+                    return new NodeClass((Class<? extends Node>) clazz);
+                }
+            });
+        }
+    };
+
+    // The comprehensive list of all fields.
+    private final NodeFieldAccessor[] fields;
+    // Separate arrays for the frequently accessed fields.
+    private final NodeFieldAccessor parentField;
+    private final NodeFieldAccessor[] childFields;
+    private final NodeFieldAccessor[] childrenFields;
+    private final NodeFieldAccessor[] cloneableFields;
+
+    private final Class<? extends Node> clazz;
+
+    public static NodeClass get(Class<? extends Node> clazz) {
+        return nodeClasses.get(clazz);
+    }
+
+    public NodeClass(Class<? extends Node> clazz) {
+        List<NodeFieldAccessor> fieldsList = new ArrayList<>();
+        NodeFieldAccessor parentFieldTmp = null;
+        List<NodeFieldAccessor> childFieldList = new ArrayList<>();
+        List<NodeFieldAccessor> childrenFieldList = new ArrayList<>();
+        List<NodeFieldAccessor> cloneableFieldList = new ArrayList<>();
+
+        for (Field field : NodeUtil.getAllFields(clazz)) {
+            if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) {
+                continue;
+            }
+
+            NodeFieldAccessor nodeField;
+            if (field.getDeclaringClass() == Node.class && field.getName().equals("parent")) {
+                assert Node.class.isAssignableFrom(field.getType());
+                nodeField = NodeFieldAccessor.create(NodeFieldKind.PARENT, field);
+                parentFieldTmp = nodeField;
+            } else if (field.getAnnotation(Child.class) != null) {
+                checkChildField(field);
+                nodeField = NodeFieldAccessor.create(NodeFieldKind.CHILD, field);
+                childFieldList.add(nodeField);
+            } else if (field.getAnnotation(Children.class) != null) {
+                checkChildrenField(field);
+                nodeField = NodeFieldAccessor.create(NodeFieldKind.CHILDREN, field);
+                childrenFieldList.add(nodeField);
+            } else {
+                nodeField = NodeFieldAccessor.create(NodeFieldKind.DATA, field);
+                if (NodeCloneable.class.isAssignableFrom(field.getType())) {
+                    cloneableFieldList.add(nodeField);
+                }
+            }
+            fieldsList.add(nodeField);
+        }
+
+        if (parentFieldTmp == null) {
+            throw new AssertionError("parent field not found");
+        }
+
+        this.fields = fieldsList.toArray(new NodeFieldAccessor[fieldsList.size()]);
+        this.parentField = parentFieldTmp;
+        this.childFields = childFieldList.toArray(new NodeFieldAccessor[childFieldList.size()]);
+        this.childrenFields = childrenFieldList.toArray(new NodeFieldAccessor[childrenFieldList.size()]);
+        this.cloneableFields = cloneableFieldList.toArray(new NodeFieldAccessor[cloneableFieldList.size()]);
+        this.clazz = clazz;
+    }
+
+    public NodeFieldAccessor[] getCloneableFields() {
+        return cloneableFields;
+    }
+
+    private static boolean isNodeType(Class<?> clazz) {
+        return Node.class.isAssignableFrom(clazz) || (clazz.isInterface() && NodeInterface.class.isAssignableFrom(clazz));
+    }
+
+    private static void checkChildField(Field field) {
+        if (!isNodeType(field.getType())) {
+            throw new AssertionError("@Child field type must be a subclass of Node or an interface extending NodeInterface (" + field + ")");
+        }
+        if (Modifier.isFinal(field.getModifiers())) {
+            throw new AssertionError("@Child field must not be final (" + field + ")");
+        }
+    }
+
+    private static void checkChildrenField(Field field) {
+        if (!(field.getType().isArray() && isNodeType(field.getType().getComponentType()))) {
+            throw new AssertionError("@Children field type must be an array of a subclass of Node or an interface extending NodeInterface (" + field + ")");
+        }
+        if (!Modifier.isFinal(field.getModifiers())) {
+            throw new AssertionError("@Children field must be final (" + field + ")");
+        }
+    }
+
+    public NodeFieldAccessor[] getFields() {
+        return fields;
+    }
+
+    public NodeFieldAccessor getParentField() {
+        return parentField;
+    }
+
+    public NodeFieldAccessor[] getChildFields() {
+        return childFields;
+    }
+
+    public NodeFieldAccessor[] getChildrenFields() {
+        return childrenFields;
+    }
+
+    @Override
+    public int hashCode() {
+        return clazz.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof NodeClass) {
+            NodeClass other = (NodeClass) obj;
+            return clazz.equals(other.clazz);
+        }
+        return false;
+    }
+
+    public Iterator<Node> makeIterator(Node node) {
+        assert clazz.isInstance(node);
+        return new NodeIterator(this, node);
+    }
+
+    private static final class NodeIterator implements Iterator<Node> {
+        private final NodeFieldAccessor[] childFields;
+        private final NodeFieldAccessor[] childrenFields;
+        private final Node node;
+        private final int childrenCount;
+        private int index;
+
+        protected NodeIterator(NodeClass nodeClass, Node node) {
+            this.childFields = nodeClass.getChildFields();
+            this.childrenFields = nodeClass.getChildrenFields();
+            this.node = node;
+            this.childrenCount = childrenCount();
+            this.index = 0;
+        }
+
+        private int childrenCount() {
+            int nodeCount = childFields.length;
+            for (NodeFieldAccessor childrenField : childrenFields) {
+                Object[] children = ((Object[]) childrenField.getObject(node));
+                if (children != null) {
+                    nodeCount += children.length;
+                }
+            }
+            return nodeCount;
+        }
+
+        private Node nodeAt(int idx) {
+            int nodeCount = childFields.length;
+            if (idx < nodeCount) {
+                return (Node) childFields[idx].getObject(node);
+            } else {
+                for (NodeFieldAccessor childrenField : childrenFields) {
+                    Object[] nodeArray = (Object[]) childrenField.getObject(node);
+                    if (idx < nodeCount + nodeArray.length) {
+                        return (Node) nodeArray[idx - nodeCount];
+                    }
+                    nodeCount += nodeArray.length;
+                }
+            }
+            return null;
+        }
+
+        private void forward() {
+            if (index < childrenCount) {
+                index++;
+            }
+        }
+
+        public boolean hasNext() {
+            return index < childrenCount;
+        }
+
+        public Node next() {
+            try {
+                return nodeAt(index);
+            } finally {
+                forward();
+            }
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeFieldAccessor.java	Thu Apr 02 01:22:41 2015 +0200
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.nodes;
+
+import java.lang.reflect.*;
+
+import sun.misc.*;
+
+import com.oracle.truffle.api.nodes.Node.Child;
+import com.oracle.truffle.api.nodes.Node.Children;
+import com.oracle.truffle.api.nodes.NodeUtil.FieldOffsetProvider;
+
+/**
+ * Information about a field in a {@link Node} class.
+ */
+public abstract class NodeFieldAccessor {
+
+    public static enum NodeFieldKind {
+        /** The single {@link Node#getParent() parent} field. */
+        PARENT,
+        /** A field annotated with {@link Child}. */
+        CHILD,
+        /** A field annotated with {@link Children}. */
+        CHILDREN,
+        /** A normal non-child data field of the node. */
+        DATA
+    }
+
+    private static final boolean USE_UNSAFE = Boolean.getBoolean("truffle.unsafe");
+
+    private final NodeFieldKind kind;
+    private final String name;
+    protected final Class<?> type;
+    protected final long offset;
+
+    protected NodeFieldAccessor(NodeFieldKind kind, Field field) {
+        this.kind = kind;
+        this.type = field.getType();
+        this.name = field.getName();
+        this.offset = unsafeFieldOffsetProvider.objectFieldOffset(field);
+    }
+
+    protected static NodeFieldAccessor create(NodeFieldKind kind, Field field) {
+        if (USE_UNSAFE) {
+            return new UnsafeNodeField(kind, field);
+        } else {
+            return new ReflectionNodeField(kind, field);
+        }
+    }
+
+    public NodeFieldKind getKind() {
+        return kind;
+    }
+
+    public Class<?> getType() {
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public long getOffset() {
+        return offset;
+    }
+
+    public abstract void putObject(Node receiver, Object value);
+
+    public abstract Object getObject(Node receiver);
+
+    public abstract Object loadValue(Node node);
+
+    @Override
+    public int hashCode() {
+        return kind.hashCode() | type.hashCode() | name.hashCode() | ((Long) offset).hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof NodeFieldAccessor) {
+            NodeFieldAccessor other = (NodeFieldAccessor) obj;
+            return offset == other.offset && name.equals(other.name) && type.equals(other.type) && kind.equals(other.kind);
+        }
+        return false;
+    }
+
+    private static final Unsafe unsafe = getUnsafe();
+
+    private static Unsafe getUnsafe() {
+        try {
+            return Unsafe.getUnsafe();
+        } catch (SecurityException e) {
+        }
+        try {
+            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
+            theUnsafeInstance.setAccessible(true);
+            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
+        } catch (Exception e) {
+            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
+        }
+    }
+
+    private static final FieldOffsetProvider unsafeFieldOffsetProvider = new FieldOffsetProvider() {
+
+        @Override
+        public long objectFieldOffset(Field field) {
+            return unsafe.objectFieldOffset(field);
+        }
+
+        @Override
+        public int getTypeSize(Class<?> clazz) {
+            if (!clazz.isPrimitive()) {
+                return Unsafe.ARRAY_OBJECT_INDEX_SCALE;
+            } else if (clazz == int.class) {
+                return Unsafe.ARRAY_INT_INDEX_SCALE;
+            } else {
+                throw new UnsupportedOperationException("unsupported field type: " + clazz);
+            }
+        }
+    };
+
+    private static final class UnsafeNodeField extends NodeFieldAccessor {
+
+        protected UnsafeNodeField(NodeFieldKind kind, Field field) {
+            super(kind, field);
+        }
+
+        @Override
+        public void putObject(Node receiver, Object value) {
+            if (!type.isPrimitive() && value == null || type.isInstance(value)) {
+                unsafe.putObject(receiver, offset, value);
+            } else {
+                throw new IllegalArgumentException();
+            }
+        }
+
+        @Override
+        public Object getObject(Node receiver) {
+            if (!type.isPrimitive()) {
+                return unsafe.getObject(receiver, offset);
+            } else {
+                throw new IllegalArgumentException();
+            }
+        }
+
+        @Override
+        public Object loadValue(Node node) {
+            if (type == boolean.class) {
+                return unsafe.getBoolean(node, offset);
+            } else if (type == byte.class) {
+                return unsafe.getByte(node, offset);
+            } else if (type == short.class) {
+                return unsafe.getShort(node, offset);
+            } else if (type == char.class) {
+                return unsafe.getChar(node, offset);
+            } else if (type == int.class) {
+                return unsafe.getInt(node, offset);
+            } else if (type == long.class) {
+                return unsafe.getLong(node, offset);
+            } else if (type == float.class) {
+                return unsafe.getFloat(node, offset);
+            } else if (type == double.class) {
+                return unsafe.getDouble(node, offset);
+            } else {
+                return unsafe.getObject(node, offset);
+            }
+        }
+    }
+
+    private static final class ReflectionNodeField extends NodeFieldAccessor {
+        private final Field field;
+
+        protected ReflectionNodeField(NodeFieldKind kind, Field field) {
+            super(kind, field);
+            this.field = field;
+            field.setAccessible(true);
+        }
+
+        @Override
+        public void putObject(Node receiver, Object value) {
+            assert !type.isPrimitive() && value == null || type.isInstance(value);
+            try {
+                field.set(receiver, value);
+            } catch (IllegalAccessException e) {
+                throw new AssertionError(e);
+            }
+        }
+
+        @Override
+        public Object getObject(Node receiver) {
+            assert !type.isPrimitive();
+            try {
+                return field.get(receiver);
+            } catch (IllegalAccessException e) {
+                throw new AssertionError(e);
+            }
+        }
+
+        @Override
+        public Object loadValue(Node node) {
+            try {
+                if (type == boolean.class) {
+                    return field.getBoolean(node);
+                } else if (type == byte.class) {
+                    return field.getByte(node);
+                } else if (type == short.class) {
+                    return field.getShort(node);
+                } else if (type == char.class) {
+                    return field.getChar(node);
+                } else if (type == int.class) {
+                    return field.getInt(node);
+                } else if (type == long.class) {
+                    return field.getLong(node);
+                } else if (type == float.class) {
+                    return field.getFloat(node);
+                } else if (type == double.class) {
+                    return field.getDouble(node);
+                } else {
+                    return field.get(node);
+                }
+            } catch (IllegalAccessException e) {
+                throw new AssertionError(e);
+            }
+        }
+    }
+
+}
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Apr 02 14:28:27 2015 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java	Thu Apr 02 01:22:41 2015 +0200
@@ -27,7 +27,6 @@
 import java.io.*;
 import java.lang.annotation.*;
 import java.lang.reflect.*;
-import java.security.*;
 import java.util.*;
 
 import sun.misc.*;
@@ -35,15 +34,13 @@
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.instrument.*;
 import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode;
-import com.oracle.truffle.api.nodes.Node.Child;
-import com.oracle.truffle.api.nodes.Node.Children;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
 import com.oracle.truffle.api.source.*;
 
 /**
  * Utility class that manages the special access methods for node instances.
  */
 public final class NodeUtil {
-    private static final boolean USE_UNSAFE = Boolean.getBoolean("truffle.unsafe");
 
     /**
      * Interface that allows the customization of field offsets used for {@link Unsafe} field
@@ -56,399 +53,6 @@
         int getTypeSize(Class<?> clazz);
     }
 
-    private static final FieldOffsetProvider unsafeFieldOffsetProvider = new FieldOffsetProvider() {
-
-        @Override
-        public long objectFieldOffset(Field field) {
-            return unsafe.objectFieldOffset(field);
-        }
-
-        @Override
-        public int getTypeSize(Class<?> clazz) {
-            if (!clazz.isPrimitive()) {
-                return Unsafe.ARRAY_OBJECT_INDEX_SCALE;
-            } else if (clazz == int.class) {
-                return Unsafe.ARRAY_INT_INDEX_SCALE;
-            } else {
-                throw new UnsupportedOperationException("unsupported field type: " + clazz);
-            }
-        }
-    };
-
-    public static enum NodeFieldKind {
-        /** The single {@link Node#getParent() parent} field. */
-        PARENT,
-        /** A field annotated with {@link Child}. */
-        CHILD,
-        /** A field annotated with {@link Children}. */
-        CHILDREN,
-        /** A normal non-child data field of the node. */
-        DATA
-    }
-
-    /**
-     * Information about a field in a {@link Node} class.
-     */
-    public abstract static class NodeField {
-
-        private final NodeFieldKind kind;
-        private final String name;
-        protected final Class<?> type;
-        protected final long offset;
-
-        protected NodeField(NodeFieldKind kind, Field field) {
-            this.kind = kind;
-            this.type = field.getType();
-            this.name = field.getName();
-            this.offset = unsafeFieldOffsetProvider.objectFieldOffset(field);
-        }
-
-        protected static NodeField create(NodeFieldKind kind, Field field) {
-            if (USE_UNSAFE) {
-                return new UnsafeNodeField(kind, field);
-            } else {
-                return new ReflectionNodeField(kind, field);
-            }
-        }
-
-        public NodeFieldKind getKind() {
-            return kind;
-        }
-
-        public Class<?> getType() {
-            return type;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public long getOffset() {
-            return offset;
-        }
-
-        public abstract void putObject(Node receiver, Object value);
-
-        public abstract Object getObject(Node receiver);
-
-        public abstract Object loadValue(Node node);
-
-        @Override
-        public int hashCode() {
-            return kind.hashCode() | type.hashCode() | name.hashCode() | ((Long) offset).hashCode();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof NodeField) {
-                NodeField other = (NodeField) obj;
-                return offset == other.offset && name.equals(other.name) && type.equals(other.type) && kind.equals(other.kind);
-            }
-            return false;
-        }
-    }
-
-    private static final class UnsafeNodeField extends NodeField {
-        protected UnsafeNodeField(NodeFieldKind kind, Field field) {
-            super(kind, field);
-        }
-
-        @Override
-        public void putObject(Node receiver, Object value) {
-            if (!type.isPrimitive() && value == null || type.isInstance(value)) {
-                unsafe.putObject(receiver, offset, value);
-            } else {
-                throw new IllegalArgumentException();
-            }
-        }
-
-        @Override
-        public Object getObject(Node receiver) {
-            if (!type.isPrimitive()) {
-                return unsafe.getObject(receiver, offset);
-            } else {
-                throw new IllegalArgumentException();
-            }
-        }
-
-        @Override
-        public Object loadValue(Node node) {
-            if (type == boolean.class) {
-                return unsafe.getBoolean(node, offset);
-            } else if (type == byte.class) {
-                return unsafe.getByte(node, offset);
-            } else if (type == short.class) {
-                return unsafe.getShort(node, offset);
-            } else if (type == char.class) {
-                return unsafe.getChar(node, offset);
-            } else if (type == int.class) {
-                return unsafe.getInt(node, offset);
-            } else if (type == long.class) {
-                return unsafe.getLong(node, offset);
-            } else if (type == float.class) {
-                return unsafe.getFloat(node, offset);
-            } else if (type == double.class) {
-                return unsafe.getDouble(node, offset);
-            } else {
-                return unsafe.getObject(node, offset);
-            }
-        }
-    }
-
-    private static final class ReflectionNodeField extends NodeField {
-        private final Field field;
-
-        protected ReflectionNodeField(NodeFieldKind kind, Field field) {
-            super(kind, field);
-            this.field = field;
-            field.setAccessible(true);
-        }
-
-        @Override
-        public void putObject(Node receiver, Object value) {
-            assert !type.isPrimitive() && value == null || type.isInstance(value);
-            try {
-                field.set(receiver, value);
-            } catch (IllegalAccessException e) {
-                throw new AssertionError(e);
-            }
-        }
-
-        @Override
-        public Object getObject(Node receiver) {
-            assert !type.isPrimitive();
-            try {
-                return field.get(receiver);
-            } catch (IllegalAccessException e) {
-                throw new AssertionError(e);
-            }
-        }
-
-        @Override
-        public Object loadValue(Node node) {
-            try {
-                if (type == boolean.class) {
-                    return field.getBoolean(node);
-                } else if (type == byte.class) {
-                    return field.getByte(node);
-                } else if (type == short.class) {
-                    return field.getShort(node);
-                } else if (type == char.class) {
-                    return field.getChar(node);
-                } else if (type == int.class) {
-                    return field.getInt(node);
-                } else if (type == long.class) {
-                    return field.getLong(node);
-                } else if (type == float.class) {
-                    return field.getFloat(node);
-                } else if (type == double.class) {
-                    return field.getDouble(node);
-                } else {
-                    return field.get(node);
-                }
-            } catch (IllegalAccessException e) {
-                throw new AssertionError(e);
-            }
-        }
-    }
-
-    /**
-     * Information about a {@link Node} class. A single instance of this class is allocated for
-     * every subclass of {@link Node} that is used.
-     */
-    public static final class NodeClass {
-        private static final ClassValue<NodeClass> nodeClasses = new ClassValue<NodeClass>() {
-            @SuppressWarnings("unchecked")
-            @Override
-            protected NodeClass computeValue(final Class<?> clazz) {
-                assert Node.class.isAssignableFrom(clazz);
-                return AccessController.doPrivileged(new PrivilegedAction<NodeClass>() {
-                    public NodeClass run() {
-                        return new NodeClass((Class<? extends Node>) clazz);
-                    }
-                });
-            }
-        };
-
-        // The comprehensive list of all fields.
-        private final NodeField[] fields;
-        // Separate arrays for the frequently accessed fields.
-        private final NodeField parentField;
-        private final NodeField[] childFields;
-        private final NodeField[] childrenFields;
-        private final NodeField[] cloneableFields;
-
-        private final Class<? extends Node> clazz;
-
-        public static NodeClass get(Class<? extends Node> clazz) {
-            return nodeClasses.get(clazz);
-        }
-
-        public NodeClass(Class<? extends Node> clazz) {
-            List<NodeField> fieldsList = new ArrayList<>();
-            NodeField parentFieldTmp = null;
-            List<NodeField> childFieldList = new ArrayList<>();
-            List<NodeField> childrenFieldList = new ArrayList<>();
-            List<NodeField> cloneableFieldList = new ArrayList<>();
-
-            for (Field field : getAllFields(clazz)) {
-                if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) {
-                    continue;
-                }
-
-                NodeField nodeField;
-                if (field.getDeclaringClass() == Node.class && field.getName().equals("parent")) {
-                    assert Node.class.isAssignableFrom(field.getType());
-                    nodeField = NodeField.create(NodeFieldKind.PARENT, field);
-                    parentFieldTmp = nodeField;
-                } else if (field.getAnnotation(Child.class) != null) {
-                    checkChildField(field);
-                    nodeField = NodeField.create(NodeFieldKind.CHILD, field);
-                    childFieldList.add(nodeField);
-                } else if (field.getAnnotation(Children.class) != null) {
-                    checkChildrenField(field);
-                    nodeField = NodeField.create(NodeFieldKind.CHILDREN, field);
-                    childrenFieldList.add(nodeField);
-                } else {
-                    nodeField = NodeField.create(NodeFieldKind.DATA, field);
-                    if (NodeCloneable.class.isAssignableFrom(field.getType())) {
-                        cloneableFieldList.add(nodeField);
-                    }
-                }
-                fieldsList.add(nodeField);
-            }
-
-            if (parentFieldTmp == null) {
-                throw new AssertionError("parent field not found");
-            }
-
-            this.fields = fieldsList.toArray(new NodeField[fieldsList.size()]);
-            this.parentField = parentFieldTmp;
-            this.childFields = childFieldList.toArray(new NodeField[childFieldList.size()]);
-            this.childrenFields = childrenFieldList.toArray(new NodeField[childrenFieldList.size()]);
-            this.cloneableFields = cloneableFieldList.toArray(new NodeField[cloneableFieldList.size()]);
-            this.clazz = clazz;
-        }
-
-        private static boolean isNodeType(Class<?> clazz) {
-            return Node.class.isAssignableFrom(clazz) || (clazz.isInterface() && NodeInterface.class.isAssignableFrom(clazz));
-        }
-
-        private static void checkChildField(Field field) {
-            if (!isNodeType(field.getType())) {
-                throw new AssertionError("@Child field type must be a subclass of Node or an interface extending NodeInterface (" + field + ")");
-            }
-            if (Modifier.isFinal(field.getModifiers())) {
-                throw new AssertionError("@Child field must not be final (" + field + ")");
-            }
-        }
-
-        private static void checkChildrenField(Field field) {
-            if (!(field.getType().isArray() && isNodeType(field.getType().getComponentType()))) {
-                throw new AssertionError("@Children field type must be an array of a subclass of Node or an interface extending NodeInterface (" + field + ")");
-            }
-            if (!Modifier.isFinal(field.getModifiers())) {
-                throw new AssertionError("@Children field must be final (" + field + ")");
-            }
-        }
-
-        public NodeField[] getFields() {
-            return fields;
-        }
-
-        public NodeField getParentField() {
-            return parentField;
-        }
-
-        public NodeField[] getChildFields() {
-            return childFields;
-        }
-
-        public NodeField[] getChildrenFields() {
-            return childrenFields;
-        }
-
-        @Override
-        public int hashCode() {
-            return clazz.hashCode();
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof NodeClass) {
-                NodeClass other = (NodeClass) obj;
-                return clazz.equals(other.clazz);
-            }
-            return false;
-        }
-
-        public Iterator<Node> makeIterator(Node node) {
-            assert clazz.isInstance(node);
-            return new NodeIterator(node);
-        }
-
-        private final class NodeIterator implements Iterator<Node> {
-            private final Node node;
-            private final int childrenCount;
-            private int index;
-
-            protected NodeIterator(Node node) {
-                this.node = node;
-                this.index = 0;
-                this.childrenCount = childrenCount();
-            }
-
-            private int childrenCount() {
-                int nodeCount = childFields.length;
-                for (NodeField childrenField : childrenFields) {
-                    Object[] children = ((Object[]) childrenField.getObject(node));
-                    if (children != null) {
-                        nodeCount += children.length;
-                    }
-                }
-                return nodeCount;
-            }
-
-            private Node nodeAt(int idx) {
-                int nodeCount = childFields.length;
-                if (idx < nodeCount) {
-                    return (Node) childFields[idx].getObject(node);
-                } else {
-                    for (NodeField childrenField : childrenFields) {
-                        Object[] nodeArray = (Object[]) childrenField.getObject(node);
-                        if (idx < nodeCount + nodeArray.length) {
-                            return (Node) nodeArray[idx - nodeCount];
-                        }
-                        nodeCount += nodeArray.length;
-                    }
-                }
-                return null;
-            }
-
-            private void forward() {
-                if (index < childrenCount) {
-                    index++;
-                }
-            }
-
-            public boolean hasNext() {
-                return index < childrenCount;
-            }
-
-            public Node next() {
-                try {
-                    return nodeAt(index);
-                } finally {
-                    forward();
-                }
-            }
-
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-        }
-    }
-
     static Iterator<Node> makeIterator(Node node) {
         return NodeClass.get(node.getClass()).makeIterator(node);
     }
@@ -521,22 +125,6 @@
         }
     }
 
-    private static final Unsafe unsafe = getUnsafe();
-
-    private static Unsafe getUnsafe() {
-        try {
-            return Unsafe.getUnsafe();
-        } catch (SecurityException e) {
-        }
-        try {
-            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
-            theUnsafeInstance.setAccessible(true);
-            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
-        } catch (Exception e) {
-            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
-        }
-    }
-
     @SuppressWarnings("unchecked")
     public static <T extends Node> T cloneNode(T orig) {
         return (T) orig.deepCopy();
@@ -546,17 +134,17 @@
         final Node clone = orig.copy();
         NodeClass nodeClass = NodeClass.get(clone.getClass());
 
-        nodeClass.parentField.putObject(clone, null);
+        nodeClass.getParentField().putObject(clone, null);
 
-        for (NodeField childField : nodeClass.childFields) {
+        for (NodeFieldAccessor childField : nodeClass.getChildFields()) {
             Node child = (Node) childField.getObject(orig);
             if (child != null) {
                 Node clonedChild = child.deepCopy();
-                nodeClass.parentField.putObject(clonedChild, clone);
+                nodeClass.getParentField().putObject(clonedChild, clone);
                 childField.putObject(clone, clonedChild);
             }
         }
-        for (NodeField childrenField : nodeClass.childrenFields) {
+        for (NodeFieldAccessor childrenField : nodeClass.getChildrenFields()) {
             Object[] children = (Object[]) childrenField.getObject(orig);
             if (children != null) {
                 Object[] clonedChildren = (Object[]) Array.newInstance(children.getClass().getComponentType(), children.length);
@@ -564,13 +152,13 @@
                     if (children[i] != null) {
                         Node clonedChild = ((Node) children[i]).deepCopy();
                         clonedChildren[i] = clonedChild;
-                        nodeClass.parentField.putObject(clonedChild, clone);
+                        nodeClass.getParentField().putObject(clonedChild, clone);
                     }
                 }
                 childrenField.putObject(clone, clonedChildren);
             }
         }
-        for (NodeField cloneableField : nodeClass.cloneableFields) {
+        for (NodeFieldAccessor cloneableField : nodeClass.getCloneableFields()) {
             Object cloneable = cloneableField.getObject(clone);
             if (cloneable != null && cloneable == cloneableField.getObject(orig)) {
                 cloneableField.putObject(clone, ((NodeCloneable) cloneable).clone());
@@ -583,13 +171,13 @@
         List<Node> nodes = new ArrayList<>();
         NodeClass nodeClass = NodeClass.get(node.getClass());
 
-        for (NodeField nodeField : nodeClass.childFields) {
+        for (NodeFieldAccessor nodeField : nodeClass.getChildFields()) {
             Object child = nodeField.getObject(node);
             if (child != null) {
                 nodes.add((Node) child);
             }
         }
-        for (NodeField nodeField : nodeClass.childrenFields) {
+        for (NodeFieldAccessor nodeField : nodeClass.getChildrenFields()) {
             Object[] children = (Object[]) nodeField.getObject(node);
             if (children != null) {
                 for (Object child : children) {
@@ -611,7 +199,7 @@
     public static boolean replaceChild(Node parent, Node oldChild, Node newChild) {
         NodeClass nodeClass = NodeClass.get(parent.getClass());
 
-        for (NodeField nodeField : nodeClass.getChildFields()) {
+        for (NodeFieldAccessor nodeField : nodeClass.getChildFields()) {
             if (nodeField.getObject(parent) == oldChild) {
                 assert assertAssignable(nodeField, newChild);
                 nodeField.putObject(parent, newChild);
@@ -619,7 +207,7 @@
             }
         }
 
-        for (NodeField nodeField : nodeClass.getChildrenFields()) {
+        for (NodeFieldAccessor nodeField : nodeClass.getChildrenFields()) {
             Object arrayObject = nodeField.getObject(parent);
             if (arrayObject != null) {
                 Object[] array = (Object[]) arrayObject;
@@ -635,7 +223,7 @@
         return false;
     }
 
-    private static boolean assertAssignable(NodeField field, Object newValue) {
+    private static boolean assertAssignable(NodeFieldAccessor field, Object newValue) {
         if (newValue == null) {
             return true;
         }
@@ -662,17 +250,17 @@
      *
      * @return the field (possibly an array) holding the child, {@code null} if not found.
      */
-    public static NodeField findChildField(Node parent, Node child) {
+    public static NodeFieldAccessor findChildField(Node parent, Node child) {
         assert child != null;
         NodeClass parentNodeClass = NodeClass.get(parent.getClass());
 
-        for (NodeField field : parentNodeClass.getChildFields()) {
+        for (NodeFieldAccessor field : parentNodeClass.getChildFields()) {
             if (field.getObject(parent) == child) {
                 return field;
             }
         }
 
-        for (NodeField field : parentNodeClass.getChildrenFields()) {
+        for (NodeFieldAccessor field : parentNodeClass.getChildrenFields()) {
             Object arrayObject = field.getObject(parent);
             if (arrayObject != null) {
                 Object[] array = (Object[]) arrayObject;
@@ -692,7 +280,7 @@
     public static boolean isReplacementSafe(Node parent, Node oldChild, Node newChild) {
         assert newChild != null;
         if (parent != null) {
-            final NodeField field = findChildField(parent, oldChild);
+            final NodeFieldAccessor field = findChildField(parent, oldChild);
             if (field != null) {
                 switch (field.getKind()) {
                     case CHILD:
@@ -716,7 +304,7 @@
         Objects.requireNonNull(visitor);
         NodeClass parentNodeClass = NodeClass.get(parent.getClass());
 
-        for (NodeField field : parentNodeClass.getChildFields()) {
+        for (NodeFieldAccessor field : parentNodeClass.getChildFields()) {
             Object child = field.getObject(parent);
             if (child != null) {
                 if (!visitor.visit((Node) child)) {
@@ -725,7 +313,7 @@
             }
         }
 
-        for (NodeField field : parentNodeClass.getChildrenFields()) {
+        for (NodeFieldAccessor field : parentNodeClass.getChildrenFields()) {
             Object arrayObject = field.getObject(parent);
             if (arrayObject != null) {
                 Object[] array = (Object[]) arrayObject;
@@ -744,7 +332,7 @@
     }
 
     /** Returns all declared fields in the class hierarchy. */
-    private static Field[] getAllFields(Class<? extends Object> clazz) {
+    static Field[] getAllFields(Class<? extends Object> clazz) {
         Field[] declaredFields = clazz.getDeclaredFields();
         if (clazz.getSuperclass() != null) {
             return concat(getAllFields(clazz.getSuperclass()), declaredFields);
@@ -976,8 +564,8 @@
     }
 
     private static String getNodeFieldName(Node parent, Node node, String defaultName) {
-        NodeField[] fields = NodeClass.get(parent.getClass()).fields;
-        for (NodeField field : fields) {
+        NodeFieldAccessor[] fields = NodeClass.get(parent.getClass()).getFields();
+        for (NodeFieldAccessor field : fields) {
             Object value = field.loadValue(parent);
             if (field.getKind() == NodeFieldKind.CHILD && value == node) {
                 return field.getName();
@@ -1053,10 +641,10 @@
 
         p.print(nodeName(node));
 
-        ArrayList<NodeField> childFields = new ArrayList<>();
+        ArrayList<NodeFieldAccessor> childFields = new ArrayList<>();
         String sep = "";
         p.print("(");
-        for (NodeField field : NodeClass.get(node.getClass()).fields) {
+        for (NodeFieldAccessor field : NodeClass.get(node.getClass()).getFields()) {
             if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) {
                 childFields.add(field);
             } else if (field.getKind() == NodeFieldKind.DATA) {
@@ -1072,7 +660,7 @@
 
         if (childFields.size() != 0) {
             p.print(" {");
-            for (NodeField field : childFields) {
+            for (NodeFieldAccessor field : childFields) {
                 printNewLine(p, level);
                 p.print(field.getName());
 
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java	Thu Apr 02 14:28:27 2015 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java	Thu Apr 02 01:22:41 2015 +0200
@@ -30,9 +30,7 @@
 import sun.misc.*;
 
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeClass;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeField;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
 import com.oracle.truffle.api.source.*;
 
 /**
@@ -148,7 +146,7 @@
 
         Node node = (Node) object;
 
-        NodeField[] nodeFields = NodeClass.get(nodeClass).getFields();
+        NodeFieldAccessor[] nodeFields = NodeClass.get(nodeClass).getFields();
         deserializeChildrenFields(node, nodeFields);
         deserializeChildFields(node, nodeFields);
         deserializeDataFields(buffer, node, nodeFields);
@@ -156,9 +154,9 @@
         return node;
     }
 
-    private void deserializeDataFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeField[] nodeFields) throws UnsupportedConstantPoolTypeException {
+    private void deserializeDataFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeFieldAccessor[] nodeFields) throws UnsupportedConstantPoolTypeException {
         for (int i = 0; i < nodeFields.length; i++) {
-            NodeField field = nodeFields[i];
+            NodeFieldAccessor field = nodeFields[i];
             if (field.getKind() == NodeFieldKind.DATA) {
                 Class<?> fieldClass = field.getType();
                 long offset = field.getOffset();
@@ -239,18 +237,18 @@
         }
     }
 
-    private void deserializeChildFields(Node parent, NodeField[] nodeFields) {
+    private void deserializeChildFields(Node parent, NodeFieldAccessor[] nodeFields) {
         for (int i = nodeFields.length - 1; i >= 0; i--) {
-            NodeField field = nodeFields[i];
+            NodeFieldAccessor field = nodeFields[i];
             if (field.getKind() == NodeFieldKind.CHILD) {
                 unsafe.putObject(parent, field.getOffset(), popNode(parent, field.getType()));
             }
         }
     }
 
-    private void deserializeChildrenFields(Node parent, NodeField[] nodeFields) {
+    private void deserializeChildrenFields(Node parent, NodeFieldAccessor[] nodeFields) {
         for (int i = nodeFields.length - 1; i >= 0; i--) {
-            NodeField field = nodeFields[i];
+            NodeFieldAccessor field = nodeFields[i];
             if (field.getKind() == NodeFieldKind.CHILDREN) {
                 unsafe.putObject(parent, field.getOffset(), popArray(parent, field.getType()));
             }
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java	Thu Apr 02 14:28:27 2015 +0200
+++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderSerializer.java	Thu Apr 02 01:22:41 2015 +0200
@@ -30,9 +30,7 @@
 import sun.misc.*;
 
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeClass;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeField;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind;
+import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
 import com.oracle.truffle.api.source.*;
 
 /**
@@ -79,16 +77,16 @@
         }
         Class<? extends Node> nodeClass = node.getClass();
 
-        NodeField[] nodeFields = NodeClass.get(nodeClass).getFields();
+        NodeFieldAccessor[] nodeFields = NodeClass.get(nodeClass).getFields();
         serializeChildFields(buffer, node, nodeFields);
         serializeChildrenFields(buffer, node, nodeFields);
         buffer.put(cp.putClass(node.getClass()));
         serializeDataFields(buffer, node, nodeFields);
     }
 
-    private void serializeDataFields(VariableLengthIntBuffer buffer, Node node, NodeField[] nodeFields) throws UnsupportedConstantPoolTypeException {
+    private void serializeDataFields(VariableLengthIntBuffer buffer, Node node, NodeFieldAccessor[] nodeFields) throws UnsupportedConstantPoolTypeException {
         for (int i = 0; i < nodeFields.length; i++) {
-            NodeField field = nodeFields[i];
+            NodeFieldAccessor field = nodeFields[i];
             if (field.getKind() == NodeFieldKind.DATA) {
                 Class<?> fieldClass = field.getType();
                 long offset = field.getOffset();
@@ -148,9 +146,9 @@
         }
     }
 
-    private void serializeChildrenFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeField[] nodeFields) throws UnsupportedConstantPoolTypeException {
+    private void serializeChildrenFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeFieldAccessor[] nodeFields) throws UnsupportedConstantPoolTypeException {
         for (int i = 0; i < nodeFields.length; i++) {
-            NodeField field = nodeFields[i];
+            NodeFieldAccessor field = nodeFields[i];
             if (field.getKind() == NodeFieldKind.CHILDREN) {
                 Object childArrayObject = unsafe.getObject(nodeInstance, field.getOffset());
                 if (childArrayObject != null && !(childArrayObject instanceof Node[])) {
@@ -173,9 +171,9 @@
         }
     }
 
-    private void serializeChildFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeField[] nodeFields) throws UnsupportedConstantPoolTypeException {
+    private void serializeChildFields(VariableLengthIntBuffer buffer, Node nodeInstance, NodeFieldAccessor[] nodeFields) throws UnsupportedConstantPoolTypeException {
         for (int i = 0; i < nodeFields.length; i++) {
-            NodeField field = nodeFields[i];
+            NodeFieldAccessor field = nodeFields[i];
             if (field.getKind() == NodeFieldKind.CHILD) {
                 Object childObject = unsafe.getObject(nodeInstance, field.getOffset());
                 if (childObject != null && !(childObject instanceof Node)) {
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java	Thu Apr 02 14:28:27 2015 +0200
+++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java	Thu Apr 02 01:22:41 2015 +0200
@@ -28,8 +28,6 @@
 import com.oracle.truffle.api.instrument.*;
 import com.oracle.truffle.api.instrument.impl.*;
 import com.oracle.truffle.api.nodes.*;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeClass;
-import com.oracle.truffle.api.nodes.NodeUtil.NodeField;
 import com.oracle.truffle.api.nodes.NodeUtil.NodeFieldKind;
 
 /**
@@ -60,9 +58,9 @@
 
         p.print(NodeUtil.printSyntaxTags(node));
 
-        ArrayList<NodeField> childFields = new ArrayList<>();
+        ArrayList<NodeFieldAccessor> childFields = new ArrayList<>();
 
-        for (NodeField field : NodeClass.get(node.getClass()).getFields()) {
+        for (NodeFieldAccessor field : NodeClass.get(node.getClass()).getFields()) {
             if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) {
                 childFields.add(field);
             } else if (field.getKind() == NodeFieldKind.DATA) {
@@ -84,7 +82,7 @@
 
             if (childFields.size() != 0) {
                 p.print(" {");
-                for (NodeField field : childFields) {
+                for (NodeFieldAccessor field : childFields) {
 
                     Object value = field.loadValue(node);
                     if (value == null) {