Mercurial > hg > truffle
changeset 17247:eed077c367d3
improved performance of NodeClass initialization by improving the way information is derived from super NodeClasses
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 29 Sep 2014 13:59:41 +0200 |
parents | 44c5817156a9 |
children | 03826360967b |
files | graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/Fields.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputEdges.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/SuccessorEdges.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java |
diffstat | 8 files changed, 135 insertions(+), 106 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java Mon Sep 29 13:58:19 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java Mon Sep 29 13:59:41 2014 +0200 @@ -112,7 +112,7 @@ /** * Scans the fields in a class hierarchy. */ - public void scan(Class<?> clazz) { + public void scan(Class<?> clazz, boolean includeSuperclasses) { Class<?> currentClazz = clazz; do { for (Field field : currentClazz.getDeclaredFields()) { @@ -123,7 +123,7 @@ scanField(field, offset); } currentClazz = currentClazz.getSuperclass(); - } while (currentClazz.getSuperclass() != Object.class); + } while (includeSuperclasses && currentClazz.getSuperclass() != Object.class); } protected abstract void scanField(Field field, long offset);
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/Fields.java Mon Sep 29 13:58:19 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/Fields.java Mon Sep 29 13:59:41 2014 +0200 @@ -71,6 +71,12 @@ return offsets.length; } + public static void translateInto(Fields fields, ArrayList<FieldInfo> infos) { + for (int index = 0; index < fields.getCount(); index++) { + infos.add(new FieldInfo(fields.offsets[index], fields.names[index], fields.types[index])); + } + } + /** * Gets the value of a field for a given object. *
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java Mon Sep 29 13:58:19 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java Mon Sep 29 13:59:41 2014 +0200 @@ -28,8 +28,9 @@ import java.util.*; +import com.oracle.graal.compiler.common.FieldIntrospection.FieldInfo; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.FieldIntrospection.*; +import com.oracle.graal.graph.NodeClass.EdgeInfo; /** * Describes {@link Node} fields representing the set of inputs for the node or the set of the @@ -48,12 +49,18 @@ private final int directCount; private final Type type; - public Edges(Type type, int directCount, ArrayList<? extends FieldInfo> fields) { - super(fields); + public Edges(Type type, int directCount, ArrayList<? extends FieldInfo> edges) { + super(edges); this.type = type; this.directCount = directCount; } + public static void translateInto(Edges edges, ArrayList<EdgeInfo> infos) { + for (int index = 0; index < edges.getCount(); index++) { + infos.add(new EdgeInfo(edges.offsets[index], edges.getName(index), edges.getType(index))); + } + } + private static Node getNode(Node node, long offset) { return (Node) unsafe.getObject(node, offset); }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputEdges.java Mon Sep 29 13:58:19 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputEdges.java Mon Sep 29 13:59:41 2014 +0200 @@ -26,7 +26,7 @@ import java.util.*; -import com.oracle.graal.graph.NodeClass.InputFieldInfo; +import com.oracle.graal.graph.NodeClass.InputInfo; import com.oracle.graal.nodeinfo.*; public final class InputEdges extends Edges { @@ -34,14 +34,20 @@ private final InputType[] inputTypes; private final boolean[] isOptional; - public InputEdges(int directCount, ArrayList<InputFieldInfo> fields) { - super(Inputs, directCount, fields); + public InputEdges(int directCount, ArrayList<InputInfo> edges) { + super(Inputs, directCount, edges); - this.inputTypes = new InputType[fields.size()]; - this.isOptional = new boolean[fields.size()]; - for (int i = 0; i < fields.size(); i++) { - this.inputTypes[i] = fields.get(i).inputType; - this.isOptional[i] = fields.get(i).optional; + this.inputTypes = new InputType[edges.size()]; + this.isOptional = new boolean[edges.size()]; + for (int i = 0; i < edges.size(); i++) { + this.inputTypes[i] = edges.get(i).inputType; + this.isOptional[i] = edges.get(i).optional; + } + } + + public static void translateInto(InputEdges inputs, ArrayList<InputInfo> infos) { + for (int index = 0; index < inputs.getCount(); index++) { + infos.add(new InputInfo(inputs.offsets[index], inputs.getName(index), inputs.getType(index), inputs.inputTypes[index], inputs.isOptional(index))); } }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Mon Sep 29 13:58:19 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Mon Sep 29 13:59:41 2014 +0200 @@ -22,10 +22,14 @@ */ package com.oracle.graal.graph; +import static com.oracle.graal.compiler.common.Fields.*; +import static com.oracle.graal.graph.Edges.*; +import static com.oracle.graal.graph.InputEdges.*; import static com.oracle.graal.graph.Node.*; import static com.oracle.graal.graph.util.CollectionsAccess.*; import static java.lang.reflect.Modifier.*; +import java.lang.annotation.*; import java.lang.reflect.*; import java.util.*; @@ -54,12 +58,20 @@ // Timers for creation of a NodeClass instance private static final DebugTimer Init = Debug.timer("NodeClass.Init"); private static final DebugTimer Init_FieldScanning = Debug.timer("NodeClass.Init.FieldScanning"); + private static final DebugTimer Init_FieldScanningInner = Debug.timer("NodeClass.Init.FieldScanning.Inner"); + private static final DebugTimer Init_AnnotationParsing = Debug.timer("NodeClass.Init.AnnotationParsing"); private static final DebugTimer Init_Edges = Debug.timer("NodeClass.Init.Edges"); private static final DebugTimer Init_Data = Debug.timer("NodeClass.Init.Data"); private static final DebugTimer Init_Naming = Debug.timer("NodeClass.Init.Naming"); private static final DebugTimer Init_AllowedUsages = Debug.timer("NodeClass.Init.AllowedUsages"); private static final DebugTimer Init_IterableIds = Debug.timer("NodeClass.Init.IterableIds"); + private static <T extends Annotation> T getAnnotation(AnnotatedElement e, Class<T> annotationClass) { + try (TimerCloseable s = Init_AnnotationParsing.start()) { + return e.getAnnotation(annotationClass); + } + } + /** * Gets the {@link NodeClass} associated with a given {@link Class}. */ @@ -77,7 +89,7 @@ try (TimerCloseable t = Init.start()) { value = (NodeClass) allClasses.get(key); if (value == null) { - GeneratedNode gen = c.getAnnotation(GeneratedNode.class); + GeneratedNode gen = getAnnotation(c, GeneratedNode.class); if (gen != null) { Class<? extends Node> originalNodeClass = (Class<? extends Node>) gen.value(); value = (NodeClass) allClasses.get(originalNodeClass); @@ -89,11 +101,12 @@ } } else { Class<?> superclass = c.getSuperclass(); + NodeClass superNodeClass = null; if (superclass != NODE_CLASS) { // Ensure NodeClass for superclass exists - get(superclass); + superNodeClass = get(superclass); } - value = new NodeClass(key); + value = new NodeClass(key, superNodeClass); } Object old = allClasses.putIfAbsent(key, value); assert old == null : old + " " + key; @@ -110,8 +123,9 @@ private static int nextIterableId = 0; - private final Edges inputs; - private final Edges successors; + private final InputEdges inputs; + private final SuccessorEdges successors; + private final NodeClass superNodeClass; private final boolean canGVN; private final int startGVNNumber; @@ -142,12 +156,13 @@ private final boolean isSimplifiable; private final boolean isLeafNode; - public NodeClass(Class<?> clazz) { - this(clazz, new DefaultCalcOffset(), null, 0); + public NodeClass(Class<?> clazz, NodeClass superNodeClass) { + this(clazz, superNodeClass, new DefaultCalcOffset(), null, 0); } - public NodeClass(Class<?> clazz, CalcOffset calcOffset, int[] presetIterableIds, int presetIterableId) { + public NodeClass(Class<?> clazz, NodeClass superNodeClass, CalcOffset calcOffset, int[] presetIterableIds, int presetIterableId) { super(clazz); + this.superNodeClass = superNodeClass; assert NODE_CLASS.isAssignableFrom(clazz); this.isCanonicalizable = Canonicalizable.class.isAssignableFrom(clazz); @@ -157,9 +172,9 @@ this.isSimplifiable = Simplifiable.class.isAssignableFrom(clazz); - FieldScanner fs = new FieldScanner(calcOffset); + FieldScanner fs = new FieldScanner(calcOffset, superNodeClass); try (TimerCloseable t = Init_FieldScanning.start()) { - fs.scan(clazz); + fs.scan(clazz, false); } try (TimerCloseable t1 = Init_Edges.start()) { @@ -175,14 +190,13 @@ canGVN = Node.ValueNumberable.class.isAssignableFrom(clazz); startGVNNumber = clazz.hashCode(); - String newNameTemplate = null; - String newShortName; + NodeInfo info = getAnnotation(clazz, NodeInfo.class); try (TimerCloseable t1 = Init_Naming.start()) { - newShortName = clazz.getSimpleName(); + String newNameTemplate = null; + String newShortName = clazz.getSimpleName(); if (newShortName.endsWith("Node") && !newShortName.equals("StartNode") && !newShortName.equals("EndNode")) { newShortName = newShortName.substring(0, newShortName.length() - 4); } - NodeInfo info = clazz.getAnnotation(NodeInfo.class); assert info != null : "missing " + NodeInfo.class.getSimpleName() + " annotation on " + clazz; if (!info.shortName().isEmpty()) { newShortName = info.shortName(); @@ -190,23 +204,14 @@ if (!info.nameTemplate().isEmpty()) { newNameTemplate = info.nameTemplate(); } + this.nameTemplate = newNameTemplate == null ? newShortName : newNameTemplate; + this.shortName = newShortName; } - EnumSet<InputType> newAllowedUsageTypes = EnumSet.noneOf(InputType.class); try (TimerCloseable t1 = Init_AllowedUsages.start()) { - Class<?> current = clazz; - do { - NodeInfo currentInfo = current.getAnnotation(NodeInfo.class); - if (currentInfo != null) { - if (currentInfo.allowedUsageTypes().length > 0) { - newAllowedUsageTypes.addAll(Arrays.asList(currentInfo.allowedUsageTypes())); - } - } - current = current.getSuperclass(); - } while (current != Node.class); + allowedUsageTypes = superNodeClass == null ? EnumSet.noneOf(InputType.class) : superNodeClass.allowedUsageTypes.clone(); + allowedUsageTypes.addAll(Arrays.asList(info.allowedUsageTypes())); } - this.nameTemplate = newNameTemplate == null ? newShortName : newNameTemplate; - this.allowedUsageTypes = newAllowedUsageTypes; - this.shortName = newShortName; + if (presetIterableIds != null) { this.iterableIds = presetIterableIds; this.iterableId = presetIterableId; @@ -215,15 +220,12 @@ try (TimerCloseable t1 = Init_IterableIds.start()) { this.iterableId = nextIterableId++; - Class<?> superclass = clazz.getSuperclass(); - while (superclass != NODE_CLASS) { - if (IterableNodeType.class.isAssignableFrom(superclass)) { - NodeClass superNodeClass = NodeClass.get(superclass); - assert !containsId(this.iterableId, superNodeClass.iterableIds); - superNodeClass.iterableIds = Arrays.copyOf(superNodeClass.iterableIds, superNodeClass.iterableIds.length + 1); - superNodeClass.iterableIds[superNodeClass.iterableIds.length - 1] = this.iterableId; - } - superclass = superclass.getSuperclass(); + NodeClass snc = superNodeClass; + while (snc != null && IterableNodeType.class.isAssignableFrom(snc.getClazz())) { + assert !containsId(this.iterableId, snc.iterableIds); + snc.iterableIds = Arrays.copyOf(snc.iterableIds, snc.iterableIds.length + 1); + snc.iterableIds[snc.iterableIds.length - 1] = this.iterableId; + snc = snc.superNodeClass; } this.iterableIds = new int[]{iterableId}; @@ -275,7 +277,7 @@ * * <pre> * if (node.getNodeClass().is(BeginNode.class)) { ... } - * + * * // Due to generated Node classes, the test below * // is *not* the same as the test above: * if (node.getClass() == BeginNode.class) { ... } @@ -284,7 +286,7 @@ * @param nodeClass a {@linkplain GeneratedNode non-generated} {@link Node} class */ public boolean is(Class<? extends Node> nodeClass) { - assert nodeClass.getAnnotation(GeneratedNode.class) == null : "cannot test NodeClas against generated " + nodeClass; + assert getAnnotation(nodeClass, GeneratedNode.class) == null : "cannot test NodeClas against generated " + nodeClass; return nodeClass == getClazz(); } @@ -330,9 +332,9 @@ /** * Describes a field representing an input or successor edge in a node. */ - protected static class EdgeFieldInfo extends FieldInfo { + protected static class EdgeInfo extends FieldInfo { - public EdgeFieldInfo(long offset, String name, Class<?> type) { + public EdgeInfo(long offset, String name, Class<?> type) { super(offset, name, type); } @@ -357,11 +359,11 @@ /** * Describes a field representing an {@linkplain Type#Inputs input} edge in a node. */ - protected static class InputFieldInfo extends EdgeFieldInfo { + protected static class InputInfo extends EdgeInfo { final InputType inputType; final boolean optional; - public InputFieldInfo(long offset, String name, Class<?> type, InputType inputType, boolean optional) { + public InputInfo(long offset, String name, Class<?> type, InputType inputType, boolean optional) { super(offset, name, type); this.inputType = inputType; this.optional = optional; @@ -375,55 +377,69 @@ protected static class FieldScanner extends BaseFieldScanner { - public final ArrayList<InputFieldInfo> inputs = new ArrayList<>(); - public final ArrayList<FieldInfo> successors = new ArrayList<>(); + public final ArrayList<InputInfo> inputs = new ArrayList<>(); + public final ArrayList<EdgeInfo> successors = new ArrayList<>(); int directInputs; int directSuccessors; - protected FieldScanner(CalcOffset calc) { + protected FieldScanner(CalcOffset calc, NodeClass superNodeClass) { super(calc); + if (superNodeClass != null) { + translateInto(superNodeClass.inputs, inputs); + translateInto(superNodeClass.successors, successors); + translateInto(superNodeClass.data, data); + directInputs = superNodeClass.inputs.getDirectCount(); + directSuccessors = superNodeClass.successors.getDirectCount(); + } } @Override protected void scanField(Field field, long offset) { - Class<?> type = field.getType(); - if (field.isAnnotationPresent(Node.Input.class) || field.isAnnotationPresent(Node.OptionalInput.class)) { - assert !field.isAnnotationPresent(Node.Successor.class) : "field cannot be both input and successor"; - assert field.isAnnotationPresent(Node.Input.class) ^ field.isAnnotationPresent(Node.OptionalInput.class) : "inputs can either be optional or non-optional"; - if (INPUT_LIST_CLASS.isAssignableFrom(type)) { - // NodeInputList fields should not be final since they are - // written (via Unsafe) in clearInputs() - GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "NodeInputList input field %s should not be final", field); - GraalInternalError.guarantee(!Modifier.isPublic(field.getModifiers()), "NodeInputList input field %s should not be public", field); - } else { - GraalInternalError.guarantee(NODE_CLASS.isAssignableFrom(type) || type.isInterface(), "invalid input type: %s", type); - GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "Node input field %s should not be final", field); - directInputs++; - } - InputType inputType; - if (field.isAnnotationPresent(Node.Input.class)) { - inputType = field.getAnnotation(Node.Input.class).value(); + Input inputAnnotation = getAnnotation(field, Node.Input.class); + OptionalInput optionalInputAnnotation = getAnnotation(field, Node.OptionalInput.class); + Successor successorAnnotation = getAnnotation(field, Successor.class); + try (TimerCloseable s = Init_FieldScanningInner.start()) { + Class<?> type = field.getType(); + int modifiers = field.getModifiers(); + + if (inputAnnotation != null || optionalInputAnnotation != null) { + assert successorAnnotation == null : "field cannot be both input and successor"; + if (INPUT_LIST_CLASS.isAssignableFrom(type)) { + // NodeInputList fields should not be final since they are + // written (via Unsafe) in clearInputs() + GraalInternalError.guarantee(!Modifier.isFinal(modifiers), "NodeInputList input field %s should not be final", field); + GraalInternalError.guarantee(!Modifier.isPublic(modifiers), "NodeInputList input field %s should not be public", field); + } else { + GraalInternalError.guarantee(NODE_CLASS.isAssignableFrom(type) || type.isInterface(), "invalid input type: %s", type); + GraalInternalError.guarantee(!Modifier.isFinal(modifiers), "Node input field %s should not be final", field); + directInputs++; + } + InputType inputType; + if (inputAnnotation != null) { + assert optionalInputAnnotation == null : "inputs can either be optional or non-optional"; + inputType = inputAnnotation.value(); + } else { + inputType = optionalInputAnnotation.value(); + } + inputs.add(new InputInfo(offset, field.getName(), type, inputType, field.isAnnotationPresent(Node.OptionalInput.class))); + } else if (successorAnnotation != null) { + if (SUCCESSOR_LIST_CLASS.isAssignableFrom(type)) { + // NodeSuccessorList fields should not be final since they are + // written (via Unsafe) in clearSuccessors() + GraalInternalError.guarantee(!Modifier.isFinal(modifiers), "NodeSuccessorList successor field % should not be final", field); + GraalInternalError.guarantee(!Modifier.isPublic(modifiers), "NodeSuccessorList successor field %s should not be public", field); + } else { + GraalInternalError.guarantee(NODE_CLASS.isAssignableFrom(type), "invalid successor type: %s", type); + GraalInternalError.guarantee(!Modifier.isFinal(modifiers), "Node successor field %s should not be final", field); + directSuccessors++; + } + successors.add(new EdgeInfo(offset, field.getName(), type)); } else { - inputType = field.getAnnotation(Node.OptionalInput.class).value(); + GraalInternalError.guarantee(!NODE_CLASS.isAssignableFrom(type) || field.getName().equals("Null"), "suspicious node field: %s", field); + GraalInternalError.guarantee(!INPUT_LIST_CLASS.isAssignableFrom(type), "suspicious node input list field: %s", field); + GraalInternalError.guarantee(!SUCCESSOR_LIST_CLASS.isAssignableFrom(type), "suspicious node successor list field: %s", field); + data.add(new FieldInfo(offset, field.getName(), type)); } - inputs.add(new InputFieldInfo(offset, field.getName(), type, inputType, field.isAnnotationPresent(Node.OptionalInput.class))); - } else if (field.isAnnotationPresent(Node.Successor.class)) { - if (SUCCESSOR_LIST_CLASS.isAssignableFrom(type)) { - // NodeSuccessorList fields should not be final since they are - // written (via Unsafe) in clearSuccessors() - GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "NodeSuccessorList successor field % should not be final", field); - GraalInternalError.guarantee(!Modifier.isPublic(field.getModifiers()), "NodeSuccessorList successor field %s should not be public", field); - } else { - GraalInternalError.guarantee(NODE_CLASS.isAssignableFrom(type), "invalid successor type: %s", type); - GraalInternalError.guarantee(!Modifier.isFinal(field.getModifiers()), "Node successor field %s should not be final", field); - directSuccessors++; - } - successors.add(new FieldInfo(offset, field.getName(), type)); - } else { - GraalInternalError.guarantee(!NODE_CLASS.isAssignableFrom(type) || field.getName().equals("Null"), "suspicious node field: %s", field); - GraalInternalError.guarantee(!INPUT_LIST_CLASS.isAssignableFrom(type), "suspicious node input list field: %s", field); - GraalInternalError.guarantee(!SUCCESSOR_LIST_CLASS.isAssignableFrom(type), "suspicious node successor list field: %s", field); - data.add(new FieldInfo(offset, field.getName(), type)); } } }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/SuccessorEdges.java Mon Sep 29 13:58:19 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/SuccessorEdges.java Mon Sep 29 13:59:41 2014 +0200 @@ -26,12 +26,12 @@ import java.util.*; -import com.oracle.graal.compiler.common.FieldIntrospection.FieldInfo; +import com.oracle.graal.graph.NodeClass.EdgeInfo; public final class SuccessorEdges extends Edges { - public SuccessorEdges(int directCount, ArrayList<FieldInfo> fields) { - super(Successors, directCount, fields); + public SuccessorEdges(int directCount, ArrayList<EdgeInfo> edges) { + super(Successors, directCount, edges); } @Override
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java Mon Sep 29 13:58:19 2014 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java Mon Sep 29 13:59:41 2014 +0200 @@ -65,7 +65,7 @@ super(clazz); ValueFieldScanner vfs = new ValueFieldScanner(calcOffset); - vfs.scan(clazz); + vfs.scan(clazz, true); values = new Values(vfs.valueAnnotations.get(CompositeValue.Component.class)); data = new Fields(vfs.data); @@ -79,11 +79,6 @@ } @Override - public void scan(Class<?> clazz) { - super.scan(clazz); - } - - @Override protected EnumSet<OperandFlag> getFlags(Field field) { EnumSet<OperandFlag> result = EnumSet.noneOf(OperandFlag.class); if (field.isAnnotationPresent(CompositeValue.Component.class)) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Mon Sep 29 13:58:19 2014 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Mon Sep 29 13:59:41 2014 +0200 @@ -128,14 +128,13 @@ return result; } - @Override public void scan(Class<?> clazz) { if (clazz.getAnnotation(Opcode.class) != null) { opcodeConstant = clazz.getAnnotation(Opcode.class).value(); } opcodeField = null; - super.scan(clazz); + super.scan(clazz, true); if (opcodeConstant == null && opcodeField == null) { opcodeConstant = clazz.getSimpleName();