comparison truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeClass.java @ 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 6598b9b7aafd
children efbc311e9ff2
comparison
equal deleted inserted replaced
22397:27cf58ec97ae 22398:07c98b5a9496
22 * or visit www.oracle.com if you need additional information or have any 22 * or visit www.oracle.com if you need additional information or have any
23 * questions. 23 * questions.
24 */ 24 */
25 package com.oracle.truffle.api.nodes; 25 package com.oracle.truffle.api.nodes;
26 26
27 import com.oracle.truffle.api.nodes.Node.Child;
28 import com.oracle.truffle.api.nodes.Node.Children;
29 import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
30 import java.lang.reflect.Field; 27 import java.lang.reflect.Field;
31 import java.lang.reflect.Modifier; 28 import java.lang.reflect.Modifier;
32 import java.security.AccessController; 29 import java.security.AccessController;
33 import java.security.PrivilegedAction; 30 import java.security.PrivilegedAction;
34 import java.util.ArrayList; 31 import java.util.ArrayList;
35 import java.util.Iterator; 32 import java.util.Iterator;
36 import java.util.List; 33 import java.util.List;
34
35 import com.oracle.truffle.api.nodes.Node.Child;
36 import com.oracle.truffle.api.nodes.Node.Children;
37 import com.oracle.truffle.api.nodes.NodeFieldAccessor.NodeFieldKind;
37 38
38 /** 39 /**
39 * Information about a {@link Node} class. A single instance of this class is allocated for every 40 * Information about a {@link Node} class. A single instance of this class is allocated for every
40 * subclass of {@link Node} that is used. 41 * subclass of {@link Node} that is used.
41 */ 42 */
73 public static NodeClass get(Node node) { 74 public static NodeClass get(Node node) {
74 return node.getNodeClass(); 75 return node.getNodeClass();
75 } 76 }
76 77
77 NodeClass(Class<? extends Node> clazz) { 78 NodeClass(Class<? extends Node> clazz) {
79 if (!Node.class.isAssignableFrom(clazz)) {
80 throw new IllegalArgumentException();
81 }
82
78 List<NodeFieldAccessor> fieldsList = new ArrayList<>(); 83 List<NodeFieldAccessor> fieldsList = new ArrayList<>();
79 NodeFieldAccessor parentFieldTmp = null; 84 NodeFieldAccessor parentFieldTmp = null;
80 NodeFieldAccessor nodeClassFieldTmp = null; 85 NodeFieldAccessor nodeClassFieldTmp = null;
81 List<NodeFieldAccessor> childFieldList = new ArrayList<>(); 86 List<NodeFieldAccessor> childFieldList = new ArrayList<>();
82 List<NodeFieldAccessor> childrenFieldList = new ArrayList<>(); 87 List<NodeFieldAccessor> childrenFieldList = new ArrayList<>();
83 List<NodeFieldAccessor> cloneableFieldList = new ArrayList<>(); 88 List<NodeFieldAccessor> cloneableFieldList = new ArrayList<>();
84 89
85 for (Field field : NodeUtil.getAllFields(clazz)) { 90 try {
91 Field field = Node.class.getDeclaredField("parent");
92 assert Node.class.isAssignableFrom(field.getType());
93 parentFieldTmp = NodeFieldAccessor.create(NodeFieldKind.PARENT, field);
94 field = Node.class.getDeclaredField("nodeClass");
95 assert NodeClass.class.isAssignableFrom(field.getType());
96 nodeClassFieldTmp = NodeFieldAccessor.create(NodeFieldKind.NODE_CLASS, field);
97 } catch (NoSuchFieldException e) {
98 throw new AssertionError("Node field not found", e);
99 }
100
101 collectInstanceFields(clazz, fieldsList, childFieldList, childrenFieldList, cloneableFieldList);
102
103 this.fields = fieldsList.toArray(EMPTY_NODE_FIELD_ARRAY);
104 this.nodeClassField = nodeClassFieldTmp;
105 this.parentField = parentFieldTmp;
106 this.childFields = childFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
107 this.childrenFields = childrenFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
108 this.cloneableFields = cloneableFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
109 this.clazz = clazz;
110 }
111
112 private static void collectInstanceFields(Class<? extends Object> clazz, List<NodeFieldAccessor> fieldsList, List<NodeFieldAccessor> childFieldList, List<NodeFieldAccessor> childrenFieldList,
113 List<NodeFieldAccessor> cloneableFieldList) {
114 if (clazz.getSuperclass() != null) {
115 collectInstanceFields(clazz.getSuperclass(), fieldsList, childFieldList, childrenFieldList, cloneableFieldList);
116 }
117 Field[] declaredFields = clazz.getDeclaredFields();
118 for (Field field : declaredFields) {
86 if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) { 119 if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) {
87 continue; 120 continue;
88 } 121 }
89 122
90 NodeFieldAccessor nodeField; 123 NodeFieldAccessor nodeField;
91 if (field.getDeclaringClass() == Node.class && field.getName().equals("parent")) { 124 if (field.getDeclaringClass() == Node.class && (field.getName().equals("parent") || field.getName().equals("nodeClass"))) {
92 assert Node.class.isAssignableFrom(field.getType()); 125 continue;
93 nodeField = NodeFieldAccessor.create(NodeFieldKind.PARENT, field);
94 parentFieldTmp = nodeField;
95 } else if (field.getDeclaringClass() == Node.class && field.getName().equals("nodeClass")) {
96 assert NodeClass.class.isAssignableFrom(field.getType());
97 nodeField = NodeFieldAccessor.create(NodeFieldKind.NODE_CLASS, field);
98 nodeClassFieldTmp = nodeField;
99 } else if (field.getAnnotation(Child.class) != null) { 126 } else if (field.getAnnotation(Child.class) != null) {
100 checkChildField(field); 127 checkChildField(field);
101 nodeField = NodeFieldAccessor.create(NodeFieldKind.CHILD, field); 128 nodeField = NodeFieldAccessor.create(NodeFieldKind.CHILD, field);
102 childFieldList.add(nodeField); 129 childFieldList.add(nodeField);
103 } else if (field.getAnnotation(Children.class) != null) { 130 } else if (field.getAnnotation(Children.class) != null) {
110 cloneableFieldList.add(nodeField); 137 cloneableFieldList.add(nodeField);
111 } 138 }
112 } 139 }
113 fieldsList.add(nodeField); 140 fieldsList.add(nodeField);
114 } 141 }
115
116 if (parentFieldTmp == null) {
117 throw new AssertionError("parent field not found");
118 }
119
120 this.fields = fieldsList.toArray(EMPTY_NODE_FIELD_ARRAY);
121 this.nodeClassField = nodeClassFieldTmp;
122 this.parentField = parentFieldTmp;
123 this.childFields = childFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
124 this.childrenFields = childrenFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
125 this.cloneableFields = cloneableFieldList.toArray(EMPTY_NODE_FIELD_ARRAY);
126 this.clazz = clazz;
127 } 142 }
128 143
129 public NodeFieldAccessor getNodeClassField() { 144 public NodeFieldAccessor getNodeClassField() {
130 return nodeClassField; 145 return nodeClassField;
131 } 146 }