Mercurial > hg > truffle
changeset 17226:a552dd335bde
generalized support for unsafe access to a subset of the fields of an object
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Fri, 26 Sep 2014 00:18:15 +0200 |
parents | f4b939d433a4 |
children | 5d03b4a472c6 |
files | 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/Node.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeferredPiNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/EdgesSubstitutions.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/FieldsSubstitutions.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java |
diffstat | 8 files changed, 446 insertions(+), 289 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/Fields.java Fri Sep 26 00:18:15 2014 +0200 @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common; + +import static com.oracle.graal.compiler.common.UnsafeAccess.*; + +import java.util.*; + +import sun.misc.*; + +/** + * Describes fields in a class, primarily for access via {@link Unsafe}. + */ +public class Fields { + + protected final Class<?> clazz; + private final long[] offsets; + private final String[] names; + private final Class<?>[] types; + + public Fields(Class<?> clazz, long[] offsets, Map<Long, String> names, Map<Long, Class<?>> types) { + this.clazz = clazz; + this.offsets = offsets; + + 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]); + } + } + + /** + * Gets the number of fields represented by this object. + */ + public int getCount() { + return offsets.length; + } + + /** + * Gets the value of a field for a given object. + * + * @param object the object whose field is to be read + * @param index the index of the field (between 0 and {@link #getCount()}) + * @return the value of the specified field which will be boxed if the field type is primitive + */ + public Object get(Object object, int index) { + long offset = offsets[index]; + Class<?> type = types[index]; + Object value = null; + if (type.isPrimitive()) { + if (type == Integer.TYPE) { + value = unsafe.getInt(object, offset); + } else if (type == Long.TYPE) { + value = unsafe.getLong(object, offset); + } else if (type == Boolean.TYPE) { + value = unsafe.getBoolean(object, offset); + } else if (type == Float.TYPE) { + value = unsafe.getFloat(object, offset); + } else if (type == Double.TYPE) { + value = unsafe.getDouble(object, offset); + } else if (type == Short.TYPE) { + value = unsafe.getShort(object, offset); + } else if (type == Character.TYPE) { + value = unsafe.getChar(object, offset); + } else if (type == Byte.TYPE) { + value = unsafe.getByte(object, offset); + } else { + assert false : "unhandled property type: " + type; + } + } else { + value = unsafe.getObject(object, offset); + } + return value; + } + + /** + * Determines if a field in the domain of this object is the same as the field denoted by the + * same index in another {@link Fields} object. + */ + public boolean isSame(Fields other, int index) { + return other.offsets[index] == offsets[index]; + } + + /** + * Gets the name of a field. + * + * @param index index of a field + */ + public String getName(int index) { + return names[index]; + } + + /** + * Gets the type of a field. + * + * @param index index of a field + */ + public Class<?> getType(int index) { + return types[index]; + } + + private boolean checkAssignable(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()); + return true; + } + + public void set(Object object, int index, Object value) { + long dataOffset = offsets[index]; + Class<?> type = types[index]; + if (type.isPrimitive()) { + if (type == Integer.TYPE) { + unsafe.putInt(object, dataOffset, (Integer) value); + } else if (type == Long.TYPE) { + unsafe.putLong(object, dataOffset, (Long) value); + } else if (type == Boolean.TYPE) { + unsafe.putBoolean(object, dataOffset, (Boolean) value); + } else if (type == Float.TYPE) { + unsafe.putFloat(object, dataOffset, (Float) value); + } else if (type == Double.TYPE) { + unsafe.putDouble(object, dataOffset, (Double) value); + } else if (type == Short.TYPE) { + unsafe.putShort(object, dataOffset, (Short) value); + } else if (type == Character.TYPE) { + unsafe.putChar(object, dataOffset, (Character) value); + } else if (type == Byte.TYPE) { + unsafe.putByte(object, dataOffset, (Byte) value); + } else { + assert false : "unhandled property type: " + type; + } + } else { + assert checkAssignable(index, value); + unsafe.putObject(object, dataOffset, value); + } + } + + @Override + public String toString() { + return clazz.getSimpleName(); + } + + public void appendFields(StringBuilder sb) { + for (int i = 0; i < offsets.length; i++) { + sb.append(i == 0 ? "" : ", ").append(getName(i)).append('@').append(offsets[i]); + } + } + + public boolean getBoolean(Object n, int i) { + assert types[i] == boolean.class; + return unsafe.getBoolean(n, offsets[i]); + } + + public byte getByte(Object n, int i) { + assert types[i] == byte.class; + return unsafe.getByte(n, offsets[i]); + } + + public short getShort(Object n, int i) { + assert types[i] == short.class; + return unsafe.getShort(n, offsets[i]); + } + + public char getChar(Object n, int i) { + assert types[i] == char.class; + return unsafe.getChar(n, offsets[i]); + } + + public int getInt(Object n, int i) { + assert types[i] == int.class; + return unsafe.getInt(n, offsets[i]); + } + + public long getLong(Object n, int i) { + assert types[i] == long.class; + return unsafe.getLong(n, offsets[i]); + } + + public float getFloat(Object n, int i) { + assert types[i] == float.class; + return unsafe.getFloat(n, offsets[i]); + } + + public double getDouble(Object n, int i) { + assert types[i] == double.class; + return unsafe.getDouble(n, offsets[i]); + } + + /** + * Gets the value of an object field. + * + * @param object the object whose field is to be read + * @param index the index of the field (between 0 and {@link #getCount()}) + * @param asType the type to which the returned object is cast + * @return the value of the specified field cast to {@code c} + */ + public <T> T getObject(Object object, int index, Class<T> asType) { + return getObject(object, offsets[index], asType); + } + + private static <T> T getObject(Object object, long offset, Class<T> asType) { + return asType.cast(unsafe.getObject(object, offset)); + } + + /** + * Sets the value of an object field. + * + * @param object the object whose field is to be written + * @param index the index of the field (between 0 and {@link #getCount()}) + * @param value the value to be written to the field + */ + protected void putObject(Object object, int index, Object value) { + assert checkAssignable(index, value); + putObject(object, offsets[index], value); + } + + private static void putObject(Object object, long offset, Object value) { + unsafe.putObject(object, offset, value); + } + +}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java Thu Sep 25 12:02:50 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java Fri Sep 26 00:18:15 2014 +0200 @@ -22,17 +22,18 @@ */ package com.oracle.graal.graph; -import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.graph.Graph.*; import static com.oracle.graal.graph.Node.*; import java.util.*; +import com.oracle.graal.compiler.common.*; + /** * Describes {@link Node} fields representing the set of inputs for the node or the set of the * node's successors. */ -public abstract class Edges { +public abstract class Edges extends Fields { /** * Constants denoting whether a set of edges are inputs or successors. @@ -42,33 +43,13 @@ Successors; } - private final Class<? extends Node> nodeClass; private final int directCount; - private final long[] offsets; - private final String[] names; - private final Class<?>[] types; private final Type type; - @SuppressWarnings("unchecked") public Edges(Class<?> nodeClass, Type type, int directCount, long[] offsets, Map<Long, String> names, Map<Long, Class<?>> types) { - this.nodeClass = (Class<? extends Node>) nodeClass; + super(nodeClass, offsets, names, types); this.type = type; this.directCount = directCount; - this.offsets = offsets; - - 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]); - } - } - - /** - * Gets the number of edges represented by this object. - */ - public int getCount() { - return offsets.length; } /** @@ -79,23 +60,6 @@ return directCount; } - private static Node getNode(Node node, long offset) { - return (Node) unsafe.getObject(node, offset); - } - - @SuppressWarnings("unchecked") - private static NodeList<Node> getNodeList(Node node, long offset) { - return (NodeList<Node>) unsafe.getObject(node, offset); - } - - private static void putNode(Node node, long offset, Node value) { - unsafe.putObject(node, offset, value); - } - - private static void putNodeList(Node node, long offset, NodeList<?> value) { - unsafe.putObject(node, offset, value); - } - /** * Gets the {@link Node} at the end point of a {@linkplain #getDirectCount() direct} edge. * @@ -105,7 +69,7 @@ */ public Node getNode(Node node, int index) { assert index >= 0 && index < directCount; - return getNode(node, offsets[index]); + return getObject(node, index, Node.class); } /** @@ -116,9 +80,10 @@ * {@link #getDirectCount()}) * @return the {@link NodeList} at the other edge of the requested edge */ + @SuppressWarnings("unchecked") public NodeList<Node> getNodeList(Node node, int index) { - assert index >= directCount && index < offsets.length; - return getNodeList(node, offsets[index]); + assert index >= directCount && index < getCount(); + return getObject(node, index, NodeList.class); } /** @@ -152,7 +117,7 @@ * @param toNode the node to which the edges should be copied. */ public void copy(Node fromNode, Node toNode) { - assert fromNode.getNodeClass().getClazz() == nodeClass && toNode.getNodeClass().getClazz() == nodeClass; + assert fromNode.getNodeClass().getClazz() == clazz && toNode.getNodeClass().getClazz() == clazz; int index = 0; while (index < getDirectCount()) { initializeNode(toNode, index, getNode(fromNode, index)); @@ -187,7 +152,7 @@ } while (index < getCount()) { NodeList<Node> list = getNodeList(node, index); - assert list != null : nodeClass; + assert list != null : clazz; if (list.replaceFirst(key, replacement)) { return true; } @@ -196,50 +161,40 @@ return false; } - public boolean isSameEdge(Edges other, int index) { - return offsets[index] == other.offsets[index]; - } - - /** - * Gets the name of an edge. - * - * @param index index of an edge - */ - public String getName(int index) { - return names[index]; + @Override + public void set(Object node, int index, Object value) { + throw new IllegalArgumentException("Cannot call set on " + this); } /** - * Gets the type of the field storing the end point of an edge. + * Sets the value of a given edge without notifying the new and old nodes on the other end of + * the edge of the change. * - * @param index index of an edge + * @param node the node whose edge is to be updated + * @param index the index of the edge (between 0 and {@link #getCount()}) + * @param value the node to be written to the edge */ - public Class<?> getType(int index) { - return types[index]; - } - - private boolean checkAssignable(int index, Node value) { - assert value == null || getType(index).isAssignableFrom(value.getClass()) : String.format("%s.%s of type %s is not assignable from %s", nodeClass.getSimpleName(), getName(index), - getType(index).getSimpleName(), value.getClass().getSimpleName()); - return true; - } - public void initializeNode(Node node, int index, Node value) { - assert checkAssignable(index, value); - putNode(node, offsets[index], value); + putObject(node, index, value); } public void initializeList(Node node, int index, NodeList<Node> value) { assert index >= directCount; - putNodeList(node, offsets[index], value); + putObject(node, index, value); } + /** + * Sets the value of a given edge and notifies the new and old nodes on the other end of the + * edge of the change. + * + * @param node the node whose edge is to be updated + * @param index the index of the edge (between 0 and {@link #getCount()}) + * @param value the node to be written to the edge + */ public void setNode(Node node, int index, Node value) { assert index < directCount; - long offset = offsets[index]; - Node old = getNode(node, offset); - assert checkAssignable(index, value); - putNode(node, offset, value); + Node old = getObject(node, index, Node.class); + putObject(node, index, value); update(node, old, value); } @@ -263,7 +218,7 @@ * Determines if the edges of two given nodes are the same. */ public boolean areEqualIn(Node node, Node other) { - assert node.getNodeClass().getClazz() == nodeClass && other.getNodeClass().getClazz() == nodeClass; + assert node.getNodeClass().getClazz() == clazz && other.getNodeClass().getClazz() == clazz; int index = 0; while (index < directCount) { if (getNode(other, index) != getNode(node, index)) { @@ -476,12 +431,6 @@ @Override public String toString() { - return nodeClass.getSimpleName() + ":" + type; - } - - void appendOffsets(StringBuilder sb) { - for (int i = 0; i < offsets.length; i++) { - sb.append(i == 0 ? "" : ", ").append(offsets[i]); - } + return super.toString() + ":" + type; } }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Thu Sep 25 12:02:50 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Sep 26 00:18:15 2014 +0200 @@ -28,6 +28,7 @@ import java.lang.annotation.*; import java.util.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.Graph.NodeEventListener; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graph.spi.*; @@ -471,8 +472,9 @@ } /** - * Updates the usages sets of the given nodes after an input slot is changed from oldInput to - * newInput: removes this node from oldInput's usages and adds this node to newInput's usages. + * Updates the usages sets of the given nodes after an input slot is changed from + * {@code oldInput} to {@code newInput} by removing this node from {@code oldInput}'s usages and + * adds this node to {@code newInput}'s usages. */ protected void updateUsages(Node oldInput, Node newInput) { assert isAlive() && (newInput == null || newInput.isAlive()) : "adding " + newInput + " to " + this + " instead of " + oldInput; @@ -883,9 +885,9 @@ */ public Map<Object, Object> getDebugProperties(Map<Object, Object> map) { NodeClass nodeClass = getNodeClass(); - for (Integer pos : nodeClass.getPropertyPositions()) { - map.put(nodeClass.getPropertyName(pos), nodeClass.getProperty(this, pos)); - + Fields properties = nodeClass.getProperties(); + for (int i = 0; i < properties.getCount(); i++) { + map.put(properties.getName(i), properties.get(this, i)); } return map; }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Thu Sep 25 12:02:50 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Fri Sep 26 00:18:15 2014 +0200 @@ -111,8 +111,8 @@ private final Edges inputs; private final Edges successors; + private final Fields properties; - private final Class<?>[] dataTypes; private final boolean canGVN; private final int startGVNNumber; private final String shortName; @@ -174,11 +174,7 @@ inputs = new InputEdges(clazz, fs.inputOffsets.size(), sortedOffsets(fs.inputOffsets, fs.inputListOffsets), fs.fieldNames, fs.fieldTypes, fs.types, fs.optionalInputs); } try (TimerCloseable t1 = Init_Data.start()) { - dataOffsets = sortedLongCopy(fs.dataOffsets); - dataTypes = new Class[dataOffsets.length]; - for (int i = 0; i < dataOffsets.length; i++) { - dataTypes[i] = fs.fieldTypes.get(dataOffsets[i]); - } + properties = new Fields(clazz, sortedLongCopy(fs.dataOffsets), fs.fieldNames, fs.fieldTypes); } isLeafNode = inputs.getCount() + successors.getCount() == 0; @@ -288,7 +284,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) { ... } @@ -402,13 +398,11 @@ public String toString() { StringBuilder str = new StringBuilder(); str.append("NodeClass ").append(getClazz().getSimpleName()).append(" ["); - inputs.appendOffsets(str); - str.append("] ["); - successors.appendOffsets(str); + inputs.appendFields(str); str.append("] ["); - for (int i = 0; i < dataOffsets.length; i++) { - str.append(i == 0 ? "" : ", ").append(dataOffsets[i]); - } + successors.appendFields(str); + str.append("] ["); + properties.appendFields(str); str.append("]"); return str.toString(); } @@ -443,41 +437,41 @@ int number = 0; if (canGVN) { number = startGVNNumber; - for (int i = 0; i < dataOffsets.length; ++i) { - Class<?> type = dataTypes[i]; + for (int i = 0; i < properties.getCount(); ++i) { + Class<?> type = properties.getType(i); if (type.isPrimitive()) { if (type == Integer.TYPE) { - int intValue = unsafe.getInt(n, dataOffsets[i]); + int intValue = properties.getInt(n, i); number += intValue; } else if (type == Long.TYPE) { - long longValue = unsafe.getLong(n, dataOffsets[i]); + long longValue = properties.getLong(n, i); number += longValue ^ (longValue >>> 32); } else if (type == Boolean.TYPE) { - boolean booleanValue = unsafe.getBoolean(n, dataOffsets[i]); + boolean booleanValue = properties.getBoolean(n, i); if (booleanValue) { number += 7; } } else if (type == Float.TYPE) { - float floatValue = unsafe.getFloat(n, dataOffsets[i]); + float floatValue = properties.getFloat(n, i); number += Float.floatToRawIntBits(floatValue); } else if (type == Double.TYPE) { - double doubleValue = unsafe.getDouble(n, dataOffsets[i]); + double doubleValue = properties.getDouble(n, i); long longValue = Double.doubleToRawLongBits(doubleValue); number += longValue ^ (longValue >>> 32); } else if (type == Short.TYPE) { - short shortValue = unsafe.getShort(n, dataOffsets[i]); + short shortValue = properties.getShort(n, i); number += shortValue; } else if (type == Character.TYPE) { - char charValue = unsafe.getChar(n, dataOffsets[i]); + char charValue = properties.getChar(n, i); number += charValue; } else if (type == Byte.TYPE) { - byte byteValue = unsafe.getByte(n, dataOffsets[i]); + byte byteValue = properties.getByte(n, i); number += byteValue; } else { assert false : "unhandled property type: " + type; } } else { - Object o = unsafe.getObject(n, dataOffsets[i]); + Object o = properties.getObject(n, i, Object.class); number += deepHashCode0(o); } number *= 13; @@ -517,54 +511,54 @@ if (a.getClass() != b.getClass()) { return a == b; } - for (int i = 0; i < dataOffsets.length; ++i) { - Class<?> type = dataTypes[i]; + for (int i = 0; i < properties.getCount(); ++i) { + Class<?> type = properties.getType(i); if (type.isPrimitive()) { if (type == Integer.TYPE) { - int aInt = unsafe.getInt(a, dataOffsets[i]); - int bInt = unsafe.getInt(b, dataOffsets[i]); + int aInt = properties.getInt(a, i); + int bInt = properties.getInt(b, i); if (aInt != bInt) { return false; } } else if (type == Boolean.TYPE) { - boolean aBoolean = unsafe.getBoolean(a, dataOffsets[i]); - boolean bBoolean = unsafe.getBoolean(b, dataOffsets[i]); + boolean aBoolean = properties.getBoolean(a, i); + boolean bBoolean = properties.getBoolean(b, i); if (aBoolean != bBoolean) { return false; } } else if (type == Long.TYPE) { - long aLong = unsafe.getLong(a, dataOffsets[i]); - long bLong = unsafe.getLong(b, dataOffsets[i]); + long aLong = properties.getLong(a, i); + long bLong = properties.getLong(b, i); if (aLong != bLong) { return false; } } else if (type == Float.TYPE) { - float aFloat = unsafe.getFloat(a, dataOffsets[i]); - float bFloat = unsafe.getFloat(b, dataOffsets[i]); + float aFloat = properties.getFloat(a, i); + float bFloat = properties.getFloat(b, i); if (aFloat != bFloat) { return false; } } else if (type == Double.TYPE) { - double aDouble = unsafe.getDouble(a, dataOffsets[i]); - double bDouble = unsafe.getDouble(b, dataOffsets[i]); + double aDouble = properties.getDouble(a, i); + double bDouble = properties.getDouble(b, i); if (aDouble != bDouble) { return false; } } else if (type == Short.TYPE) { - short aShort = unsafe.getShort(a, dataOffsets[i]); - short bShort = unsafe.getShort(b, dataOffsets[i]); + short aShort = properties.getShort(a, i); + short bShort = properties.getShort(b, i); if (aShort != bShort) { return false; } } else if (type == Character.TYPE) { - char aChar = unsafe.getChar(a, dataOffsets[i]); - char bChar = unsafe.getChar(b, dataOffsets[i]); + char aChar = properties.getChar(a, i); + char bChar = properties.getChar(b, i); if (aChar != bChar) { return false; } } else if (type == Byte.TYPE) { - byte aByte = unsafe.getByte(a, dataOffsets[i]); - byte bByte = unsafe.getByte(b, dataOffsets[i]); + byte aByte = properties.getByte(a, i); + byte bByte = properties.getByte(b, i); if (aByte != bByte) { return false; } @@ -572,8 +566,8 @@ assert false : "unhandled type: " + type; } } else { - Object objectA = unsafe.getObject(a, dataOffsets[i]); - Object objectB = unsafe.getObject(b, dataOffsets[i]); + Object objectA = properties.getObject(a, i, Object.class); + Object objectB = properties.getObject(b, i, Object.class); if (objectA != objectB) { if (objectA != null && objectB != null) { if (!deepEquals0(objectA, objectB)) { @@ -599,74 +593,14 @@ if (pos.getIndex() >= fromEdges.getCount()) { return false; } - return toEdges.isSameEdge(fromEdges, pos.getIndex()); - } - - public String getPropertyName(int pos) { - return fieldNames.get(dataOffsets[pos]); - } - - public Class<?> getPropertyType(int pos) { - return fieldTypes.get(dataOffsets[pos]); + return toEdges.isSame(fromEdges, pos.getIndex()); } - public Object getProperty(Node node, int pos) { - long dataOffset = dataOffsets[pos]; - Class<?> type = fieldTypes.get(dataOffset); - Object value = null; - if (type.isPrimitive()) { - if (type == Integer.TYPE) { - value = unsafe.getInt(node, dataOffset); - } else if (type == Long.TYPE) { - value = unsafe.getLong(node, dataOffset); - } else if (type == Boolean.TYPE) { - value = unsafe.getBoolean(node, dataOffset); - } else if (type == Float.TYPE) { - value = unsafe.getFloat(node, dataOffset); - } else if (type == Double.TYPE) { - value = unsafe.getDouble(node, dataOffset); - } else if (type == Short.TYPE) { - value = unsafe.getShort(node, dataOffset); - } else if (type == Character.TYPE) { - value = unsafe.getChar(node, dataOffset); - } else if (type == Byte.TYPE) { - value = unsafe.getByte(node, dataOffset); - } else { - assert false : "unhandled property type: " + type; - } - } else { - value = unsafe.getObject(node, dataOffset); - } - return value; - } - - public void setProperty(Node node, int pos, Object value) { - long dataOffset = dataOffsets[pos]; - Class<?> type = fieldTypes.get(dataOffset); - if (type.isPrimitive()) { - if (type == Integer.TYPE) { - unsafe.putInt(node, dataOffset, (Integer) value); - } else if (type == Long.TYPE) { - unsafe.putLong(node, dataOffset, (Long) value); - } else if (type == Boolean.TYPE) { - unsafe.putBoolean(node, dataOffset, (Boolean) value); - } else if (type == Float.TYPE) { - unsafe.putFloat(node, dataOffset, (Float) value); - } else if (type == Double.TYPE) { - unsafe.putDouble(node, dataOffset, (Double) value); - } else if (type == Short.TYPE) { - unsafe.putShort(node, dataOffset, (Short) value); - } else if (type == Character.TYPE) { - unsafe.putChar(node, dataOffset, (Character) value); - } else if (type == Byte.TYPE) { - unsafe.putByte(node, dataOffset, (Byte) value); - } else { - assert false : "unhandled property type: " + type; - } - } else { - assert value == null || !value.getClass().isPrimitive(); - unsafe.putObject(node, dataOffset, value); - } + /** + * Gets the non-edge properties defined by this node class. + */ + public Fields getProperties() { + return properties; } static void updateEdgesInPlace(Node node, InplaceUpdateClosure duplicationReplacement, Edges edges) { @@ -719,36 +653,6 @@ return type == Edges.Type.Inputs ? inputs : successors; } - public Collection<Integer> getPropertyPositions() { - return new AbstractCollection<Integer>() { - @Override - public Iterator<Integer> iterator() { - return new Iterator<Integer>() { - int i = 0; - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - public Integer next() { - Integer pos = i++; - return pos; - } - - public boolean hasNext() { - return i < dataOffsets.length; - } - }; - } - - @Override - public int size() { - return dataOffsets.length; - } - }; - } - /** * Initializes a fresh allocated node for which no constructor is called yet. Needed to * implement node factories in svm.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeferredPiNode.java Fri Sep 26 00:18:15 2014 +0200 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes; + +//JaCoCo Exclude + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.calc.*; + +/** + * A node that changes the type of its input where the type is not immediately available at node + * intrinsification time. It is replaced by a {@link PiNode} once the type becomes constant. + */ +@NodeInfo +public class DeferredPiNode extends FloatingNode implements Canonicalizable { + + @Input ValueNode object; + @Input ValueNode type; + + public ValueNode object() { + return object; + } + + public static DeferredPiNode create(ValueNode type, ValueNode object) { + return USE_GENERATED_NODES ? new DeferredPiNodeGen(type, object) : new DeferredPiNode(type, object); + } + + protected DeferredPiNode(ValueNode type, ValueNode object) { + super(StampFactory.object()); + this.type = type; + this.object = object; + } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (type.isConstant()) { + ResolvedJavaType javaType = tool.getConstantReflection().asJavaType(type.asConstant()); + ObjectStamp objectStamp = (ObjectStamp) stamp(); + return PiNode.create(object, javaType, objectStamp.isExactType(), objectStamp.nonNull()); + } + return this; + } + + @NodeIntrinsic + public static native <T> T piCast(Class<T> type, Object object); +}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/EdgesSubstitutions.java Thu Sep 25 12:02:50 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; - -/** - * Substitutions for improving the performance of some critical methods in {@link Edges}. These - * substitutions improve the performance by forcing the relevant methods to be inlined - * (intrinsification being a special form of inlining) and removing a checked cast. The latter - * cannot be done directly in Java code as {@link PiNode} is not available to the project containing - * {@link Edges}. - */ -@ClassSubstitution(Edges.class) -public class EdgesSubstitutions { - - @MethodSubstitution - private static Node getNode(Node node, long offset) { - return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), Node.class); - } - - @MethodSubstitution - private static NodeList<?> getNodeList(Node node, long offset) { - return PiNode.piCast(UnsafeLoadNode.load(node, offset, Kind.Object, LocationIdentity.ANY_LOCATION), NodeList.class); - } - - @MethodSubstitution - private static void putNode(Node node, long offset, Node value) { - UnsafeStoreNode.store(node, offset, value, Kind.Object, LocationIdentity.ANY_LOCATION); - } - - @MethodSubstitution - private static void putNodeList(Node node, long offset, NodeList<?> value) { - UnsafeStoreNode.store(node, offset, value, Kind.Object, LocationIdentity.ANY_LOCATION); - } - -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/FieldsSubstitutions.java Fri Sep 26 00:18:15 2014 +0200 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; + +/** + * Substitutions for improving the performance of some critical methods in {@link Fields}. These + * substitutions improve the performance by forcing the relevant methods to be inlined + * (intrinsification being a special form of inlining) and removing a checked cast. The latter + * cannot be done directly in Java code as {@link DeferredPiNode} is not available to the project + * containing {@link Fields}. + */ +@ClassSubstitution(Fields.class) +public class FieldsSubstitutions { + + @MethodSubstitution + private static <T> T getObject(Object object, long offset, Class<T> c) { + return DeferredPiNode.piCast(c, UnsafeLoadNode.load(object, offset, Kind.Object, LocationIdentity.ANY_LOCATION)); + } + + @MethodSubstitution + private static void putObject(Object node, long offset, Object value) { + UnsafeStoreNode.store(node, offset, value, Kind.Object, LocationIdentity.ANY_LOCATION); + } +}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Thu Sep 25 12:02:50 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Fri Sep 26 00:18:15 2014 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.nodes.spi.*; /** @@ -50,6 +51,7 @@ replacements.registerSubstitutions(Character.class, CharacterSubstitutions.class); replacements.registerSubstitutions(Short.class, ShortSubstitutions.class); replacements.registerSubstitutions(UnsignedMath.class, UnsignedMathSubstitutions.class); + replacements.registerSubstitutions(Fields.class, FieldsSubstitutions.class); } } }