changeset 22398:07c98b5a9496

NodeClass: avoid unnecessary array copying during initialization
author Andreas Woess <andreas.woess@oracle.com>
date Thu, 19 Nov 2015 18:49:55 +0100
parents 27cf58ec97ae
children efbc311e9ff2
files truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java
diffstat 2 files changed, 39 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- 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<? extends Node> clazz) {
+        if (!Node.class.isAssignableFrom(clazz)) {
+            throw new IllegalArgumentException();
+        }
+
         List<NodeFieldAccessor> fieldsList = new ArrayList<>();
         NodeFieldAccessor parentFieldTmp = null;
         NodeFieldAccessor nodeClassFieldTmp = null;
@@ -82,20 +87,42 @@
         List<NodeFieldAccessor> childrenFieldList = new ArrayList<>();
         List<NodeFieldAccessor> 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<? extends Object> clazz, List<NodeFieldAccessor> fieldsList, List<NodeFieldAccessor> childFieldList, List<NodeFieldAccessor> childrenFieldList,
+                    List<NodeFieldAccessor> 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() {
--- 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<? extends Object> clazz) {
-        Field[] declaredFields = clazz.getDeclaredFields();
-        if (clazz.getSuperclass() != null) {
-            return concat(getAllFields(clazz.getSuperclass()), declaredFields);
-        }
-        return declaredFields;
-    }
-
     public static <T> T[] concat(T[] first, T[] second) {
         T[] result = Arrays.copyOf(first, first.length + second.length);
         System.arraycopy(second, 0, result, first.length, second.length);