# HG changeset patch # User Doug Simon # Date 1411834578 -7200 # Node ID aef31f60e97006e264c9bcdc1780aca215b42334 # Parent 5b00a1e62a5ec70c5a78c1aeb7fc32c50f9340d7 converted all FieldIntrospection subclass to use Fields diff -r 5b00a1e62a5e -r aef31f60e970 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java Fri Sep 26 18:59:08 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/FieldIntrospection.java Sat Sep 27 18:16:18 2014 +0200 @@ -47,9 +47,11 @@ protected static final ConcurrentHashMap, FieldIntrospection> allClasses = new ConcurrentHashMap<>(); private final Class clazz; - protected long[] dataOffsets; - protected Map fieldNames; - protected Map> fieldTypes; + + /** + * The set of fields in {@link #clazz} that do long belong to a more specific category. + */ + protected Fields data; public FieldIntrospection(Class clazz) { this.clazz = clazz; @@ -59,20 +61,57 @@ return clazz; } + /** + * Gets the fields in {@link #getClazz()} that do long belong to specific category. + */ + public Fields getData() { + return data; + } + + /** + * Describes a field in a class during scanning. + */ + public static class FieldInfo implements Comparable { + public final long offset; + public final String name; + public final Class type; + + public FieldInfo(long offset, String name, Class type) { + this.offset = offset; + this.name = name; + this.type = type; + } + + /** + * Sorts fields in ascending order by their {@link #offset}s. + */ + public int compareTo(FieldInfo o) { + return offset < o.offset ? -1 : (offset > o.offset ? 1 : 0); + } + + @Override + public String toString() { + return "[" + offset + "]" + name + ":" + type.getSimpleName(); + } + } + public abstract static class BaseFieldScanner { private final CalcOffset calc; - /** The offsets of fields that are not specially handled by subclasses. */ - public final ArrayList dataOffsets = new ArrayList<>(); - - public final Map fieldNames = new HashMap<>(); - public final Map> fieldTypes = new HashMap<>(); + /** + * Fields not belonging to a more specific category defined by scanner subclasses are added + * to this list. + */ + public final ArrayList data = new ArrayList<>(); protected BaseFieldScanner(CalcOffset calc) { this.calc = calc; } + /** + * Scans the fields in a class hierarchy. + */ public void scan(Class clazz) { Class currentClazz = clazz; do { @@ -80,69 +119,13 @@ if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers())) { continue; } - Class type = field.getType(); long offset = calc.getOffset(field); - - // scanField() may overwrite the name with a customized name. - fieldNames.put(offset, field.getName()); - fieldTypes.put(offset, type); - - scanField(field, type, offset); + scanField(field, offset); } currentClazz = currentClazz.getSuperclass(); } while (currentClazz.getSuperclass() != Object.class); } - protected abstract void scanField(Field field, Class type, long offset); - } - - protected static void copyInto(long[] dest, long[] src) { - assert dest.length == src.length; - for (int i = 0; i < dest.length; i++) { - dest[i] = src[i]; - } - } - - protected static void copyInto(T[] dest, T[] src) { - assert dest.length == src.length; - for (int i = 0; i < dest.length; i++) { - dest[i] = src[i]; - } - } - - protected static void copyInto(T[] dest, List src) { - assert dest.length == src.size(); - for (int i = 0; i < dest.length; i++) { - dest[i] = src.get(i); - } - } - - protected static T[] arrayUsingSortedOffsets(Map map, long[] sortedOffsets, T[] result) { - for (int i = 0; i < sortedOffsets.length; i++) { - result[i] = map.get(sortedOffsets[i]); - } - return result; - } - - protected static long[] sortedLongCopy(ArrayList list1) { - Collections.sort(list1); - long[] result = new long[list1.size()]; - for (int i = 0; i < list1.size(); i++) { - result[i] = list1.get(i); - } - return result; - } - - protected static long[] sortedLongCopy(ArrayList list1, ArrayList list2) { - Collections.sort(list1); - Collections.sort(list2); - long[] result = new long[list1.size() + list2.size()]; - for (int i = 0; i < list1.size(); i++) { - result[i] = list1.get(i); - } - for (int i = 0; i < list2.size(); i++) { - result[list1.size() + i] = list2.get(i); - } - return result; + protected abstract void scanField(Field field, long offset); } } diff -r 5b00a1e62a5e -r aef31f60e970 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/Fields.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/Fields.java Fri Sep 26 18:59:08 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/Fields.java Sat Sep 27 18:16:18 2014 +0200 @@ -28,25 +28,39 @@ import sun.misc.*; +import com.oracle.graal.compiler.common.FieldIntrospection.FieldInfo; + /** * Describes fields in a class, primarily for access via {@link Unsafe}. */ public class Fields { - protected final Class clazz; + /** + * Offsets used with {@link Unsafe} to access the fields. + */ protected final long[] offsets; + + /** + * The names of the fields. + */ private final String[] names; + + /** + * The types of the fields. + */ private final Class[] types; - public Fields(Class clazz, long[] offsets, Map names, Map> types) { - this.clazz = clazz; - this.offsets = offsets; - + public Fields(ArrayList fields) { + Collections.sort(fields); + this.offsets = new long[fields.size()]; this.names = new String[offsets.length]; this.types = new Class[offsets.length]; - for (int i = 0; i < offsets.length; i++) { - this.names[i] = names.get(offsets[i]); - this.types[i] = types.get(offsets[i]); + int index = 0; + for (FieldInfo f : fields) { + offsets[index] = f.offset; + names[index] = f.name; + types[index] = f.type; + index++; } } @@ -126,44 +140,46 @@ * @param index the index of the field to check * @param value a value that will be assigned to the field */ - private boolean checkAssignableFrom(int index, Object value) { - assert value == null || getType(index).isAssignableFrom(value.getClass()) : String.format("%s.%s of type %s is not assignable from %s", clazz.getSimpleName(), getName(index), - getType(index).getSimpleName(), value.getClass().getSimpleName()); + private boolean checkAssignableFrom(Object object, int index, Object value) { + assert value == null || getType(index).isAssignableFrom(value.getClass()) : String.format("Field %s.%s of type %s is not assignable from %s", object.getClass().getSimpleName(), + getName(index), getType(index).getSimpleName(), value.getClass().getSimpleName()); return true; } public void set(Object object, int index, Object value) { - long dataOffset = offsets[index]; + long offset = offsets[index]; Class type = types[index]; if (type.isPrimitive()) { if (type == Integer.TYPE) { - unsafe.putInt(object, dataOffset, (Integer) value); + unsafe.putInt(object, offset, (Integer) value); } else if (type == Long.TYPE) { - unsafe.putLong(object, dataOffset, (Long) value); + unsafe.putLong(object, offset, (Long) value); } else if (type == Boolean.TYPE) { - unsafe.putBoolean(object, dataOffset, (Boolean) value); + unsafe.putBoolean(object, offset, (Boolean) value); } else if (type == Float.TYPE) { - unsafe.putFloat(object, dataOffset, (Float) value); + unsafe.putFloat(object, offset, (Float) value); } else if (type == Double.TYPE) { - unsafe.putDouble(object, dataOffset, (Double) value); + unsafe.putDouble(object, offset, (Double) value); } else if (type == Short.TYPE) { - unsafe.putShort(object, dataOffset, (Short) value); + unsafe.putShort(object, offset, (Short) value); } else if (type == Character.TYPE) { - unsafe.putChar(object, dataOffset, (Character) value); + unsafe.putChar(object, offset, (Character) value); } else if (type == Byte.TYPE) { - unsafe.putByte(object, dataOffset, (Byte) value); + unsafe.putByte(object, offset, (Byte) value); } else { assert false : "unhandled property type: " + type; } } else { - assert checkAssignableFrom(index, value); - unsafe.putObject(object, dataOffset, value); + assert checkAssignableFrom(object, index, value); + unsafe.putObject(object, offset, value); } } @Override public String toString() { - return clazz.getSimpleName(); + StringBuilder sb = new StringBuilder(getClass().getSimpleName()).append('['); + appendFields(sb); + return sb.append(']').toString(); } public void appendFields(StringBuilder sb) { @@ -216,4 +232,9 @@ assert !types[i].isPrimitive(); return unsafe.getObject(object, offsets[i]); } + + public void putObject(Object object, int i, Object value) { + assert checkAssignableFrom(object, i, value); + unsafe.putObject(object, offsets[i], value); + } } diff -r 5b00a1e62a5e -r aef31f60e970 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java Fri Sep 26 18:59:08 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java Sat Sep 27 18:16:18 2014 +0200 @@ -29,6 +29,7 @@ import java.util.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.FieldIntrospection.*; /** * Describes {@link Node} fields representing the set of inputs for the node or the set of the @@ -47,8 +48,8 @@ private final int directCount; private final Type type; - public Edges(Class nodeClass, Type type, int directCount, long[] offsets, Map names, Map> types) { - super(nodeClass, offsets, names, types); + public Edges(Type type, int directCount, ArrayList fields) { + super(fields); this.type = type; this.directCount = directCount; } @@ -134,7 +135,7 @@ * @param toNode the node to which the edges should be copied. */ public void copy(Node fromNode, Node toNode) { - assert fromNode.getNodeClass().getClazz() == clazz && toNode.getNodeClass().getClazz() == clazz; + assert fromNode.getNodeClass().getClazz() == toNode.getNodeClass().getClazz(); int index = 0; while (index < getDirectCount()) { initializeNode(toNode, index, getNode(fromNode, index)); @@ -169,7 +170,7 @@ } while (index < getCount()) { NodeList list = getNodeList(node, index); - assert list != null : clazz; + assert list != null : this; if (list.replaceFirst(key, replacement)) { return true; } @@ -235,7 +236,7 @@ * Determines if the edges of two given nodes are the same. */ public boolean areEqualIn(Node node, Node other) { - assert node.getNodeClass().getClazz() == clazz && other.getNodeClass().getClazz() == clazz; + assert node.getNodeClass().getClazz() == other.getNodeClass().getClazz(); int index = 0; while (index < directCount) { if (getNode(other, index) != getNode(node, index)) { diff -r 5b00a1e62a5e -r aef31f60e970 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputEdges.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputEdges.java Fri Sep 26 18:59:08 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputEdges.java Sat Sep 27 18:16:18 2014 +0200 @@ -26,6 +26,7 @@ import java.util.*; +import com.oracle.graal.graph.NodeClass.InputFieldInfo; import com.oracle.graal.nodeinfo.*; public final class InputEdges extends Edges { @@ -33,14 +34,14 @@ private final InputType[] inputTypes; private final boolean[] isOptional; - public InputEdges(Class nodeClass, int directCount, long[] offsets, Map names, Map> types, Map inputTypes, Set isOptional) { - super(nodeClass, Inputs, directCount, offsets, names, types); + public InputEdges(int directCount, ArrayList fields) { + super(Inputs, directCount, fields); - this.inputTypes = new InputType[offsets.length]; - this.isOptional = new boolean[offsets.length]; - for (int i = 0; i < offsets.length; i++) { - this.inputTypes[i] = inputTypes.get(offsets[i]); - this.isOptional[i] = isOptional.contains(offsets[i]); + 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; } } diff -r 5b00a1e62a5e -r aef31f60e970 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Sep 26 18:59:08 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Sat Sep 27 18:16:18 2014 +0200 @@ -885,7 +885,7 @@ */ public Map getDebugProperties(Map map) { NodeClass nodeClass = getNodeClass(); - Fields properties = nodeClass.getProperties(); + Fields properties = nodeClass.getData(); for (int i = 0; i < properties.getCount(); i++) { map.put(properties.getName(i), properties.get(this, i)); } diff -r 5b00a1e62a5e -r aef31f60e970 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Fri Sep 26 18:59:08 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Sat Sep 27 18:16:18 2014 +0200 @@ -32,6 +32,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; +import com.oracle.graal.graph.Edges.Type; import com.oracle.graal.graph.Graph.DuplicationReplacement; import com.oracle.graal.graph.Node.Input; import com.oracle.graal.graph.Node.Successor; @@ -111,7 +112,6 @@ private final Edges inputs; private final Edges successors; - private final Fields properties; private final boolean canGVN; private final int startGVNNumber; @@ -146,13 +146,6 @@ this(clazz, new DefaultCalcOffset(), null, 0); } - private static long[] sortedOffsets(ArrayList list1, ArrayList list2) { - if (list1.isEmpty() && list2.isEmpty()) { - return new long[0]; - } - return sortedLongCopy(list1, list2); - } - public NodeClass(Class clazz, CalcOffset calcOffset, int[] presetIterableIds, int presetIterableId) { super(clazz); assert NODE_CLASS.isAssignableFrom(clazz); @@ -170,16 +163,14 @@ } try (TimerCloseable t1 = Init_Edges.start()) { - successors = new SuccessorEdges(clazz, fs.successorOffsets.size(), sortedOffsets(fs.successorOffsets, fs.successorListOffsets), fs.fieldNames, fs.fieldTypes); - inputs = new InputEdges(clazz, fs.inputOffsets.size(), sortedOffsets(fs.inputOffsets, fs.inputListOffsets), fs.fieldNames, fs.fieldTypes, fs.types, fs.optionalInputs); + successors = new SuccessorEdges(fs.directSuccessors, fs.successors); + inputs = new InputEdges(fs.directInputs, fs.inputs); } try (TimerCloseable t1 = Init_Data.start()) { - properties = new Fields(clazz, sortedLongCopy(fs.dataOffsets), fs.fieldNames, fs.fieldTypes); + data = new Fields(fs.data); } isLeafNode = inputs.getCount() + successors.getCount() == 0; - fieldNames = fs.fieldNames; - fieldTypes = fs.fieldTypes; canGVN = Node.ValueNumberable.class.isAssignableFrom(clazz); startGVNNumber = clazz.hashCode(); @@ -336,21 +327,66 @@ return allowedUsageTypes; } + /** + * Describes a field representing an input or successor edge in a node. + */ + protected static class EdgeFieldInfo extends FieldInfo { + + public EdgeFieldInfo(long offset, String name, Class type) { + super(offset, name, type); + } + + /** + * Sorts non-list edges before list edges. + */ + @Override + public int compareTo(FieldInfo o) { + if (NodeList.class.isAssignableFrom(o.type)) { + if (!NodeList.class.isAssignableFrom(type)) { + return -1; + } + } else { + if (NodeList.class.isAssignableFrom(type)) { + return 1; + } + } + return super.compareTo(o); + } + } + + /** + * Describes a field representing an {@linkplain Type#Inputs input} edge in a node. + */ + protected static class InputFieldInfo extends EdgeFieldInfo { + final InputType inputType; + final boolean optional; + + public InputFieldInfo(long offset, String name, Class type, InputType inputType, boolean optional) { + super(offset, name, type); + this.inputType = inputType; + this.optional = optional; + } + + @Override + public String toString() { + return super.toString() + "{inputType=" + inputType + ", optional=" + optional + "}"; + } + } + protected static class FieldScanner extends BaseFieldScanner { - public final ArrayList inputOffsets = new ArrayList<>(); - public final ArrayList inputListOffsets = new ArrayList<>(); - public final ArrayList successorOffsets = new ArrayList<>(); - public final ArrayList successorListOffsets = new ArrayList<>(); - public final HashMap types = new HashMap<>(); - public final HashSet optionalInputs = new HashSet<>(); + public final ArrayList inputs = new ArrayList<>(); + public final ArrayList successors = new ArrayList<>(); + int directInputs; + int directSuccessors; protected FieldScanner(CalcOffset calc) { super(calc); } @Override - protected void scanField(Field field, Class type, long offset) { + 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"; @@ -359,37 +395,35 @@ // 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); - inputListOffsets.add(offset); } 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); - inputOffsets.add(offset); + directInputs++; } + InputType inputType; if (field.isAnnotationPresent(Node.Input.class)) { - types.put(offset, field.getAnnotation(Node.Input.class).value()); + inputType = field.getAnnotation(Node.Input.class).value(); } else { - types.put(offset, field.getAnnotation(Node.OptionalInput.class).value()); + inputType = field.getAnnotation(Node.OptionalInput.class).value(); } - if (field.isAnnotationPresent(Node.OptionalInput.class)) { - optionalInputs.add(offset); - } + 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); - successorListOffsets.add(offset); } 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); - successorOffsets.add(offset); + 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); - dataOffsets.add(offset); + data.add(new FieldInfo(offset, field.getName(), type)); } } } @@ -402,7 +436,7 @@ str.append("] ["); successors.appendFields(str); str.append("] ["); - properties.appendFields(str); + data.appendFields(str); str.append("]"); return str.toString(); } @@ -437,41 +471,41 @@ int number = 0; if (canGVN) { number = startGVNNumber; - for (int i = 0; i < properties.getCount(); ++i) { - Class type = properties.getType(i); + for (int i = 0; i < data.getCount(); ++i) { + Class type = data.getType(i); if (type.isPrimitive()) { if (type == Integer.TYPE) { - int intValue = properties.getInt(n, i); + int intValue = data.getInt(n, i); number += intValue; } else if (type == Long.TYPE) { - long longValue = properties.getLong(n, i); + long longValue = data.getLong(n, i); number += longValue ^ (longValue >>> 32); } else if (type == Boolean.TYPE) { - boolean booleanValue = properties.getBoolean(n, i); + boolean booleanValue = data.getBoolean(n, i); if (booleanValue) { number += 7; } } else if (type == Float.TYPE) { - float floatValue = properties.getFloat(n, i); + float floatValue = data.getFloat(n, i); number += Float.floatToRawIntBits(floatValue); } else if (type == Double.TYPE) { - double doubleValue = properties.getDouble(n, i); + double doubleValue = data.getDouble(n, i); long longValue = Double.doubleToRawLongBits(doubleValue); number += longValue ^ (longValue >>> 32); } else if (type == Short.TYPE) { - short shortValue = properties.getShort(n, i); + short shortValue = data.getShort(n, i); number += shortValue; } else if (type == Character.TYPE) { - char charValue = properties.getChar(n, i); + char charValue = data.getChar(n, i); number += charValue; } else if (type == Byte.TYPE) { - byte byteValue = properties.getByte(n, i); + byte byteValue = data.getByte(n, i); number += byteValue; } else { assert false : "unhandled property type: " + type; } } else { - Object o = properties.getObject(n, i); + Object o = data.getObject(n, i); number += deepHashCode0(o); } number *= 13; @@ -511,54 +545,54 @@ if (a.getClass() != b.getClass()) { return a == b; } - for (int i = 0; i < properties.getCount(); ++i) { - Class type = properties.getType(i); + for (int i = 0; i < data.getCount(); ++i) { + Class type = data.getType(i); if (type.isPrimitive()) { if (type == Integer.TYPE) { - int aInt = properties.getInt(a, i); - int bInt = properties.getInt(b, i); + int aInt = data.getInt(a, i); + int bInt = data.getInt(b, i); if (aInt != bInt) { return false; } } else if (type == Boolean.TYPE) { - boolean aBoolean = properties.getBoolean(a, i); - boolean bBoolean = properties.getBoolean(b, i); + boolean aBoolean = data.getBoolean(a, i); + boolean bBoolean = data.getBoolean(b, i); if (aBoolean != bBoolean) { return false; } } else if (type == Long.TYPE) { - long aLong = properties.getLong(a, i); - long bLong = properties.getLong(b, i); + long aLong = data.getLong(a, i); + long bLong = data.getLong(b, i); if (aLong != bLong) { return false; } } else if (type == Float.TYPE) { - float aFloat = properties.getFloat(a, i); - float bFloat = properties.getFloat(b, i); + float aFloat = data.getFloat(a, i); + float bFloat = data.getFloat(b, i); if (aFloat != bFloat) { return false; } } else if (type == Double.TYPE) { - double aDouble = properties.getDouble(a, i); - double bDouble = properties.getDouble(b, i); + double aDouble = data.getDouble(a, i); + double bDouble = data.getDouble(b, i); if (aDouble != bDouble) { return false; } } else if (type == Short.TYPE) { - short aShort = properties.getShort(a, i); - short bShort = properties.getShort(b, i); + short aShort = data.getShort(a, i); + short bShort = data.getShort(b, i); if (aShort != bShort) { return false; } } else if (type == Character.TYPE) { - char aChar = properties.getChar(a, i); - char bChar = properties.getChar(b, i); + char aChar = data.getChar(a, i); + char bChar = data.getChar(b, i); if (aChar != bChar) { return false; } } else if (type == Byte.TYPE) { - byte aByte = properties.getByte(a, i); - byte bByte = properties.getByte(b, i); + byte aByte = data.getByte(a, i); + byte bByte = data.getByte(b, i); if (aByte != bByte) { return false; } @@ -566,8 +600,8 @@ assert false : "unhandled type: " + type; } } else { - Object objectA = properties.getObject(a, i); - Object objectB = properties.getObject(b, i); + Object objectA = data.getObject(a, i); + Object objectB = data.getObject(b, i); if (objectA != objectB) { if (objectA != null && objectB != null) { if (!deepEquals0(objectA, objectB)) { @@ -596,13 +630,6 @@ return toEdges.isSame(fromEdges, pos.getIndex()); } - /** - * Gets the non-edge properties defined by this node class. - */ - public Fields getProperties() { - return properties; - } - static void updateEdgesInPlace(Node node, InplaceUpdateClosure duplicationReplacement, Edges edges) { int index = 0; while (index < edges.getDirectCount()) { diff -r 5b00a1e62a5e -r aef31f60e970 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/SuccessorEdges.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/SuccessorEdges.java Fri Sep 26 18:59:08 2014 -0700 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/SuccessorEdges.java Sat Sep 27 18:16:18 2014 +0200 @@ -26,10 +26,12 @@ import java.util.*; +import com.oracle.graal.compiler.common.FieldIntrospection.FieldInfo; + public final class SuccessorEdges extends Edges { - public SuccessorEdges(Class nodeClass, int directCount, long[] offsets, Map names, Map> types) { - super(nodeClass, Successors, directCount, offsets, names, types); + public SuccessorEdges(int directCount, ArrayList fields) { + super(Successors, directCount, fields); } @Override diff -r 5b00a1e62a5e -r aef31f60e970 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java Fri Sep 26 18:59:08 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java Sat Sep 27 18:16:18 2014 +0200 @@ -57,37 +57,24 @@ } } - private final int directComponentCount; - private final long[] componentOffsets; - private final EnumSet[] componentFlags; - public CompositeValueClass(Class clazz) { this(clazz, new DefaultCalcOffset()); } - @SuppressWarnings("unchecked") public CompositeValueClass(Class clazz, CalcOffset calcOffset) { super(clazz); - ValueFieldScanner scanner = new ValueFieldScanner(calcOffset); - scanner.scan(clazz); + ValueFieldScanner vfs = new ValueFieldScanner(calcOffset); + vfs.scan(clazz); - OperandModeAnnotation mode = scanner.valueAnnotations.get(CompositeValue.Component.class); - directComponentCount = mode.scalarOffsets.size(); - componentOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets); - componentFlags = arrayUsingSortedOffsets(mode.flags, componentOffsets, new EnumSet[componentOffsets.length]); - - dataOffsets = sortedLongCopy(scanner.dataOffsets); - - fieldNames = scanner.fieldNames; - fieldTypes = scanner.fieldTypes; + values = new Values(vfs.valueAnnotations.get(CompositeValue.Component.class)); + data = new Fields(vfs.data); } private static class ValueFieldScanner extends FieldScanner { public ValueFieldScanner(CalcOffset calc) { super(calc); - valueAnnotations.put(CompositeValue.Component.class, new OperandModeAnnotation()); } @@ -111,57 +98,53 @@ @Override public String toString() { StringBuilder str = new StringBuilder(); - str.append(getClass().getSimpleName()).append(" ").append(getClazz().getSimpleName()).append(" component["); - for (int i = 0; i < componentOffsets.length; i++) { - str.append(i == 0 ? "" : ", ").append(componentOffsets[i]); - } + str.append(getClass().getSimpleName()).append(" ").append(getClazz().getSimpleName()).append(" components["); + values.appendFields(str); str.append("] data["); - for (int i = 0; i < dataOffsets.length; i++) { - str.append(i == 0 ? "" : ", ").append(dataOffsets[i]); - } + data.appendFields(str); str.append("]"); return str.toString(); } final CompositeValue forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, InstructionValueProcedureBase proc) { - return forEachComponent(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc); + return super.forEachComponent(inst, obj, values, mode, proc); } final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) { - forEach(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc, outerPosition); + forEach(inst, obj, values, mode, proc, outerPosition); } public String toString(CompositeValue obj) { StringBuilder result = new StringBuilder(); - appendValues(result, obj, "", "", "{", "}", new String[]{""}, componentOffsets); + appendValues(result, obj, "", "", "{", "}", new String[]{""}, values); - for (int i = 0; i < dataOffsets.length; i++) { - result.append(" ").append(fieldNames.get(dataOffsets[i])).append(": ").append(getFieldString(obj, dataOffsets[i])); + for (int i = 0; i < data.getCount(); i++) { + result.append(" ").append(data.getName(i)).append(": ").append(getFieldString(obj, i, data)); } return result.toString(); } Value getValue(CompositeValue obj, ValuePosition pos) { - return getValueForPosition(obj, componentOffsets, directComponentCount, pos); + return getValueForPosition(obj, values, pos); } CompositeValue createUpdatedValue(CompositeValue compValue, ValuePosition pos, Value value) { CompositeValue newCompValue = compValue.clone(); - setValueForPosition(newCompValue, componentOffsets, directComponentCount, pos, value); + setValueForPosition(newCompValue, values, pos, value); return newCompValue; } EnumSet getFlags(ValuePosition pos) { - return componentFlags[pos.getIndex()]; + return values.getFlags(pos.getIndex()); } void copyValueArrays(CompositeValue compositeValue) { - for (int i = directComponentCount; i < componentOffsets.length; i++) { - Value[] valueArray = getValueArray(compositeValue, componentOffsets[i]); + for (int i = values.getDirectCount(); i < values.getCount(); i++) { + Value[] valueArray = values.getValueArray(compositeValue, i); Value[] newValueArray = Arrays.copyOf(valueArray, valueArray.length); - setValueArray(compositeValue, componentOffsets[i], newValueArray); + values.setValueArray(compositeValue, i, newValueArray); } } } diff -r 5b00a1e62a5e -r aef31f60e970 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Fri Sep 26 18:59:08 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Sat Sep 27 18:16:18 2014 +0200 @@ -53,70 +53,50 @@ private static final Class INSTRUCTION_CLASS = LIRInstruction.class; private static final Class STATE_CLASS = LIRFrameState.class; - private final int directUseCount; - private final long[] useOffsets; - private final EnumSet[] useFlags; - private final int directAliveCount; - private final long[] aliveOffsets; - private final EnumSet[] aliveFlags; - private final int directTempCount; - private final long[] tempOffsets; - private final EnumSet[] tempFlags; - private final int directDefCount; - private final long[] defOffsets; - private final EnumSet[] defFlags; - - private final long[] stateOffsets; + private final Values uses; + private final Values alives; + private final Values temps; + private final Values defs; + private final Fields states; private String opcodeConstant; - private long opcodeOffset; + private int opcodeIndex; private LIRInstructionClass(Class clazz) { this(clazz, new DefaultCalcOffset()); } - @SuppressWarnings("unchecked") public LIRInstructionClass(Class clazz, CalcOffset calcOffset) { super(clazz); assert INSTRUCTION_CLASS.isAssignableFrom(clazz); - InstructionFieldScanner scanner = new InstructionFieldScanner(calcOffset); - scanner.scan(clazz); + InstructionFieldScanner ifs = new InstructionFieldScanner(calcOffset); + ifs.scan(clazz); - OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class); - directUseCount = mode.scalarOffsets.size(); - useOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets); - useFlags = arrayUsingSortedOffsets(mode.flags, useOffsets, new EnumSet[useOffsets.length]); - - mode = scanner.valueAnnotations.get(LIRInstruction.Alive.class); - directAliveCount = mode.scalarOffsets.size(); - aliveOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets); - aliveFlags = arrayUsingSortedOffsets(mode.flags, aliveOffsets, new EnumSet[aliveOffsets.length]); + uses = new Values(ifs.valueAnnotations.get(LIRInstruction.Use.class)); + alives = new Values(ifs.valueAnnotations.get(LIRInstruction.Alive.class)); + temps = new Values(ifs.valueAnnotations.get(LIRInstruction.Temp.class)); + defs = new Values(ifs.valueAnnotations.get(LIRInstruction.Def.class)); - mode = scanner.valueAnnotations.get(LIRInstruction.Temp.class); - directTempCount = mode.scalarOffsets.size(); - tempOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets); - tempFlags = arrayUsingSortedOffsets(mode.flags, tempOffsets, new EnumSet[tempOffsets.length]); + states = new Fields(ifs.states); + data = new Fields(ifs.data); - mode = scanner.valueAnnotations.get(LIRInstruction.Def.class); - directDefCount = mode.scalarOffsets.size(); - defOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets); - defFlags = arrayUsingSortedOffsets(mode.flags, defOffsets, new EnumSet[defOffsets.length]); - - stateOffsets = sortedLongCopy(scanner.stateOffsets); - dataOffsets = sortedLongCopy(scanner.dataOffsets); - - fieldNames = scanner.fieldNames; - fieldTypes = scanner.fieldTypes; - - opcodeConstant = scanner.opcodeConstant; - opcodeOffset = scanner.opcodeOffset; + opcodeConstant = ifs.opcodeConstant; + if (ifs.opcodeField == null) { + opcodeIndex = -1; + } else { + opcodeIndex = ifs.data.indexOf(ifs.opcodeField); + } } private static class InstructionFieldScanner extends FieldScanner { private String opcodeConstant; - private long opcodeOffset; + + /** + * Field (if any) annotated by {@link Opcode}. + */ + private FieldInfo opcodeField; public InstructionFieldScanner(CalcOffset calc) { super(calc); @@ -153,11 +133,11 @@ if (clazz.getAnnotation(Opcode.class) != null) { opcodeConstant = clazz.getAnnotation(Opcode.class).value(); } - opcodeOffset = -1; + opcodeField = null; super.scan(clazz); - if (opcodeConstant == null && opcodeOffset == -1) { + if (opcodeConstant == null && opcodeField == null) { opcodeConstant = clazz.getSimpleName(); if (opcodeConstant.endsWith("Op")) { opcodeConstant = opcodeConstant.substring(0, opcodeConstant.length() - 2); @@ -166,18 +146,20 @@ } @Override - protected void scanField(Field field, Class type, long offset) { + protected void scanField(Field field, long offset) { + Class type = field.getType(); if (STATE_CLASS.isAssignableFrom(type)) { assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field; assert field.getAnnotation(LIRInstruction.State.class) != null : "Field must have state annotation: " + field; - stateOffsets.add(offset); + states.add(new FieldInfo(offset, field.getName(), type)); } else { - super.scanField(field, type, offset); + super.scanField(field, offset); } if (field.getAnnotation(Opcode.class) != null) { - assert opcodeConstant == null && opcodeOffset == -1 : "Can have only one Opcode definition: " + field.getType(); - opcodeOffset = offset; + assert opcodeConstant == null && opcodeField == null : "Can have only one Opcode definition: " + type; + assert data.get(data.size() - 1).offset == offset; + opcodeField = data.get(data.size() - 1); } } } @@ -186,97 +168,33 @@ public String toString() { StringBuilder str = new StringBuilder(); str.append(getClass().getSimpleName()).append(" ").append(getClazz().getSimpleName()).append(" use["); - for (int i = 0; i < useOffsets.length; i++) { - str.append(i == 0 ? "" : ", ").append(useOffsets[i]); - } + uses.appendFields(str); str.append("] alive["); - for (int i = 0; i < aliveOffsets.length; i++) { - str.append(i == 0 ? "" : ", ").append(aliveOffsets[i]); - } + alives.appendFields(str); str.append("] temp["); - for (int i = 0; i < tempOffsets.length; i++) { - str.append(i == 0 ? "" : ", ").append(tempOffsets[i]); - } + temps.appendFields(str); str.append("] def["); - for (int i = 0; i < defOffsets.length; i++) { - str.append(i == 0 ? "" : ", ").append(defOffsets[i]); - } + defs.appendFields(str); str.append("] state["); - for (int i = 0; i < stateOffsets.length; i++) { - str.append(i == 0 ? "" : ", ").append(stateOffsets[i]); - } + states.appendFields(str); str.append("] data["); - for (int i = 0; i < dataOffsets.length; i++) { - str.append(i == 0 ? "" : ", ").append(dataOffsets[i]); - } + data.appendFields(str); str.append("]"); return str.toString(); } - Value getValue(LIRInstruction obj, ValuePosition pos) { - long[] offsets; - int directCount; - switch (pos.getMode()) { - case USE: - directCount = directUseCount; - offsets = useOffsets; - break; - case ALIVE: - directCount = directAliveCount; - offsets = aliveOffsets; - break; - case TEMP: - directCount = directTempCount; - offsets = tempOffsets; - break; - case DEF: - directCount = directDefCount; - offsets = defOffsets; - break; - default: - throw GraalInternalError.shouldNotReachHere("unkown OperandMode: " + pos.getMode()); - } - return getValueForPosition(obj, offsets, directCount, pos); - } - - void setValue(LIRInstruction obj, ValuePosition pos, Value value) { - long[] offsets; - int directCount; - switch (pos.getMode()) { + Values getValues(OperandMode mode) { + switch (mode) { case USE: - directCount = directUseCount; - offsets = useOffsets; - break; + return uses; case ALIVE: - directCount = directAliveCount; - offsets = aliveOffsets; - break; + return alives; case TEMP: - directCount = directTempCount; - offsets = tempOffsets; - break; + return temps; case DEF: - directCount = directDefCount; - offsets = defOffsets; - break; + return defs; default: - throw GraalInternalError.shouldNotReachHere("unkown OperandMode: " + pos.getMode()); - } - setValueForPosition(obj, offsets, directCount, pos, value); - } - - EnumSet getFlags(ValuePosition pos) { - switch (pos.getMode()) { - case USE: - return useFlags[pos.getIndex()]; - case ALIVE: - return aliveFlags[pos.getIndex()]; - case TEMP: - return tempFlags[pos.getIndex()]; - case DEF: - return defFlags[pos.getIndex()]; - default: - throw GraalInternalError.shouldNotReachHere("unkown OperandMode: " + pos.getMode()); + throw GraalInternalError.shouldNotReachHere("unknown OperandMode: " + mode); } } @@ -284,17 +202,17 @@ if (opcodeConstant != null) { return opcodeConstant; } - assert opcodeOffset != -1; - return unsafe.getObject(obj, opcodeOffset).toString(); + assert opcodeIndex != -1; + return data.getObject(obj, opcodeIndex).toString(); } final boolean hasOperands() { - return useOffsets.length > 0 || aliveOffsets.length > 0 || tempOffsets.length > 0 || defOffsets.length > 0; + return uses.getCount() > 0 || alives.getCount() > 0 || temps.getCount() > 0 || defs.getCount() > 0; } final boolean hasState(LIRInstruction obj) { - for (int i = 0; i < stateOffsets.length; i++) { - if (getState(obj, stateOffsets[i]) != null) { + for (int i = 0; i < states.getCount(); i++) { + if (states.getObject(obj, i) != null) { return true; } } @@ -302,40 +220,40 @@ } final void forEachUse(LIRInstruction obj, ValuePositionProcedure proc) { - forEach(obj, obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc, ValuePosition.ROOT_VALUE_POSITION); + forEach(obj, obj, uses, OperandMode.USE, proc, ValuePosition.ROOT_VALUE_POSITION); } final void forEachAlive(LIRInstruction obj, ValuePositionProcedure proc) { - forEach(obj, obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc, ValuePosition.ROOT_VALUE_POSITION); + forEach(obj, obj, alives, OperandMode.ALIVE, proc, ValuePosition.ROOT_VALUE_POSITION); } final void forEachTemp(LIRInstruction obj, ValuePositionProcedure proc) { - forEach(obj, obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc, ValuePosition.ROOT_VALUE_POSITION); + forEach(obj, obj, temps, OperandMode.TEMP, proc, ValuePosition.ROOT_VALUE_POSITION); } final void forEachDef(LIRInstruction obj, ValuePositionProcedure proc) { - forEach(obj, obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc, ValuePosition.ROOT_VALUE_POSITION); + forEach(obj, obj, defs, OperandMode.DEF, proc, ValuePosition.ROOT_VALUE_POSITION); } final void forEachUse(LIRInstruction obj, InstructionValueProcedureBase proc) { - forEach(obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc); + forEach(obj, uses, OperandMode.USE, proc); } final void forEachAlive(LIRInstruction obj, InstructionValueProcedureBase proc) { - forEach(obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc); + forEach(obj, alives, OperandMode.ALIVE, proc); } final void forEachTemp(LIRInstruction obj, InstructionValueProcedureBase proc) { - forEach(obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc); + forEach(obj, temps, OperandMode.TEMP, proc); } final void forEachDef(LIRInstruction obj, InstructionValueProcedureBase proc) { - forEach(obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc); + forEach(obj, defs, OperandMode.DEF, proc); } final void forEachState(LIRInstruction obj, InstructionValueProcedureBase proc) { - for (int i = 0; i < stateOffsets.length; i++) { - LIRFrameState state = getState(obj, stateOffsets[i]); + for (int i = 0; i < states.getCount(); i++) { + LIRFrameState state = (LIRFrameState) states.getObject(obj, i); if (state != null) { state.forEachState(obj, proc); } @@ -343,8 +261,8 @@ } final void forEachState(LIRInstruction obj, InstructionStateProcedure proc) { - for (int i = 0; i < stateOffsets.length; i++) { - LIRFrameState state = getState(obj, stateOffsets[i]); + for (int i = 0; i < states.getCount(); i++) { + LIRFrameState state = (LIRFrameState) states.getObject(obj, i); if (state != null) { proc.doState(obj, state); } @@ -352,27 +270,24 @@ } final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, InstructionValueProcedure proc) { - int hintDirectCount = 0; - long[] hintOffsets = null; + Values hints; if (mode == OperandMode.USE) { - hintDirectCount = directDefCount; - hintOffsets = defOffsets; + hints = defs; } else if (mode == OperandMode.DEF) { - hintDirectCount = directUseCount; - hintOffsets = useOffsets; + hints = uses; } else { return null; } - for (int i = 0; i < hintOffsets.length; i++) { - if (i < hintDirectCount) { - Value hintValue = getValue(obj, hintOffsets[i]); + for (int i = 0; i < hints.getCount(); i++) { + if (i < hints.getDirectCount()) { + Value hintValue = hints.getValue(obj, i); Value result = proc.processValue(obj, hintValue, null, null); if (result != null) { return result; } } else { - Value[] hintValues = getValueArray(obj, hintOffsets[i]); + Value[] hintValues = hints.getValueArray(obj, i); for (int j = 0; j < hintValues.length; j++) { Value hintValue = hintValues[j]; Value result = proc.processValue(obj, hintValue, null, null); @@ -385,29 +300,25 @@ return null; } - private static LIRFrameState getState(LIRInstruction obj, long offset) { - return (LIRFrameState) unsafe.getObject(obj, offset); - } - String toString(LIRInstruction obj) { StringBuilder result = new StringBuilder(); - appendValues(result, obj, "", " = ", "(", ")", new String[]{""}, defOffsets); - result.append(getOpcode(obj).toUpperCase()); - appendValues(result, obj, " ", "", "(", ")", new String[]{"", "~"}, useOffsets, aliveOffsets); - appendValues(result, obj, " ", "", "{", "}", new String[]{""}, tempOffsets); + appendValues(result, obj, "", " = ", "(", ")", new String[]{""}, defs); + result.append(String.valueOf(getOpcode(obj)).toUpperCase()); + appendValues(result, obj, " ", "", "(", ")", new String[]{"", "~"}, uses, alives); + appendValues(result, obj, " ", "", "{", "}", new String[]{""}, temps); - for (int i = 0; i < dataOffsets.length; i++) { - if (dataOffsets[i] == opcodeOffset) { + for (int i = 0; i < data.getCount(); i++) { + if (i == opcodeIndex) { continue; } - result.append(" ").append(fieldNames.get(dataOffsets[i])).append(": ").append(getFieldString(obj, dataOffsets[i])); + result.append(" ").append(data.getName(i)).append(": ").append(getFieldString(obj, i, data)); } - for (int i = 0; i < stateOffsets.length; i++) { - LIRFrameState state = getState(obj, stateOffsets[i]); + for (int i = 0; i < states.getCount(); i++) { + LIRFrameState state = (LIRFrameState) states.getObject(obj, i); if (state != null) { - result.append(" ").append(fieldNames.get(stateOffsets[i])).append(" [bci:"); + result.append(" ").append(states.getName(i)).append(" [bci:"); String sep = ""; for (BytecodeFrame cur = state.topFrame; cur != null; cur = cur.caller()) { result.append(sep).append(cur.getBCI()); diff -r 5b00a1e62a5e -r aef31f60e970 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Fri Sep 26 18:59:08 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Sat Sep 27 18:16:18 2014 +0200 @@ -48,21 +48,117 @@ super(clazz); } + protected static class Values extends Fields { + private final int directCount; + private final OperandMode mode; + private final EnumSet[] flags; + + public Values(OperandModeAnnotation mode) { + this(mode.directCount, null, mode.values); + } + + @SuppressWarnings("unchecked") + public Values(int directCount, OperandMode mode, ArrayList fields) { + super(fields); + this.mode = mode; + this.directCount = directCount; + flags = new EnumSet[fields.size()]; + for (int i = 0; i < fields.size(); i++) { + flags[i] = fields.get(i).flags; + } + } + + public int getDirectCount() { + return directCount; + } + + public OperandMode getMode() { + return mode; + } + + public EnumSet getFlags(int i) { + return flags[i]; + } + + protected Value getValue(Object obj, int index) { + return (Value) getObject(obj, index); + } + + protected void setValue(Object obj, int index, Value value) { + putObject(obj, index, value); + } + + protected Value[] getValueArray(Object obj, int index) { + return (Value[]) getObject(obj, index); + } + + protected void setValueArray(Object obj, int index, Value[] valueArray) { + putObject(obj, index, valueArray); + } + + @Override + public String toString() { + if (mode != null) { + return super.toString() + ":" + mode; + } + return super.toString(); + } + } + + /** + * The component values in an {@link LIRInstruction} or {@link CompositeValue}. + */ + protected Values values; + + protected static class ValueFieldInfo extends FieldInfo { + + final EnumSet flags; + + public ValueFieldInfo(long offset, String name, Class type, EnumSet flags) { + super(offset, name, type); + assert VALUE_ARRAY_CLASS.isAssignableFrom(type) || VALUE_CLASS.isAssignableFrom(type); + this.flags = flags; + } + + /** + * Sorts non-array fields before array fields. + */ + @Override + public int compareTo(FieldInfo o) { + if (VALUE_ARRAY_CLASS.isAssignableFrom(o.type)) { + if (!VALUE_ARRAY_CLASS.isAssignableFrom(type)) { + return -1; + } + } else { + if (VALUE_ARRAY_CLASS.isAssignableFrom(type)) { + return 1; + } + } + return super.compareTo(o); + } + + @Override + public String toString() { + return super.toString() + flags; + } + } + protected static class OperandModeAnnotation { - public final ArrayList scalarOffsets = new ArrayList<>(); - public final ArrayList arrayOffsets = new ArrayList<>(); - public final Map> flags = new HashMap<>(); + /** + * Number of non-array fields in {@link #values}. + */ + public int directCount; + public final ArrayList values = new ArrayList<>(); } protected abstract static class FieldScanner extends BaseFieldScanner { public final Map, OperandModeAnnotation> valueAnnotations; - public final ArrayList stateOffsets = new ArrayList<>(); + public final ArrayList states = new ArrayList<>(); public FieldScanner(CalcOffset calc) { super(calc); - valueAnnotations = new HashMap<>(); } @@ -81,26 +177,26 @@ protected abstract EnumSet getFlags(Field field); @Override - protected void scanField(Field field, Class type, long offset) { + protected void scanField(Field field, long offset) { + Class type = field.getType(); if (VALUE_CLASS.isAssignableFrom(type) && type != CONSTANT_CLASS) { assert !Modifier.isFinal(field.getModifiers()) : "Value field must not be declared final because it is modified by register allocator: " + field; OperandModeAnnotation annotation = getOperandModeAnnotation(field); assert annotation != null : "Field must have operand mode annotation: " + field; - annotation.scalarOffsets.add(offset); EnumSet flags = getFlags(field); assert verifyFlags(field, type, flags); - annotation.flags.put(offset, getFlags(field)); + annotation.values.add(new ValueFieldInfo(offset, field.getName(), type, flags)); + annotation.directCount++; } else if (VALUE_ARRAY_CLASS.isAssignableFrom(type)) { OperandModeAnnotation annotation = getOperandModeAnnotation(field); assert annotation != null : "Field must have operand mode annotation: " + field; - annotation.arrayOffsets.add(offset); EnumSet flags = getFlags(field); assert verifyFlags(field, type.getComponentType(), flags); - annotation.flags.put(offset, getFlags(field)); + annotation.values.add(new ValueFieldInfo(offset, field.getName(), type, flags)); } else { assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field; assert field.getAnnotation(LIRInstruction.State.class) == null : "Field must not have state annotation: " + field; - dataOffsets.add(offset); + data.add(new FieldInfo(offset, field.getName(), type)); } } @@ -118,74 +214,73 @@ } } - protected static void forEach(LIRInstruction inst, int directCount, long[] offsets, OperandMode mode, EnumSet[] flags, InstructionValueProcedureBase proc) { - for (int i = 0; i < offsets.length; i++) { - assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]); + protected static void forEach(LIRInstruction inst, Values values, OperandMode mode, InstructionValueProcedureBase proc) { + for (int i = 0; i < values.getCount(); i++) { + assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(values.getFlags(i)); - if (i < directCount) { - Value value = getValue(inst, offsets[i]); + if (i < values.getDirectCount()) { + Value value = values.getValue(inst, i); Value newValue; if (value instanceof CompositeValue) { CompositeValue composite = (CompositeValue) value; newValue = composite.forEachComponent(inst, mode, proc); } else { - newValue = proc.processValue(inst, value, mode, flags[i]); + newValue = proc.processValue(inst, value, mode, values.getFlags(i)); } if (!value.identityEquals(newValue)) { - setValue(inst, offsets[i], newValue); + values.setValue(inst, i, newValue); } } else { - Value[] values = getValueArray(inst, offsets[i]); - for (int j = 0; j < values.length; j++) { - Value value = values[j]; + Value[] valueArray = values.getValueArray(inst, i); + for (int j = 0; j < valueArray.length; j++) { + Value value = valueArray[j]; Value newValue; if (value instanceof CompositeValue) { CompositeValue composite = (CompositeValue) value; newValue = composite.forEachComponent(inst, mode, proc); } else { - newValue = proc.processValue(inst, value, mode, flags[i]); + newValue = proc.processValue(inst, value, mode, values.getFlags(i)); } if (!value.identityEquals(newValue)) { - values[j] = newValue; + valueArray[j] = newValue; } } } } } - protected static CompositeValue forEachComponent(LIRInstruction inst, CompositeValue obj, int directCount, long[] offsets, OperandMode mode, EnumSet[] flags, - InstructionValueProcedureBase proc) { + protected static CompositeValue forEachComponent(LIRInstruction inst, CompositeValue obj, Values values, OperandMode mode, InstructionValueProcedureBase proc) { CompositeValue newCompValue = null; - for (int i = 0; i < offsets.length; i++) { - assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]); + for (int i = 0; i < values.getCount(); i++) { + assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(values.getFlags(i)); - if (i < directCount) { - Value value = getValue(obj, offsets[i]); + if (i < values.getDirectCount()) { + Value value = values.getValue(obj, i); Value newValue; if (value instanceof CompositeValue) { CompositeValue composite = (CompositeValue) value; newValue = composite.forEachComponent(inst, mode, proc); } else { - newValue = proc.processValue(inst, value, mode, flags[i]); + newValue = proc.processValue(inst, value, mode, values.getFlags(i)); } if (!value.identityEquals(newValue)) { // lazy initialize if (newCompValue == null) { newCompValue = obj.clone(); } - setValue(newCompValue, offsets[i], newValue); + values.setValue(newCompValue, i, newValue); } } else { - Value[] values = getValueArray(obj, offsets[i]); + Value[] valueArray = values.getValueArray(obj, i); Value[] newValues = null; - for (int j = 0; j < values.length; j++) { - Value value = values[j]; + for (int j = 0; j < valueArray.length; j++) { + Value value = valueArray[j]; Value newValue; if (value instanceof CompositeValue) { CompositeValue composite = (CompositeValue) value; newValue = composite.forEachComponent(inst, mode, proc); } else { - newValue = proc.processValue(inst, value, mode, flags[i]); + newValue = proc.processValue(inst, value, mode, values.getFlags(i)); } if (!value.identityEquals(newValue)) { // lazy initialize @@ -193,7 +288,7 @@ if (newCompValue == null) { newCompValue = obj.clone(); } - newValues = getValueArray(newCompValue, offsets[i]); + newValues = values.getValueArray(newCompValue, i); } newValues[j] = newValue; } @@ -203,18 +298,17 @@ return newCompValue != null ? newCompValue : obj; } - protected static void forEach(LIRInstruction inst, Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet[] flags, ValuePositionProcedure proc, - ValuePosition outerPosition) { - for (int i = 0; i < offsets.length; i++) { - assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]); + protected static void forEach(LIRInstruction inst, Object obj, Values values, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition) { + for (int i = 0; i < values.getCount(); i++) { + assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(values.getFlags(i)); - if (i < directCount) { - Value value = getValue(obj, offsets[i]); + if (i < values.getDirectCount()) { + Value value = values.getValue(obj, i); doForValue(inst, mode, proc, outerPosition, i, ValuePosition.NO_SUBINDEX, value); } else { - Value[] values = getValueArray(obj, offsets[i]); - for (int j = 0; j < values.length; j++) { - Value value = values[j]; + Value[] valueArray = values.getValueArray(obj, i); + for (int j = 0; j < valueArray.length; j++) { + Value value = valueArray[j]; doForValue(inst, mode, proc, outerPosition, i, j, value); } } @@ -222,7 +316,8 @@ } private static void doForValue(LIRInstruction inst, OperandMode mode, ValuePositionProcedure proc, ValuePosition outerPosition, int index, int subIndex, Value value) { - ValuePosition position = new ValuePosition(mode, index, subIndex, outerPosition); + Values values = inst.getLIRInstructionClass().getValues(mode); + ValuePosition position = new ValuePosition(values, index, subIndex, outerPosition); if (value instanceof CompositeValue) { CompositeValue composite = (CompositeValue) value; composite.forEachComponent(inst, mode, proc, position); @@ -231,41 +326,25 @@ } } - protected static Value getValueForPosition(Object obj, long[] offsets, int directCount, ValuePosition pos) { - if (pos.getIndex() < directCount) { - return getValue(obj, offsets[pos.getIndex()]); + protected static Value getValueForPosition(Object obj, Values values, ValuePosition pos) { + if (pos.getIndex() < values.getDirectCount()) { + return values.getValue(obj, pos.getIndex()); } - return getValueArray(obj, offsets[pos.getIndex()])[pos.getSubIndex()]; + return values.getValueArray(obj, pos.getIndex())[pos.getSubIndex()]; } - protected static void setValueForPosition(Object obj, long[] offsets, int directCount, ValuePosition pos, Value value) { - if (pos.getIndex() < directCount) { - setValue(obj, offsets[pos.getIndex()], value); + protected static void setValueForPosition(Object obj, Values values, ValuePosition pos, Value value) { + if (pos.getIndex() < values.getDirectCount()) { + values.setValue(obj, pos.getIndex(), value); } else { - getValueArray(obj, offsets[pos.getIndex()])[pos.getSubIndex()] = value; + values.getValueArray(obj, pos.getIndex())[pos.getSubIndex()] = value; } } - protected static Value getValue(Object obj, long offset) { - return (Value) unsafe.getObject(obj, offset); - } - - protected static void setValue(Object obj, long offset, Value value) { - unsafe.putObject(obj, offset, value); - } - - protected static Value[] getValueArray(Object obj, long offset) { - return (Value[]) unsafe.getObject(obj, offset); - } - - protected static void setValueArray(Object obj, long offset, Value[] valueArray) { - unsafe.putObject(obj, offset, valueArray); - } - - protected void appendValues(StringBuilder result, Object obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, long[]... moffsets) { + protected void appendValues(StringBuilder result, Object obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, Fields... fieldsList) { int total = 0; - for (long[] offsets : moffsets) { - total += offsets.length; + for (Fields fields : fieldsList) { + total += fields.getCount(); } if (total == 0) { return; @@ -276,16 +355,15 @@ result.append(startMultiple); } String sep = ""; - for (int i = 0; i < moffsets.length; i++) { - long[] offsets = moffsets[i]; + int i = 0; + for (Fields fields : fieldsList) { - for (int j = 0; j < offsets.length; j++) { - result.append(sep).append(prefix[i]); - long offset = offsets[j]; + for (int j = 0; j < fields.getCount(); j++) { + result.append(sep).append(prefix[i++]); if (total > 1) { - result.append(fieldNames.get(offset)).append(": "); + result.append(fields.getName(j)).append(": "); } - result.append(getFieldString(obj, offset)); + result.append(getFieldString(obj, j, fields)); sep = ", "; } } @@ -295,38 +373,25 @@ result.append(end); } - protected String getFieldString(Object obj, long offset) { - Class type = fieldTypes.get(offset); - if (type == int.class) { - return String.valueOf(unsafe.getInt(obj, offset)); - } else if (type == long.class) { - return String.valueOf(unsafe.getLong(obj, offset)); - } else if (type == boolean.class) { - return String.valueOf(unsafe.getBoolean(obj, offset)); - } else if (type == float.class) { - return String.valueOf(unsafe.getFloat(obj, offset)); - } else if (type == double.class) { - return String.valueOf(unsafe.getDouble(obj, offset)); - } else if (type == byte.class) { - return String.valueOf(unsafe.getByte(obj, offset)); - } else if (!type.isPrimitive()) { - Object value = unsafe.getObject(obj, offset); - if (!type.isArray()) { - return String.valueOf(value); - } else if (type == int[].class) { - return Arrays.toString((int[]) value); - } else if (type == double[].class) { - return Arrays.toString((double[]) value); - } else if (type == byte[].class) { - byte[] byteValue = (byte[]) value; - if (isPrintableAsciiString(byteValue)) { - return toString(byteValue); - } else { - return Arrays.toString(byteValue); - } - } else if (!type.getComponentType().isPrimitive()) { - return Arrays.toString((Object[]) value); + protected String getFieldString(Object obj, int index, Fields fields) { + Object value = fields.get(obj, index); + Class type = fields.getType(index); + if (value == null || type.isPrimitive() || !type.isArray()) { + return String.valueOf(value); + } + if (type == int[].class) { + return Arrays.toString((int[]) value); + } else if (type == double[].class) { + return Arrays.toString((double[]) value); + } else if (type == byte[].class) { + byte[] byteValue = (byte[]) value; + if (isPrintableAsciiString(byteValue)) { + return toString(byteValue); + } else { + return Arrays.toString(byteValue); } + } else if (!type.getComponentType().isPrimitive()) { + return Arrays.toString((Object[]) value); } assert false : "unhandled field type: " + type; return ""; diff -r 5b00a1e62a5e -r aef31f60e970 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePosition.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePosition.java Fri Sep 26 18:59:08 2014 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ValuePosition.java Sat Sep 27 18:16:18 2014 +0200 @@ -25,14 +25,15 @@ import java.util.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.LIRInstruction.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRIntrospection.Values; /** * Describes an operand slot for a {@link LIRInstructionClass}. */ public final class ValuePosition { - private final OperandMode mode; + private final Values values; private final int index; private final int subIndex; private final ValuePosition outerPosition; @@ -40,8 +41,8 @@ public static final int NO_SUBINDEX = -1; public static final ValuePosition ROOT_VALUE_POSITION = null; - public ValuePosition(OperandMode mode, int index, int subIndex, ValuePosition outerPosition) { - this.mode = mode; + public ValuePosition(Values values, int index, int subIndex, ValuePosition outerPosition) { + this.values = values; this.index = index; this.subIndex = subIndex; this.outerPosition = outerPosition; @@ -51,20 +52,12 @@ return outerPosition != ROOT_VALUE_POSITION; } - public Value get(LIRInstruction inst) { + public Value get(Object inst) { if (isCompositePosition()) { CompositeValue compValue = (CompositeValue) outerPosition.get(inst); return compValue.getValueClass().getValue(compValue, this); } - return inst.getLIRInstructionClass().getValue(inst, this); - } - - public EnumSet getFlags(LIRInstruction inst) { - if (isCompositePosition()) { - CompositeValue compValue = (CompositeValue) outerPosition.get(inst); - return compValue.getValueClass().getFlags(this); - } - return inst.getLIRInstructionClass().getFlags(this); + return getValue(inst); } public void set(LIRInstruction inst, Value value) { @@ -73,7 +66,7 @@ CompositeValue newCompValue = compValue.getValueClass().createUpdatedValue(compValue, this, value); outerPosition.set(inst, newCompValue); } else { - inst.getLIRInstructionClass().setValue(inst, this, value); + setValue(inst, value); } } @@ -85,8 +78,23 @@ return index; } - public OperandMode getMode() { - return mode; + public EnumSet getFlags() { + return values.getFlags(index); + } + + public Value getValue(Object obj) { + if (index < values.getDirectCount()) { + return values.getValue(obj, index); + } + return values.getValueArray(obj, index)[subIndex]; + } + + public void setValue(Object obj, Value value) { + if (index < values.getDirectCount()) { + values.setValue(obj, index, value); + } else { + values.getValueArray(obj, index)[subIndex] = value; + } } public ValuePosition getSuperPosition() { @@ -96,9 +104,9 @@ @Override public String toString() { if (outerPosition == ROOT_VALUE_POSITION) { - return mode.toString() + "(" + index + (subIndex < 0 ? "" : "/" + subIndex) + ")"; + return values.getMode() + "(" + index + (subIndex < 0 ? "" : "/" + subIndex) + ")"; } - return outerPosition.toString() + "[" + mode.toString() + "(" + index + (subIndex < 0 ? "" : "/" + subIndex) + ")]"; + return outerPosition.toString() + "[" + values.getMode() + "(" + index + (subIndex < 0 ? "" : "/" + subIndex) + ")]"; } @Override @@ -106,7 +114,7 @@ final int prime = 31; int result = 1; result = prime * result + index; - result = prime * result + ((mode == null) ? 0 : mode.hashCode()); + result = prime * result + ((values.getMode() == null) ? 0 : values.getMode().hashCode()); result = prime * result + subIndex; result = prime * result + ((outerPosition == null) ? 0 : outerPosition.hashCode()); return result; @@ -127,7 +135,7 @@ if (index != other.index) { return false; } - if (mode != other.mode) { + if (values.getMode() != other.values.getMode()) { return false; } if (subIndex != other.subIndex) {