# HG changeset patch # User Andreas Woess # Date 1421883449 -3600 # Node ID 6ba170cb6f5386cea135fd198e8a66a5f1575f0e # Parent 11ec0a5c551860db7aa8361fa47cbdb10dbbf332 Truffle: channel all NodeUtil field accesses through NodeField class diff -r 11ec0a5c5518 -r 6ba170cb6f53 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Wed Jan 21 11:00:48 2015 -0800 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Thu Jan 22 00:37:29 2015 +0100 @@ -95,11 +95,15 @@ private final String name; private long offset; - protected NodeField(NodeFieldKind kind, Class type, String name, long offset) { + private NodeField(NodeFieldKind kind, Field field) { this.kind = kind; - this.type = type; - this.name = name; - this.offset = offset; + this.type = field.getType(); + this.name = field.getName(); + this.offset = unsafeFieldOffsetProvider.objectFieldOffset(field); + } + + protected static NodeField create(NodeFieldKind kind, Field field) { + return new NodeField(kind, field); } public NodeFieldKind getKind() { @@ -119,10 +123,15 @@ } public void putObject(Object receiver, Object value) { - assert value == null || type.isInstance(value); + assert !type.isPrimitive() && value == null || type.isInstance(value); unsafe.putObject(receiver, offset, value); } + public Object getObject(Object receiver) { + assert !type.isPrimitive(); + return unsafe.getObject(receiver, offset); + } + public Object loadValue(Node node) { if (type == boolean.class) { return unsafe.getBoolean(node, offset); @@ -172,7 +181,7 @@ assert Node.class.isAssignableFrom(clazz); return AccessController.doPrivileged(new PrivilegedAction() { public NodeClass run() { - return new NodeClass((Class) clazz, unsafeFieldOffsetProvider); + return new NodeClass((Class) clazz); } }); } @@ -180,60 +189,61 @@ // The comprehensive list of all fields. private final NodeField[] fields; - // Separate arrays for the frequently accessed field offsets. - private final long parentOffset; - private final long[] childOffsets; - private final long[] childrenOffsets; - private final long[] cloneableOffsets; + // 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 clazz; public static NodeClass get(Class clazz) { return nodeClasses.get(clazz); } - public NodeClass(Class clazz, FieldOffsetProvider fieldOffsetProvider) { + public NodeClass(Class clazz) { List fieldsList = new ArrayList<>(); - long parentFieldOffset = -1; - List childOffsetsList = new ArrayList<>(); - List childrenOffsetsList = new ArrayList<>(); - List cloneableOffsetsList = new ArrayList<>(); + NodeField parentFieldTmp = null; + List childFieldList = new ArrayList<>(); + List childrenFieldList = new ArrayList<>(); + List cloneableFieldList = new ArrayList<>(); for (Field field : getAllFields(clazz)) { if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) { continue; } - NodeFieldKind kind; + NodeField nodeField; if (field.getDeclaringClass() == Node.class && field.getName().equals("parent")) { assert Node.class.isAssignableFrom(field.getType()); - kind = NodeFieldKind.PARENT; - parentFieldOffset = fieldOffsetProvider.objectFieldOffset(field); + nodeField = NodeField.create(NodeFieldKind.PARENT, field); + parentFieldTmp = nodeField; } else if (field.getAnnotation(Child.class) != null) { checkChildField(field); - kind = NodeFieldKind.CHILD; - childOffsetsList.add(fieldOffsetProvider.objectFieldOffset(field)); + nodeField = NodeField.create(NodeFieldKind.CHILD, field); + childFieldList.add(nodeField); } else if (field.getAnnotation(Children.class) != null) { checkChildrenField(field); - kind = NodeFieldKind.CHILDREN; - childrenOffsetsList.add(fieldOffsetProvider.objectFieldOffset(field)); - } else if (NodeCloneable.class.isAssignableFrom(field.getType())) { - kind = NodeFieldKind.DATA; - cloneableOffsetsList.add(fieldOffsetProvider.objectFieldOffset(field)); + nodeField = NodeField.create(NodeFieldKind.CHILDREN, field); + childrenFieldList.add(nodeField); } else { - kind = NodeFieldKind.DATA; + nodeField = NodeField.create(NodeFieldKind.DATA, field); + if (NodeCloneable.class.isAssignableFrom(field.getType())) { + cloneableFieldList.add(nodeField); + } } - fieldsList.add(new NodeField(kind, field.getType(), field.getName(), fieldOffsetProvider.objectFieldOffset(field))); + fieldsList.add(nodeField); } - if (parentFieldOffset < 0) { + if (parentFieldTmp == null) { throw new AssertionError("parent field not found"); } this.fields = fieldsList.toArray(new NodeField[fieldsList.size()]); - this.parentOffset = parentFieldOffset; - this.childOffsets = toLongArray(childOffsetsList); - this.childrenOffsets = toLongArray(childrenOffsetsList); - this.cloneableOffsets = toLongArray(cloneableOffsetsList); + 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; } @@ -263,29 +273,28 @@ return fields; } - public long getParentOffset() { - return parentOffset; + public NodeField getParentField() { + return parentField; } - public long[] getChildOffsets() { - return childOffsets; + public NodeField[] getChildFields() { + return childFields; } - public long[] getChildrenOffsets() { - return childrenOffsets; + public NodeField[] getChildrenFields() { + return childrenFields; } @Override public int hashCode() { - return Arrays.hashCode(fields) ^ Arrays.hashCode(childOffsets) ^ Arrays.hashCode(childrenOffsets) ^ ((Long) parentOffset).hashCode(); + return clazz.hashCode(); } @Override public boolean equals(Object obj) { if (obj instanceof NodeClass) { NodeClass other = (NodeClass) obj; - return Arrays.equals(fields, other.fields) && Arrays.equals(childOffsets, other.childOffsets) && Arrays.equals(childrenOffsets, other.childrenOffsets) && - parentOffset == other.parentOffset; + return clazz.equals(other.clazz); } return false; } @@ -307,9 +316,9 @@ } private int childrenCount() { - int nodeCount = childOffsets.length; - for (long fieldOffset : childrenOffsets) { - Object[] children = ((Object[]) unsafe.getObject(node, fieldOffset)); + int nodeCount = childFields.length; + for (NodeField childrenField : childrenFields) { + Object[] children = ((Object[]) childrenField.getObject(node)); if (children != null) { nodeCount += children.length; } @@ -318,12 +327,12 @@ } private Node nodeAt(int idx) { - int nodeCount = childOffsets.length; + int nodeCount = childFields.length; if (idx < nodeCount) { - return (Node) unsafe.getObject(node, childOffsets[idx]); + return (Node) childFields[idx].getObject(node); } else { - for (long fieldOffset : childrenOffsets) { - Object[] nodeArray = (Object[]) unsafe.getObject(node, fieldOffset); + for (NodeField childrenField : childrenFields) { + Object[] nodeArray = (Object[]) childrenField.getObject(node); if (idx < nodeCount + nodeArray.length) { return (Node) nodeArray[idx - nodeCount]; } @@ -429,14 +438,6 @@ } } - private static long[] toLongArray(List list) { - long[] array = new long[list.size()]; - for (int i = 0; i < list.size(); i++) { - array[i] = list.get(i); - } - return array; - } - private static final Unsafe unsafe = getUnsafe(); private static Unsafe getUnsafe() { @@ -462,34 +463,34 @@ final Node clone = orig.copy(); NodeClass nodeClass = NodeClass.get(clone.getClass()); - unsafe.putObject(clone, nodeClass.parentOffset, null); + nodeClass.parentField.putObject(clone, null); - for (long fieldOffset : nodeClass.childOffsets) { - Node child = (Node) unsafe.getObject(orig, fieldOffset); + for (NodeField childField : nodeClass.childFields) { + Node child = (Node) childField.getObject(orig); if (child != null) { Node clonedChild = child.deepCopy(); - unsafe.putObject(clonedChild, nodeClass.parentOffset, clone); - unsafe.putObject(clone, fieldOffset, clonedChild); + nodeClass.parentField.putObject(clonedChild, clone); + childField.putObject(clone, clonedChild); } } - for (long fieldOffset : nodeClass.childrenOffsets) { - Object[] children = (Object[]) unsafe.getObject(orig, fieldOffset); + for (NodeField childrenField : nodeClass.childrenFields) { + Object[] children = (Object[]) childrenField.getObject(orig); if (children != null) { Object[] clonedChildren = (Object[]) Array.newInstance(children.getClass().getComponentType(), children.length); for (int i = 0; i < children.length; i++) { if (children[i] != null) { Node clonedChild = ((Node) children[i]).deepCopy(); clonedChildren[i] = clonedChild; - unsafe.putObject(clonedChild, nodeClass.parentOffset, clone); + nodeClass.parentField.putObject(clonedChild, clone); } } - unsafe.putObject(clone, fieldOffset, clonedChildren); + childrenField.putObject(clone, clonedChildren); } } - for (long fieldOffset : nodeClass.cloneableOffsets) { - Object cloneable = unsafe.getObject(clone, fieldOffset); - if (cloneable != null && cloneable == unsafe.getObject(orig, fieldOffset)) { - unsafe.putObject(clone, fieldOffset, ((NodeCloneable) cloneable).clone()); + for (NodeField cloneableField : nodeClass.cloneableFields) { + Object cloneable = cloneableField.getObject(clone); + if (cloneable != null && cloneable == cloneableField.getObject(orig)) { + cloneableField.putObject(clone, ((NodeCloneable) cloneable).clone()); } } return clone; @@ -499,14 +500,14 @@ List nodes = new ArrayList<>(); NodeClass nodeClass = NodeClass.get(node.getClass()); - for (long fieldOffset : nodeClass.childOffsets) { - Object child = unsafe.getObject(node, fieldOffset); + for (NodeField nodeField : nodeClass.childFields) { + Object child = nodeField.getObject(node); if (child != null) { nodes.add((Node) child); } } - for (long fieldOffset : nodeClass.childrenOffsets) { - Object[] children = (Object[]) unsafe.getObject(node, fieldOffset); + for (NodeField nodeField : nodeClass.childrenFields) { + Object[] children = (Object[]) nodeField.getObject(node); if (children != null) { for (Object child : children) { if (child != null) { @@ -522,21 +523,21 @@ public static boolean replaceChild(Node parent, Node oldChild, Node newChild) { NodeClass nodeClass = NodeClass.get(parent.getClass()); - for (long fieldOffset : nodeClass.getChildOffsets()) { - if (unsafe.getObject(parent, fieldOffset) == oldChild) { - assert assertAssignable(nodeClass, fieldOffset, newChild); - unsafe.putObject(parent, fieldOffset, newChild); + for (NodeField nodeField : nodeClass.getChildFields()) { + if (nodeField.getObject(parent) == oldChild) { + assert assertAssignable(nodeField, newChild); + nodeField.putObject(parent, newChild); return true; } } - for (long fieldOffset : nodeClass.getChildrenOffsets()) { - Object arrayObject = unsafe.getObject(parent, fieldOffset); + for (NodeField nodeField : nodeClass.getChildrenFields()) { + Object arrayObject = nodeField.getObject(parent); if (arrayObject != null) { Object[] array = (Object[]) arrayObject; for (int i = 0; i < array.length; i++) { if (array[i] == oldChild) { - assert assertAssignable(nodeClass, fieldOffset, newChild); + assert assertAssignable(nodeField, newChild); array[i] = newChild; return true; } @@ -546,27 +547,23 @@ return false; } - private static boolean assertAssignable(NodeClass clazz, long fieldOffset, Object newValue) { + private static boolean assertAssignable(NodeField field, Object newValue) { if (newValue == null) { return true; } - for (NodeField field : clazz.getFields()) { - if (field.getOffset() == fieldOffset) { - if (field.getKind() == NodeFieldKind.CHILD) { - 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.getType().getName(); - return false; - } - } else if (field.getKind() == NodeFieldKind.CHILDREN) { - 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.getType().getName(); - return false; - } - } + if (field.getKind() == NodeFieldKind.CHILD) { + 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.getType().getName(); + return false; + } + } else if (field.getKind() == NodeFieldKind.CHILDREN) { + 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.getType().getName(); + return false; } } throw new IllegalArgumentException(); diff -r 11ec0a5c5518 -r 6ba170cb6f53 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java Wed Jan 21 11:00:48 2015 -0800 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/serial/PostOrderDeserializer.java Thu Jan 22 00:37:29 2015 +0100 @@ -259,8 +259,7 @@ private static Node updateParent(Node parent, Node child) { if (child != null) { - long parentOffset = NodeClass.get(child.getClass()).getParentOffset(); - unsafe.putObject(child, parentOffset, parent); + NodeClass.get(child.getClass()).getParentField().putObject(child, parent); } return child; }