# HG changeset patch # User Andreas Woess # Date 1447955395 -3600 # Node ID 07c98b5a949641810cf0c9824e45e8cfdb363ddb # Parent 27cf58ec97ae7e46b0eab225bfd6a2437f7011cd NodeClass: avoid unnecessary array copying during initialization diff -r 27cf58ec97ae -r 07c98b5a9496 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 Thu Nov 19 16:37:34 2015 +0100 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java Thu Nov 19 18:49:55 2015 +0100 @@ -24,9 +24,6 @@ */ 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; @@ -35,6 +32,10 @@ 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.NodeFieldKind; + /** * Information about a {@link Node} class. A single instance of this class is allocated for every * subclass of {@link Node} that is used. @@ -75,6 +76,10 @@ } NodeClass(Class clazz) { + if (!Node.class.isAssignableFrom(clazz)) { + throw new IllegalArgumentException(); + } + List fieldsList = new ArrayList<>(); NodeFieldAccessor parentFieldTmp = null; NodeFieldAccessor nodeClassFieldTmp = null; @@ -82,20 +87,42 @@ List childrenFieldList = new ArrayList<>(); List cloneableFieldList = new ArrayList<>(); - for (Field field : NodeUtil.getAllFields(clazz)) { + try { + Field field = Node.class.getDeclaredField("parent"); + assert Node.class.isAssignableFrom(field.getType()); + parentFieldTmp = NodeFieldAccessor.create(NodeFieldKind.PARENT, field); + field = Node.class.getDeclaredField("nodeClass"); + assert NodeClass.class.isAssignableFrom(field.getType()); + nodeClassFieldTmp = NodeFieldAccessor.create(NodeFieldKind.NODE_CLASS, field); + } catch (NoSuchFieldException e) { + throw new AssertionError("Node field not found", e); + } + + collectInstanceFields(clazz, fieldsList, childFieldList, childrenFieldList, cloneableFieldList); + + 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; + } + + private static void collectInstanceFields(Class clazz, List fieldsList, List childFieldList, List childrenFieldList, + List cloneableFieldList) { + if (clazz.getSuperclass() != null) { + collectInstanceFields(clazz.getSuperclass(), fieldsList, childFieldList, childrenFieldList, cloneableFieldList); + } + Field[] declaredFields = clazz.getDeclaredFields(); + for (Field field : declaredFields) { 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.getDeclaringClass() == Node.class && field.getName().equals("nodeClass")) { - assert NodeClass.class.isAssignableFrom(field.getType()); - nodeField = NodeFieldAccessor.create(NodeFieldKind.NODE_CLASS, field); - nodeClassFieldTmp = nodeField; + if (field.getDeclaringClass() == Node.class && (field.getName().equals("parent") || field.getName().equals("nodeClass"))) { + continue; } else if (field.getAnnotation(Child.class) != null) { checkChildField(field); nodeField = NodeFieldAccessor.create(NodeFieldKind.CHILD, field); @@ -112,18 +139,6 @@ } 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 NodeFieldAccessor getNodeClassField() { diff -r 27cf58ec97ae -r 07c98b5a9496 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 Thu Nov 19 16:37:34 2015 +0100 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Thu Nov 19 18:49:55 2015 +0100 @@ -30,7 +30,6 @@ import java.io.StringWriter; import java.lang.annotation.Annotation; import java.lang.reflect.Array; -import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -383,15 +382,6 @@ return true; } - /** Returns all declared fields in the class hierarchy. */ - static Field[] getAllFields(Class clazz) { - Field[] declaredFields = clazz.getDeclaredFields(); - if (clazz.getSuperclass() != null) { - return concat(getAllFields(clazz.getSuperclass()), declaredFields); - } - return declaredFields; - } - public static T[] concat(T[] first, T[] second) { T[] result = Arrays.copyOf(first, first.length + second.length); System.arraycopy(second, 0, result, first.length, second.length);