Mercurial > hg > graal-compiler
diff graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java @ 20129:5b7db8941fd7
Truffle: make NodeClass and NodeField a top-level class.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Thu, 02 Apr 2015 01:22:41 +0200 |
parents | a0971187a38a |
children | 8dc73c226c63 |
line wrap: on
line diff
--- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Thu Apr 02 14:28:27 2015 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/NodeUtil.java Thu Apr 02 01:22:41 2015 +0200 @@ -27,7 +27,6 @@ import java.io.*; import java.lang.annotation.*; import java.lang.reflect.*; -import java.security.*; import java.util.*; import sun.misc.*; @@ -35,15 +34,13 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.instrument.ProbeNode.WrapperNode; -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 com.oracle.truffle.api.source.*; /** * Utility class that manages the special access methods for node instances. */ public final class NodeUtil { - private static final boolean USE_UNSAFE = Boolean.getBoolean("truffle.unsafe"); /** * Interface that allows the customization of field offsets used for {@link Unsafe} field @@ -56,399 +53,6 @@ int getTypeSize(Class<?> clazz); } - private static final FieldOffsetProvider unsafeFieldOffsetProvider = new FieldOffsetProvider() { - - @Override - public long objectFieldOffset(Field field) { - return unsafe.objectFieldOffset(field); - } - - @Override - public int getTypeSize(Class<?> clazz) { - if (!clazz.isPrimitive()) { - return Unsafe.ARRAY_OBJECT_INDEX_SCALE; - } else if (clazz == int.class) { - return Unsafe.ARRAY_INT_INDEX_SCALE; - } else { - throw new UnsupportedOperationException("unsupported field type: " + clazz); - } - } - }; - - public static enum NodeFieldKind { - /** The single {@link Node#getParent() parent} field. */ - PARENT, - /** A field annotated with {@link Child}. */ - CHILD, - /** A field annotated with {@link Children}. */ - CHILDREN, - /** A normal non-child data field of the node. */ - DATA - } - - /** - * Information about a field in a {@link Node} class. - */ - public abstract static class NodeField { - - private final NodeFieldKind kind; - private final String name; - protected final Class<?> type; - protected final long offset; - - protected NodeField(NodeFieldKind kind, Field field) { - this.kind = kind; - this.type = field.getType(); - this.name = field.getName(); - this.offset = unsafeFieldOffsetProvider.objectFieldOffset(field); - } - - protected static NodeField create(NodeFieldKind kind, Field field) { - if (USE_UNSAFE) { - return new UnsafeNodeField(kind, field); - } else { - return new ReflectionNodeField(kind, field); - } - } - - public NodeFieldKind getKind() { - return kind; - } - - public Class<?> getType() { - return type; - } - - public String getName() { - return name; - } - - public long getOffset() { - return offset; - } - - public abstract void putObject(Node receiver, Object value); - - public abstract Object getObject(Node receiver); - - public abstract Object loadValue(Node node); - - @Override - public int hashCode() { - return kind.hashCode() | type.hashCode() | name.hashCode() | ((Long) offset).hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof NodeField) { - NodeField other = (NodeField) obj; - return offset == other.offset && name.equals(other.name) && type.equals(other.type) && kind.equals(other.kind); - } - return false; - } - } - - private static final class UnsafeNodeField extends NodeField { - protected UnsafeNodeField(NodeFieldKind kind, Field field) { - super(kind, field); - } - - @Override - public void putObject(Node receiver, Object value) { - if (!type.isPrimitive() && value == null || type.isInstance(value)) { - unsafe.putObject(receiver, offset, value); - } else { - throw new IllegalArgumentException(); - } - } - - @Override - public Object getObject(Node receiver) { - if (!type.isPrimitive()) { - return unsafe.getObject(receiver, offset); - } else { - throw new IllegalArgumentException(); - } - } - - @Override - public Object loadValue(Node node) { - if (type == boolean.class) { - return unsafe.getBoolean(node, offset); - } else if (type == byte.class) { - return unsafe.getByte(node, offset); - } else if (type == short.class) { - return unsafe.getShort(node, offset); - } else if (type == char.class) { - return unsafe.getChar(node, offset); - } else if (type == int.class) { - return unsafe.getInt(node, offset); - } else if (type == long.class) { - return unsafe.getLong(node, offset); - } else if (type == float.class) { - return unsafe.getFloat(node, offset); - } else if (type == double.class) { - return unsafe.getDouble(node, offset); - } else { - return unsafe.getObject(node, offset); - } - } - } - - private static final class ReflectionNodeField extends NodeField { - private final Field field; - - protected ReflectionNodeField(NodeFieldKind kind, Field field) { - super(kind, field); - this.field = field; - field.setAccessible(true); - } - - @Override - public void putObject(Node receiver, Object value) { - assert !type.isPrimitive() && value == null || type.isInstance(value); - try { - field.set(receiver, value); - } catch (IllegalAccessException e) { - throw new AssertionError(e); - } - } - - @Override - public Object getObject(Node receiver) { - assert !type.isPrimitive(); - try { - return field.get(receiver); - } catch (IllegalAccessException e) { - throw new AssertionError(e); - } - } - - @Override - public Object loadValue(Node node) { - try { - if (type == boolean.class) { - return field.getBoolean(node); - } else if (type == byte.class) { - return field.getByte(node); - } else if (type == short.class) { - return field.getShort(node); - } else if (type == char.class) { - return field.getChar(node); - } else if (type == int.class) { - return field.getInt(node); - } else if (type == long.class) { - return field.getLong(node); - } else if (type == float.class) { - return field.getFloat(node); - } else if (type == double.class) { - return field.getDouble(node); - } else { - return field.get(node); - } - } catch (IllegalAccessException e) { - throw new AssertionError(e); - } - } - } - - /** - * Information about a {@link Node} class. A single instance of this class is allocated for - * every subclass of {@link Node} that is used. - */ - public static final class NodeClass { - private static final ClassValue<NodeClass> nodeClasses = new ClassValue<NodeClass>() { - @SuppressWarnings("unchecked") - @Override - protected NodeClass computeValue(final Class<?> clazz) { - assert Node.class.isAssignableFrom(clazz); - return AccessController.doPrivileged(new PrivilegedAction<NodeClass>() { - public NodeClass run() { - return new NodeClass((Class<? extends Node>) clazz); - } - }); - } - }; - - // The comprehensive list of all fields. - private final NodeField[] fields; - // 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<? extends Node> clazz; - - public static NodeClass get(Class<? extends Node> clazz) { - return nodeClasses.get(clazz); - } - - public NodeClass(Class<? extends Node> clazz) { - List<NodeField> fieldsList = new ArrayList<>(); - NodeField parentFieldTmp = null; - List<NodeField> childFieldList = new ArrayList<>(); - List<NodeField> childrenFieldList = new ArrayList<>(); - List<NodeField> cloneableFieldList = new ArrayList<>(); - - for (Field field : getAllFields(clazz)) { - if (Modifier.isStatic(field.getModifiers()) || field.isSynthetic()) { - continue; - } - - NodeField nodeField; - if (field.getDeclaringClass() == Node.class && field.getName().equals("parent")) { - assert Node.class.isAssignableFrom(field.getType()); - nodeField = NodeField.create(NodeFieldKind.PARENT, field); - parentFieldTmp = nodeField; - } else if (field.getAnnotation(Child.class) != null) { - checkChildField(field); - nodeField = NodeField.create(NodeFieldKind.CHILD, field); - childFieldList.add(nodeField); - } else if (field.getAnnotation(Children.class) != null) { - checkChildrenField(field); - nodeField = NodeField.create(NodeFieldKind.CHILDREN, field); - childrenFieldList.add(nodeField); - } else { - nodeField = NodeField.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(new NodeField[fieldsList.size()]); - 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; - } - - 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 NodeField[] getFields() { - return fields; - } - - public NodeField getParentField() { - return parentField; - } - - public NodeField[] getChildFields() { - return childFields; - } - - public NodeField[] 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<Node> makeIterator(Node node) { - assert clazz.isInstance(node); - return new NodeIterator(node); - } - - private final class NodeIterator implements Iterator<Node> { - private final Node node; - private final int childrenCount; - private int index; - - protected NodeIterator(Node node) { - this.node = node; - this.index = 0; - this.childrenCount = childrenCount(); - } - - private int childrenCount() { - int nodeCount = childFields.length; - for (NodeField childrenField : childrenFields) { - Object[] children = ((Object[]) childrenField.getObject(node)); - if (children != null) { - nodeCount += children.length; - } - } - return nodeCount; - } - - private Node nodeAt(int idx) { - int nodeCount = childFields.length; - if (idx < nodeCount) { - return (Node) childFields[idx].getObject(node); - } else { - for (NodeField childrenField : childrenFields) { - Object[] nodeArray = (Object[]) childrenField.getObject(node); - if (idx < nodeCount + nodeArray.length) { - return (Node) nodeArray[idx - nodeCount]; - } - nodeCount += nodeArray.length; - } - } - return null; - } - - private void forward() { - if (index < childrenCount) { - index++; - } - } - - public boolean hasNext() { - return index < childrenCount; - } - - public Node next() { - try { - return nodeAt(index); - } finally { - forward(); - } - } - - public void remove() { - throw new UnsupportedOperationException(); - } - } - } - static Iterator<Node> makeIterator(Node node) { return NodeClass.get(node.getClass()).makeIterator(node); } @@ -521,22 +125,6 @@ } } - private static final Unsafe unsafe = getUnsafe(); - - private static Unsafe getUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException e) { - } - try { - Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeInstance.setAccessible(true); - return (Unsafe) theUnsafeInstance.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); - } - } - @SuppressWarnings("unchecked") public static <T extends Node> T cloneNode(T orig) { return (T) orig.deepCopy(); @@ -546,17 +134,17 @@ final Node clone = orig.copy(); NodeClass nodeClass = NodeClass.get(clone.getClass()); - nodeClass.parentField.putObject(clone, null); + nodeClass.getParentField().putObject(clone, null); - for (NodeField childField : nodeClass.childFields) { + for (NodeFieldAccessor childField : nodeClass.getChildFields()) { Node child = (Node) childField.getObject(orig); if (child != null) { Node clonedChild = child.deepCopy(); - nodeClass.parentField.putObject(clonedChild, clone); + nodeClass.getParentField().putObject(clonedChild, clone); childField.putObject(clone, clonedChild); } } - for (NodeField childrenField : nodeClass.childrenFields) { + for (NodeFieldAccessor childrenField : nodeClass.getChildrenFields()) { Object[] children = (Object[]) childrenField.getObject(orig); if (children != null) { Object[] clonedChildren = (Object[]) Array.newInstance(children.getClass().getComponentType(), children.length); @@ -564,13 +152,13 @@ if (children[i] != null) { Node clonedChild = ((Node) children[i]).deepCopy(); clonedChildren[i] = clonedChild; - nodeClass.parentField.putObject(clonedChild, clone); + nodeClass.getParentField().putObject(clonedChild, clone); } } childrenField.putObject(clone, clonedChildren); } } - for (NodeField cloneableField : nodeClass.cloneableFields) { + for (NodeFieldAccessor cloneableField : nodeClass.getCloneableFields()) { Object cloneable = cloneableField.getObject(clone); if (cloneable != null && cloneable == cloneableField.getObject(orig)) { cloneableField.putObject(clone, ((NodeCloneable) cloneable).clone()); @@ -583,13 +171,13 @@ List<Node> nodes = new ArrayList<>(); NodeClass nodeClass = NodeClass.get(node.getClass()); - for (NodeField nodeField : nodeClass.childFields) { + for (NodeFieldAccessor nodeField : nodeClass.getChildFields()) { Object child = nodeField.getObject(node); if (child != null) { nodes.add((Node) child); } } - for (NodeField nodeField : nodeClass.childrenFields) { + for (NodeFieldAccessor nodeField : nodeClass.getChildrenFields()) { Object[] children = (Object[]) nodeField.getObject(node); if (children != null) { for (Object child : children) { @@ -611,7 +199,7 @@ public static boolean replaceChild(Node parent, Node oldChild, Node newChild) { NodeClass nodeClass = NodeClass.get(parent.getClass()); - for (NodeField nodeField : nodeClass.getChildFields()) { + for (NodeFieldAccessor nodeField : nodeClass.getChildFields()) { if (nodeField.getObject(parent) == oldChild) { assert assertAssignable(nodeField, newChild); nodeField.putObject(parent, newChild); @@ -619,7 +207,7 @@ } } - for (NodeField nodeField : nodeClass.getChildrenFields()) { + for (NodeFieldAccessor nodeField : nodeClass.getChildrenFields()) { Object arrayObject = nodeField.getObject(parent); if (arrayObject != null) { Object[] array = (Object[]) arrayObject; @@ -635,7 +223,7 @@ return false; } - private static boolean assertAssignable(NodeField field, Object newValue) { + private static boolean assertAssignable(NodeFieldAccessor field, Object newValue) { if (newValue == null) { return true; } @@ -662,17 +250,17 @@ * * @return the field (possibly an array) holding the child, {@code null} if not found. */ - public static NodeField findChildField(Node parent, Node child) { + public static NodeFieldAccessor findChildField(Node parent, Node child) { assert child != null; NodeClass parentNodeClass = NodeClass.get(parent.getClass()); - for (NodeField field : parentNodeClass.getChildFields()) { + for (NodeFieldAccessor field : parentNodeClass.getChildFields()) { if (field.getObject(parent) == child) { return field; } } - for (NodeField field : parentNodeClass.getChildrenFields()) { + for (NodeFieldAccessor field : parentNodeClass.getChildrenFields()) { Object arrayObject = field.getObject(parent); if (arrayObject != null) { Object[] array = (Object[]) arrayObject; @@ -692,7 +280,7 @@ public static boolean isReplacementSafe(Node parent, Node oldChild, Node newChild) { assert newChild != null; if (parent != null) { - final NodeField field = findChildField(parent, oldChild); + final NodeFieldAccessor field = findChildField(parent, oldChild); if (field != null) { switch (field.getKind()) { case CHILD: @@ -716,7 +304,7 @@ Objects.requireNonNull(visitor); NodeClass parentNodeClass = NodeClass.get(parent.getClass()); - for (NodeField field : parentNodeClass.getChildFields()) { + for (NodeFieldAccessor field : parentNodeClass.getChildFields()) { Object child = field.getObject(parent); if (child != null) { if (!visitor.visit((Node) child)) { @@ -725,7 +313,7 @@ } } - for (NodeField field : parentNodeClass.getChildrenFields()) { + for (NodeFieldAccessor field : parentNodeClass.getChildrenFields()) { Object arrayObject = field.getObject(parent); if (arrayObject != null) { Object[] array = (Object[]) arrayObject; @@ -744,7 +332,7 @@ } /** Returns all declared fields in the class hierarchy. */ - private static Field[] getAllFields(Class<? extends Object> clazz) { + static Field[] getAllFields(Class<? extends Object> clazz) { Field[] declaredFields = clazz.getDeclaredFields(); if (clazz.getSuperclass() != null) { return concat(getAllFields(clazz.getSuperclass()), declaredFields); @@ -976,8 +564,8 @@ } private static String getNodeFieldName(Node parent, Node node, String defaultName) { - NodeField[] fields = NodeClass.get(parent.getClass()).fields; - for (NodeField field : fields) { + NodeFieldAccessor[] fields = NodeClass.get(parent.getClass()).getFields(); + for (NodeFieldAccessor field : fields) { Object value = field.loadValue(parent); if (field.getKind() == NodeFieldKind.CHILD && value == node) { return field.getName(); @@ -1053,10 +641,10 @@ p.print(nodeName(node)); - ArrayList<NodeField> childFields = new ArrayList<>(); + ArrayList<NodeFieldAccessor> childFields = new ArrayList<>(); String sep = ""; p.print("("); - for (NodeField field : NodeClass.get(node.getClass()).fields) { + 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) { @@ -1072,7 +660,7 @@ if (childFields.size() != 0) { p.print(" {"); - for (NodeField field : childFields) { + for (NodeFieldAccessor field : childFields) { printNewLine(p, level); p.print(field.getName());