# HG changeset patch # User Doug Simon # Date 1412342162 -7200 # Node ID 1e7e354e407f17dcf46750b6fc40994edc0d2938 # Parent c9bb0da795d428b384642fa69d2cd22b67aa7716 use Unsafe.allocateInstance in Node.clone(Graph into, boolean clearInputsAndSuccessors) to avoid initializing fields twice diff -r c9bb0da795d4 -r 1e7e354e407f 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 Oct 03 14:19:58 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/Fields.java Fri Oct 03 15:16:02 2014 +0200 @@ -78,6 +78,43 @@ } /** + * Copies fields from {@code from} to {@code to}. The objects must be of the exact same type. + * + * @param from the object from which the fields should be copied. + * @param to the object to which the fields should be copied. + */ + public void copy(Object from, Object to) { + assert from.getClass() == to.getClass(); + for (int index = 0; index < offsets.length; index++) { + long offset = offsets[index]; + Class type = types[index]; + if (type.isPrimitive()) { + if (type == Integer.TYPE) { + unsafe.putInt(to, offset, unsafe.getInt(from, offset)); + } else if (type == Long.TYPE) { + unsafe.putLong(to, offset, unsafe.getLong(from, offset)); + } else if (type == Boolean.TYPE) { + unsafe.putBoolean(to, offset, unsafe.getBoolean(from, offset)); + } else if (type == Float.TYPE) { + unsafe.putFloat(to, offset, unsafe.getFloat(from, offset)); + } else if (type == Double.TYPE) { + unsafe.putDouble(to, offset, unsafe.getDouble(from, offset)); + } else if (type == Short.TYPE) { + unsafe.putShort(to, offset, unsafe.getShort(from, offset)); + } else if (type == Character.TYPE) { + unsafe.putChar(to, offset, unsafe.getChar(from, offset)); + } else if (type == Byte.TYPE) { + unsafe.putByte(to, offset, unsafe.getByte(from, offset)); + } else { + assert false : "unhandled property type: " + type; + } + } else { + unsafe.putObject(to, offset, unsafe.getObject(from, offset)); + } + } + } + + /** * Gets the value of a field for a given object. * * @param object the object whose field is to be read diff -r c9bb0da795d4 -r 1e7e354e407f 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 Oct 03 14:19:58 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Edges.java Fri Oct 03 15:16:02 2014 +0200 @@ -135,6 +135,24 @@ } /** + * Initializes the list edges in a given node based on the size of the list edges in a prototype + * node. + * + * @param node the node whose list edges are to be initialized + * @param prototype the node whose list edge sizes are used when creating new edge lists + */ + public void initializeLists(Node node, Node prototype) { + int index = getDirectCount(); + while (index < getCount()) { + NodeList list = getNodeList(prototype, index); + int size = list.initialSize; + NodeList newList = type == Edges.Type.Inputs ? new NodeInputList<>(node, size) : new NodeSuccessorList<>(node, size); + initializeList(node, index, newList); + index++; + } + } + + /** * Copies edges from {@code fromNode} to {@code toNode}. The nodes are expected to be of the * exact same type. * @@ -150,7 +168,13 @@ } while (index < getCount()) { NodeList list = getNodeList(toNode, index); - list.copy(getNodeList(fromNode, index)); + if (list == null) { + NodeList fromList = getNodeList(fromNode, index); + list = type == Edges.Type.Inputs ? new NodeInputList<>(toNode, fromList) : new NodeSuccessorList<>(toNode, fromList); + initializeList(toNode, index, list); + } else { + list.copy(getNodeList(fromNode, index)); + } index++; } } diff -r c9bb0da795d4 -r 1e7e354e407f 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 Oct 03 14:19:58 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Fri Oct 03 15:16:02 2014 +0200 @@ -58,6 +58,7 @@ public abstract class Node implements Cloneable, Formattable { public final static boolean USE_GENERATED_NODES = Boolean.parseBoolean(System.getProperty("graal.useGeneratedNodes", "true")); + public final static boolean USE_UNSAFE_CLONE = Boolean.parseBoolean(System.getProperty("graal.useUnsafeClone", "true")); static final int DELETED_ID_START = -1000000000; static final int INITIAL_ID = -1; @@ -756,24 +757,36 @@ Node newNode = null; try { - newNode = (Node) this.clone(); - } catch (CloneNotSupportedException e) { + if (USE_UNSAFE_CLONE) { + newNode = (Node) UnsafeAccess.unsafe.allocateInstance(getClass()); + nodeClass.getData().copy(this, newNode); + if (clearInputsAndSuccessors) { + nodeClass.getEdges(Inputs).initializeLists(newNode, this); + nodeClass.getEdges(Successors).initializeLists(newNode, this); + } else { + nodeClass.getEdges(Inputs).copy(this, newNode); + nodeClass.getEdges(Successors).copy(this, newNode); + } + } else { + newNode = (Node) this.clone(); + if (clearInputsAndSuccessors) { + nodeClass.getEdges(Inputs).clear(newNode); + nodeClass.getEdges(Successors).clear(newNode); + } + newNode.typeCacheNext = null; + newNode.usage0 = null; + newNode.usage1 = null; + newNode.predecessor = null; + } + } catch (Exception e) { throw new GraalGraphInternalError(e).addContext(this); } - if (clearInputsAndSuccessors) { - nodeClass.getEdges(Inputs).clear(newNode); - nodeClass.getEdges(Successors).clear(newNode); - } newNode.graph = into; - newNode.typeCacheNext = null; newNode.id = INITIAL_ID; if (into != null) { into.register(newNode); } - newNode.usage0 = null; - newNode.usage1 = null; newNode.extraUsages = NO_NODES; - newNode.predecessor = null; if (into != null && nodeClass.valueNumberable() && nodeClass.isLeafNode()) { into.putNodeIntoCache(newNode); diff -r c9bb0da795d4 -r 1e7e354e407f graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java Fri Oct 03 14:19:58 2014 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorList.java Fri Oct 03 15:16:02 2014 +0200 @@ -24,6 +24,8 @@ import static com.oracle.graal.graph.Edges.Type.*; +import java.util.*; + import com.oracle.graal.graph.Edges.*; public final class NodeSuccessorList extends NodeList { @@ -41,6 +43,11 @@ assert self.usages().isEmpty(); } + public NodeSuccessorList(Node self, List elements) { + super(self, elements); + assert self.usages().isEmpty(); + } + @Override protected void update(T oldNode, T newNode) { self.updatePredecessor(oldNode, newNode);