# HG changeset patch # User Christian Wirth # Date 1447754575 -3600 # Node ID 6598b9b7aafd07d4860a988b5971b553ad21d161 # Parent 75c4ce3a352a9017d395cb7f55001419a1175ae6 Backed out changeset: 0d4b0e4263ee diff -r 75c4ce3a352a -r 6598b9b7aafd truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java --- a/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java Mon Nov 16 16:29:27 2015 +0100 +++ b/truffle/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java Tue Nov 17 11:02:55 2015 +0100 @@ -87,7 +87,7 @@ } private static void updateRootImpl(SpecializationNode start, Node node) { - NodeFieldAccessor[] fields = NodeClass.Lookup.get(start).getFields(); + NodeFieldAccessor[] fields = NodeClass.get(start).getFields(); for (int i = fields.length - 1; i >= 0; i--) { NodeFieldAccessor f = fields[i]; if (f.getName().equals("root")) { @@ -508,8 +508,6 @@ throw new UnsupportedSpecializationException(findRoot(), getSuppliedChildren(), args); } - /* Suppress FindBugs false positive. */ - @SuppressFBWarnings(value = "NP") static SpecializationNode insertSorted(SpecializationNode start, final SpecializationNode generated, final CharSequence message, final SpecializationNode merged) { if (merged == generated) { // new node diff -r 75c4ce3a352a -r 6598b9b7aafd truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java Mon Nov 16 16:29:27 2015 +0100 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/impl/DefaultASTPrinter.java Tue Nov 17 11:02:55 2015 +0100 @@ -103,7 +103,7 @@ ArrayList childFields = new ArrayList<>(); - for (NodeFieldAccessor field : NodeClass.Lookup.get(node).getFields()) { + for (NodeFieldAccessor field : NodeClass.get(node).getFields()) { if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) { childFields.add(field); } else if (field.getKind() == NodeFieldKind.DATA) { diff -r 75c4ce3a352a -r 6598b9b7aafd truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Mon Nov 16 16:29:27 2015 +0100 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/GraphPrintVisitor.java Tue Nov 17 11:02:55 2015 +0100 @@ -474,7 +474,7 @@ } private void readNodeProperties(Node node) { - NodeFieldAccessor[] fields = NodeClass.Lookup.get(node).getFields(); + NodeFieldAccessor[] fields = NodeClass.get(node).getFields(); for (NodeFieldAccessor field : fields) { if (field.getKind() == NodeFieldKind.DATA) { String key = field.getName(); @@ -546,7 +546,7 @@ private static LinkedHashMap findNamedNodeChildren(Node node) { LinkedHashMap nodes = new LinkedHashMap<>(); - NodeClass nodeClass = NodeClass.Lookup.get(node); + NodeClass nodeClass = NodeClass.get(node); for (NodeFieldAccessor field : nodeClass.getFields()) { NodeFieldKind kind = field.getKind(); diff -r 75c4ce3a352a -r 6598b9b7aafd truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Mon Nov 16 16:29:27 2015 +0100 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Tue Nov 17 11:02:55 2015 +0100 @@ -75,7 +75,7 @@ protected Node(SourceSection sourceSection) { CompilerAsserts.neverPartOfCompilation(); this.sourceSection = sourceSection; - this.nodeClass = NodeClass.Lookup.get(getClass()); + this.nodeClass = NodeClass.get(getClass()); if (TruffleOptions.TraceASTJSON) { JSONHelper.dumpNewNode(this); } diff -r 75c4ce3a352a -r 6598b9b7aafd truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java Mon Nov 16 16:29:27 2015 +0100 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java Tue Nov 17 11:02:55 2015 +0100 @@ -24,6 +24,9 @@ */ package com.oracle.truffle.api.nodes; +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 java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.security.AccessController; @@ -32,206 +35,170 @@ import java.util.Iterator; import java.util.List; -import com.oracle.truffle.api.nodes.Node.Child; -import com.oracle.truffle.api.nodes.Node.Children; -import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldAccessorImpl; -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 nodeClasses = new ClassValue() { + @SuppressWarnings("unchecked") + @Override + protected NodeClass computeValue(final Class clazz) { + assert Node.class.isAssignableFrom(clazz); + return AccessController.doPrivileged(new PrivilegedAction() { + public NodeClass run() { + return new NodeClass((Class) clazz); + } + }); + } + }; + + private static final NodeFieldAccessor[] EMPTY_NODE_FIELD_ARRAY = new NodeFieldAccessor[0]; + + // The comprehensive list of all fields. + private final NodeFieldAccessor[] fields; + // Separate arrays for the frequently accessed fields. + private final NodeFieldAccessor parentField; + private final NodeFieldAccessor nodeClassField; + private final NodeFieldAccessor[] childFields; + private final NodeFieldAccessor[] childrenFields; + private final NodeFieldAccessor[] cloneableFields; + + private final Class clazz; + + public static NodeClass get(Class clazz) { + return nodeClasses.get(clazz); + } -public interface NodeClass { + public static NodeClass get(Node node) { + return node.getNodeClass(); + } + + NodeClass(Class clazz) { + List fieldsList = new ArrayList<>(); + NodeFieldAccessor parentFieldTmp = null; + NodeFieldAccessor nodeClassFieldTmp = null; + List childFieldList = new ArrayList<>(); + List childrenFieldList = new ArrayList<>(); + List cloneableFieldList = new ArrayList<>(); + + for (Field field : NodeUtil.getAllFields(clazz)) { + if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) { + continue; + } - public static class Lookup { - public static NodeClass get(Class clazz) { - return NodeClassImpl.nodeClasses.get(clazz); + 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.getDeclaringClass() == Node.class && field.getName().equals("nodeClass")) { + assert NodeClass.class.isAssignableFrom(field.getType()); + nodeField = NodeFieldAccessor.create(NodeFieldKind.NODE_CLASS, field); + nodeClassFieldTmp = 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); } - public static NodeClass get(Node node) { - return node.getNodeClass(); + if (parentFieldTmp == null) { + throw new AssertionError("parent field not found"); + } + + this.fields = fieldsList.toArray(EMPTY_NODE_FIELD_ARRAY); + this.nodeClassField = nodeClassFieldTmp; + this.parentField = parentFieldTmp; + this.childFields = childFieldList.toArray(EMPTY_NODE_FIELD_ARRAY); + this.childrenFields = childrenFieldList.toArray(EMPTY_NODE_FIELD_ARRAY); + this.cloneableFields = cloneableFieldList.toArray(EMPTY_NODE_FIELD_ARRAY); + this.clazz = clazz; + } + + public NodeFieldAccessor getNodeClassField() { + return nodeClassField; + } + + 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 + ")"); } } - NodeFieldAccessor getNodeClassField(); - - NodeFieldAccessor[] getCloneableFields(); - - NodeFieldAccessor[] getFields(); - - NodeFieldAccessor getParentField(); - - NodeFieldAccessor[] getChildFields(); - - NodeFieldAccessor[] getChildrenFields(); - - Iterator makeIterator(Node node); - - /** - * 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 NodeClassImpl implements NodeClass { - static final ClassValue nodeClasses = new ClassValue() { - @SuppressWarnings("unchecked") - @Override - protected NodeClass computeValue(final Class clazz) { - assert Node.class.isAssignableFrom(clazz); - return AccessController.doPrivileged(new PrivilegedAction() { - public NodeClass run() { - return new NodeClassImpl((Class) clazz); - } - }); - } - }; - - private static final NodeFieldAccessor[] EMPTY_NODE_FIELD_ARRAY = new NodeFieldAccessor[0]; - - // The comprehensive list of all fields. - private final NodeFieldAccessor[] fields; - // Separate arrays for the frequently accessed fields. - private final NodeFieldAccessor parentField; - private final NodeFieldAccessor nodeClassField; - private final NodeFieldAccessor[] childFields; - private final NodeFieldAccessor[] childrenFields; - private final NodeFieldAccessor[] cloneableFields; - - private final Class clazz; - - public static NodeClass get(Class clazz) { - return nodeClasses.get(clazz); - } - - public static NodeClass get(Node node) { - return node.getNodeClass(); + 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 + ")"); } - - NodeClassImpl(Class clazz) { - List fieldsList = new ArrayList<>(); - NodeFieldAccessor parentFieldTmp = null; - NodeFieldAccessor nodeClassFieldTmp = null; - List childFieldList = new ArrayList<>(); - List childrenFieldList = new ArrayList<>(); - List 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 = NodeFieldAccessorImpl.create(NodeFieldKind.PARENT, field); - parentFieldTmp = nodeField; - } else if (field.getDeclaringClass() == Node.class && field.getName().equals("nodeClass")) { - assert NodeClass.class.isAssignableFrom(field.getType()); - nodeField = NodeFieldAccessorImpl.create(NodeFieldKind.NODE_CLASS, field); - nodeClassFieldTmp = nodeField; - } else if (field.getAnnotation(Child.class) != null) { - checkChildField(field); - nodeField = NodeFieldAccessorImpl.create(NodeFieldKind.CHILD, field); - childFieldList.add(nodeField); - } else if (field.getAnnotation(Children.class) != null) { - checkChildrenField(field); - nodeField = NodeFieldAccessorImpl.create(NodeFieldKind.CHILDREN, field); - childrenFieldList.add(nodeField); - } else { - nodeField = NodeFieldAccessorImpl.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(EMPTY_NODE_FIELD_ARRAY); - this.nodeClassField = nodeClassFieldTmp; - this.parentField = parentFieldTmp; - this.childFields = childFieldList.toArray(EMPTY_NODE_FIELD_ARRAY); - this.childrenFields = childrenFieldList.toArray(EMPTY_NODE_FIELD_ARRAY); - this.cloneableFields = cloneableFieldList.toArray(EMPTY_NODE_FIELD_ARRAY); - this.clazz = clazz; - } - - public Class getNodeClass() { - return clazz; - } - - public NodeFieldAccessor getNodeClassField() { - return nodeClassField; - } - - 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 NodeClassImpl) { - NodeClassImpl other = (NodeClassImpl) obj; - return clazz.equals(other.clazz); - } - return false; - } - - public Iterator makeIterator(Node node) { - assert clazz.isInstance(node); - return new NodeIterator(this, node); + if (!Modifier.isFinal(field.getModifiers())) { + throw new AssertionError("@Children field must be final (" + field + ")"); } } - public static final class NodeIterator implements Iterator { + 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 makeIterator(Node node) { + assert clazz.isInstance(node); + return new NodeIterator(this, node); + } + + private static final class NodeIterator implements Iterator { private final NodeFieldAccessor[] childFields; private final NodeFieldAccessor[] childrenFields; private final Node node; private final int childrenCount; private int index; - public NodeIterator(NodeClass nodeClass, Node node) { + protected NodeIterator(NodeClass nodeClass, Node node) { this.childFields = nodeClass.getChildFields(); this.childrenFields = nodeClass.getChildrenFields(); this.node = node; diff -r 75c4ce3a352a -r 6598b9b7aafd truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeFieldAccessor.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeFieldAccessor.java Mon Nov 16 16:29:27 2015 +0100 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeFieldAccessor.java Tue Nov 17 11:02:55 2015 +0100 @@ -31,7 +31,10 @@ import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.nodes.Node.Children; -public interface NodeFieldAccessor { +/** + * Information about a field in a {@link Node} class. + */ +public abstract class NodeFieldAccessor { public static enum NodeFieldKind { /** The reference to the {@link NodeClass}. */ @@ -46,64 +49,51 @@ DATA } - NodeFieldKind getKind(); - - Class getFieldType(); - - Class getFieldDeclaringClass(); - - String getName(); - - void putObject(Node receiver, Object value); - - Object getObject(Node receiver); + private static final boolean USE_UNSAFE = Boolean.getBoolean("truffle.unsafe"); - Object loadValue(Node node); - - /** - * Information about a field in a {@link Node} class. - */ - public abstract static class NodeFieldAccessorImpl implements NodeFieldAccessor { - private static final boolean USE_UNSAFE = Boolean.getBoolean("truffle.unsafe"); - - private final NodeFieldKind kind; - private final Class declaringClass; - private final String name; - protected final Class type; + private final NodeFieldKind kind; + private final Class declaringClass; + private final String name; + protected final Class type; - protected NodeFieldAccessorImpl(NodeFieldKind kind, Class declaringClass, String name, Class type) { - this.kind = kind; - this.declaringClass = declaringClass; - this.name = name; - this.type = type; - } - - protected static NodeFieldAccessor create(NodeFieldKind kind, Field field) { - if (USE_UNSAFE) { - return new UnsafeNodeField(kind, field); - } else { - return new ReflectionNodeField(kind, field); - } - } + protected NodeFieldAccessor(NodeFieldKind kind, Class declaringClass, String name, Class type) { + this.kind = kind; + this.declaringClass = declaringClass; + this.name = name; + this.type = type; + } - public NodeFieldKind getKind() { - return kind; - } - - public Class getFieldType() { - return type; - } - - public Class getFieldDeclaringClass() { - return declaringClass; - } - - public String getName() { - return name; + protected static NodeFieldAccessor create(NodeFieldKind kind, Field field) { + if (USE_UNSAFE) { + return new UnsafeNodeField(kind, field); + } else { + return new ReflectionNodeField(kind, field); } } - public abstract static class AbstractUnsafeNodeFieldAccessor extends NodeFieldAccessorImpl { + public NodeFieldKind getKind() { + return kind; + } + + public Class getType() { + return type; + } + + public Class getDeclaringClass() { + return declaringClass; + } + + public String getName() { + return name; + } + + public abstract void putObject(Node receiver, Object value); + + public abstract Object getObject(Node receiver); + + public abstract Object loadValue(Node node); + + public abstract static class AbstractUnsafeNodeFieldAccessor extends NodeFieldAccessor { protected AbstractUnsafeNodeFieldAccessor(NodeFieldKind kind, Class declaringClass, String name, Class type) { super(kind, declaringClass, name, type); @@ -169,7 +159,7 @@ } } - public static final class UnsafeNodeField extends AbstractUnsafeNodeFieldAccessor { + private static final class UnsafeNodeField extends AbstractUnsafeNodeFieldAccessor { private final long offset; protected UnsafeNodeField(NodeFieldKind kind, Field field) { @@ -183,7 +173,7 @@ } } - public static final class ReflectionNodeField extends NodeFieldAccessorImpl { + private static final class ReflectionNodeField extends NodeFieldAccessor { private final Field field; protected ReflectionNodeField(NodeFieldKind kind, Field field) { @@ -239,4 +229,5 @@ } } } + } diff -r 75c4ce3a352a -r 6598b9b7aafd truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Mon Nov 16 16:29:27 2015 +0100 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Tue Nov 17 11:02:55 2015 +0100 @@ -241,17 +241,17 @@ return true; } if (field.getKind() == NodeFieldKind.CHILD) { - if (field.getFieldType().isAssignableFrom(newValue.getClass())) { + if (field.getType().isAssignableFrom(newValue.getClass())) { return true; } else { - assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getFieldType().getName(); + assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getType().getName(); return false; } } else if (field.getKind() == NodeFieldKind.CHILDREN) { - if (field.getFieldType().getComponentType().isAssignableFrom(newValue.getClass())) { + if (field.getType().getComponentType().isAssignableFrom(newValue.getClass())) { return true; } else { - assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getFieldType().getName(); + assert false : "Child class " + newValue.getClass().getName() + " is not assignable to field \"" + field.getName() + "\" of type " + field.getType().getName(); return false; } } @@ -297,9 +297,9 @@ if (field != null) { switch (field.getKind()) { case CHILD: - return field.getFieldType().isAssignableFrom(newChild.getClass()); + return field.getType().isAssignableFrom(newChild.getClass()); case CHILDREN: - return field.getFieldType().getComponentType().isAssignableFrom(newChild.getClass()); + return field.getType().getComponentType().isAssignableFrom(newChild.getClass()); default: throw new IllegalStateException(); } @@ -679,7 +679,7 @@ ArrayList childFields = new ArrayList<>(); String sep = ""; p.print("("); - for (NodeFieldAccessor field : NodeClass.Lookup.get(node).getFields()) { + for (NodeFieldAccessor field : NodeClass.get(node).getFields()) { if (field.getKind() == NodeFieldKind.CHILD || field.getKind() == NodeFieldKind.CHILDREN) { childFields.add(field); } else if (field.getKind() == NodeFieldKind.DATA) { diff -r 75c4ce3a352a -r 6598b9b7aafd truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java --- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java Mon Nov 16 16:29:27 2015 +0100 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/instrument/SLASTPrinter.java Tue Nov 17 11:02:55 2015 +0100 @@ -80,7 +80,7 @@ ArrayList childFields = new ArrayList<>(); - for (NodeFieldAccessor field : NodeClass.Lookup.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) {