changeset 17130:f396d15ddce2

Factor out HotSpot-independent parts of ArrayCopy and ObjectClone nodes
author Christian Wimmer <christian.wimmer@oracle.com>
date Tue, 16 Sep 2014 18:43:39 -0700
parents f2a87467d41a
children 4e15850b67bb
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java
diffstat 5 files changed, 269 insertions(+), 182 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java	Tue Sep 16 18:42:23 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyCallNode.java	Tue Sep 16 18:43:39 2014 -0700
@@ -185,6 +185,10 @@
         return uninitialized;
     }
 
+    static boolean isHeapWordAligned(Constant value, Kind kind) {
+        return (arrayBaseOffset(kind) + (long) value.asInt() * arrayIndexScale(kind)) % heapWordSize() == 0;
+    }
+
     public void updateAlignedDisjoint() {
         Kind componentKind = elementKind;
         if (srcPos == destPos) {
@@ -195,7 +199,7 @@
         Constant constantDst = destPos.stamp().asConstant();
         if (constantSrc != null && constantDst != null) {
             if (!aligned) {
-                aligned = ArrayCopyNode.isHeapWordAligned(constantSrc, componentKind) && ArrayCopyNode.isHeapWordAligned(constantDst, componentKind);
+                aligned = isHeapWordAligned(constantSrc, componentKind) && isHeapWordAligned(constantDst, componentKind);
             }
             if (constantSrc.asInt() >= constantDst.asInt()) {
                 // low to high copy so treat as disjoint
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Tue Sep 16 18:42:23 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ArrayCopyNode.java	Tue Sep 16 18:43:39 2014 -0700
@@ -23,7 +23,6 @@
 package com.oracle.graal.hotspot.replacements;
 
 import static com.oracle.graal.compiler.GraalCompiler.*;
-import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
@@ -34,13 +33,12 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.nodes.*;
 
 @NodeInfo
-public class ArrayCopyNode extends MacroStateSplitNode implements Virtualizable, Lowerable {
+public class ArrayCopyNode extends BasicArrayCopyNode implements Virtualizable, Lowerable {
 
     public static ArrayCopyNode create(Invoke invoke) {
         return USE_GENERATED_NODES ? new ArrayCopyNodeGen(invoke) : new ArrayCopyNode(invoke);
@@ -50,30 +48,6 @@
         super(invoke);
     }
 
-    private ValueNode getSource() {
-        return arguments.get(0);
-    }
-
-    private ValueNode getSourcePosition() {
-        return arguments.get(1);
-    }
-
-    private ValueNode getDestination() {
-        return arguments.get(2);
-    }
-
-    private ValueNode getDestinationPosition() {
-        return arguments.get(3);
-    }
-
-    private ValueNode getLength() {
-        return arguments.get(4);
-    }
-
-    static boolean isHeapWordAligned(Constant value, Kind kind) {
-        return (arrayBaseOffset(kind) + (long) value.asInt() * arrayIndexScale(kind)) % heapWordSize() == 0;
-    }
-
     private StructuredGraph selectSnippet(LoweringTool tool, final Replacements replacements) {
         ResolvedJavaType srcType = StampTool.typeOrNull(getSource().stamp());
         ResolvedJavaType destType = StampTool.typeOrNull(getDestination().stamp());
@@ -162,67 +136,4 @@
         }
         return false;
     }
-
-    private static boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) {
-        return position >= 0 && position + length <= virtualObject.entryCount();
-    }
-
-    private static boolean checkEntryTypes(int srcPos, int length, State srcState, ResolvedJavaType destComponentType, VirtualizerTool tool) {
-        if (destComponentType.getKind() == Kind.Object) {
-            for (int i = 0; i < length; i++) {
-                ValueNode entry = srcState.getEntry(srcPos + i);
-                State state = tool.getObjectState(entry);
-                ResolvedJavaType type;
-                if (state != null) {
-                    if (state.getState() == EscapeState.Virtual) {
-                        type = state.getVirtualObject().type();
-                    } else {
-                        type = StampTool.typeOrNull(state.getMaterializedValue());
-                    }
-                } else {
-                    type = StampTool.typeOrNull(entry);
-                }
-                if (type == null || !destComponentType.isAssignableFrom(type)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    @Override
-    public void virtualize(VirtualizerTool tool) {
-        if (getSourcePosition().isConstant() && getDestinationPosition().isConstant() && getLength().isConstant()) {
-            int srcPos = getSourcePosition().asConstant().asInt();
-            int destPos = getDestinationPosition().asConstant().asInt();
-            int length = getLength().asConstant().asInt();
-            State srcState = tool.getObjectState(getSource());
-            State destState = tool.getObjectState(getDestination());
-
-            if (srcState != null && srcState.getState() == EscapeState.Virtual && destState != null && destState.getState() == EscapeState.Virtual) {
-                VirtualObjectNode srcVirtual = srcState.getVirtualObject();
-                VirtualObjectNode destVirtual = destState.getVirtualObject();
-                if (!(srcVirtual instanceof VirtualArrayNode) || !(destVirtual instanceof VirtualArrayNode)) {
-                    return;
-                }
-                if (((VirtualArrayNode) srcVirtual).componentType().getKind() != Kind.Object || ((VirtualArrayNode) destVirtual).componentType().getKind() != Kind.Object) {
-                    return;
-                }
-                if (length < 0 || !checkBounds(srcPos, length, srcVirtual) || !checkBounds(destPos, length, destVirtual)) {
-                    return;
-                }
-                if (!checkEntryTypes(srcPos, length, srcState, destVirtual.type().getComponentType(), tool)) {
-                    return;
-                }
-                for (int i = 0; i < length; i++) {
-                    tool.setVirtualEntry(destState, destPos + i, srcState.getEntry(srcPos + i), false);
-                }
-                tool.delete();
-                if (Debug.isLogEnabled()) {
-                    Debug.log("virtualized arraycopyf(%s, %d, %s, %d, %d)", getSource(), srcPos, getDestination(), destPos, length);
-                }
-            }
-        }
-    }
-
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Tue Sep 16 18:42:23 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java	Tue Sep 16 18:43:39 2014 -0700
@@ -25,11 +25,8 @@
 import static com.oracle.graal.compiler.GraalCompiler.*;
 
 import java.lang.reflect.*;
-import java.util.*;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.nodeinfo.*;
@@ -37,11 +34,10 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.replacements.nodes.*;
 
 @NodeInfo
-public class ObjectCloneNode extends MacroStateSplitNode implements VirtualizableAllocation, ArrayLengthProvider {
+public class ObjectCloneNode extends BasicObjectCloneNode implements VirtualizableAllocation, ArrayLengthProvider {
 
     public static ObjectCloneNode create(Invoke invoke) {
         return USE_GENERATED_NODES ? new ObjectCloneNodeGen(invoke) : new ObjectCloneNode(invoke);
@@ -52,15 +48,6 @@
     }
 
     @Override
-    public boolean inferStamp() {
-        return updateStamp(getObject().stamp());
-    }
-
-    private ValueNode getObject() {
-        return arguments.get(0);
-    }
-
-    @Override
     protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) {
         if (!shouldIntrinsify(getTargetMethod())) {
             return null;
@@ -105,81 +92,4 @@
         }
         return null;
     }
-
-    private static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) {
-        return metaAccess.lookupJavaType(Cloneable.class).isAssignableFrom(type);
-    }
-
-    /*
-     * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an
-     * exact type) and if it is a cloneable type.
-     * 
-     * If yes, then the exact type is returned, otherwise it returns null.
-     */
-    private static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) {
-        if (!(stamp instanceof ObjectStamp)) {
-            return null;
-        }
-        ObjectStamp objectStamp = (ObjectStamp) stamp;
-        if (objectStamp.type() == null) {
-            return null;
-        } else if (objectStamp.isExactType()) {
-            return isCloneableType(objectStamp.type(), metaAccess) ? objectStamp.type() : null;
-        } else {
-            ResolvedJavaType type = objectStamp.type().findUniqueConcreteSubtype();
-            if (type != null && isCloneableType(type, metaAccess)) {
-                assumptions.recordConcreteSubtype(objectStamp.type(), type);
-                return type;
-            } else {
-                return null;
-            }
-        }
-    }
-
-    @Override
-    public void virtualize(VirtualizerTool tool) {
-        State originalState = tool.getObjectState(getObject());
-        if (originalState != null && originalState.getState() == EscapeState.Virtual) {
-            VirtualObjectNode originalVirtual = originalState.getVirtualObject();
-            if (isCloneableType(originalVirtual.type(), tool.getMetaAccessProvider())) {
-                ValueNode[] newEntryState = new ValueNode[originalVirtual.entryCount()];
-                for (int i = 0; i < newEntryState.length; i++) {
-                    newEntryState[i] = originalState.getEntry(i);
-                }
-                VirtualObjectNode newVirtual = originalVirtual.duplicate();
-                tool.createVirtualObject(newVirtual, newEntryState, Collections.<MonitorIdNode> emptyList());
-                tool.replaceWithVirtual(newVirtual);
-            }
-        } else {
-            ValueNode obj;
-            if (originalState != null) {
-                obj = originalState.getMaterializedValue();
-            } else {
-                obj = tool.getReplacedValue(getObject());
-            }
-            ResolvedJavaType type = getConcreteType(obj.stamp(), tool.getAssumptions(), tool.getMetaAccessProvider());
-            if (type != null && !type.isArray()) {
-                VirtualInstanceNode newVirtual = VirtualInstanceNode.create(type, true);
-                ResolvedJavaField[] fields = newVirtual.getFields();
-
-                ValueNode[] state = new ValueNode[fields.length];
-                final LoadFieldNode[] loads = new LoadFieldNode[fields.length];
-                for (int i = 0; i < fields.length; i++) {
-                    state[i] = loads[i] = LoadFieldNode.create(obj, fields[i]);
-                    tool.addNode(loads[i]);
-                }
-                tool.createVirtualObject(newVirtual, state, Collections.<MonitorIdNode> emptyList());
-                tool.replaceWithVirtual(newVirtual);
-            }
-        }
-    }
-
-    @Override
-    public ValueNode length() {
-        if (getObject() instanceof ArrayLengthProvider) {
-            return ((ArrayLengthProvider) getObject()).length();
-        } else {
-            return null;
-        }
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java	Tue Sep 16 18:43:39 2014 -0700
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 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.replacements.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
+
+@NodeInfo
+public class BasicArrayCopyNode extends MacroStateSplitNode implements Virtualizable {
+
+    public static BasicArrayCopyNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new BasicArrayCopyNodeGen(invoke) : new BasicArrayCopyNode(invoke);
+    }
+
+    protected BasicArrayCopyNode(Invoke invoke) {
+        super(invoke);
+    }
+
+    protected ValueNode getSource() {
+        return arguments.get(0);
+    }
+
+    protected ValueNode getSourcePosition() {
+        return arguments.get(1);
+    }
+
+    protected ValueNode getDestination() {
+        return arguments.get(2);
+    }
+
+    protected ValueNode getDestinationPosition() {
+        return arguments.get(3);
+    }
+
+    protected ValueNode getLength() {
+        return arguments.get(4);
+    }
+
+    private static boolean checkBounds(int position, int length, VirtualObjectNode virtualObject) {
+        return position >= 0 && position + length <= virtualObject.entryCount();
+    }
+
+    private static boolean checkEntryTypes(int srcPos, int length, State srcState, ResolvedJavaType destComponentType, VirtualizerTool tool) {
+        if (destComponentType.getKind() == Kind.Object) {
+            for (int i = 0; i < length; i++) {
+                ValueNode entry = srcState.getEntry(srcPos + i);
+                State state = tool.getObjectState(entry);
+                ResolvedJavaType type;
+                if (state != null) {
+                    if (state.getState() == EscapeState.Virtual) {
+                        type = state.getVirtualObject().type();
+                    } else {
+                        type = StampTool.typeOrNull(state.getMaterializedValue());
+                    }
+                } else {
+                    type = StampTool.typeOrNull(entry);
+                }
+                if (type == null || !destComponentType.isAssignableFrom(type)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        if (getSourcePosition().isConstant() && getDestinationPosition().isConstant() && getLength().isConstant()) {
+            int srcPos = getSourcePosition().asConstant().asInt();
+            int destPos = getDestinationPosition().asConstant().asInt();
+            int length = getLength().asConstant().asInt();
+            State srcState = tool.getObjectState(getSource());
+            State destState = tool.getObjectState(getDestination());
+
+            if (srcState != null && srcState.getState() == EscapeState.Virtual && destState != null && destState.getState() == EscapeState.Virtual) {
+                VirtualObjectNode srcVirtual = srcState.getVirtualObject();
+                VirtualObjectNode destVirtual = destState.getVirtualObject();
+                if (!(srcVirtual instanceof VirtualArrayNode) || !(destVirtual instanceof VirtualArrayNode)) {
+                    return;
+                }
+                if (((VirtualArrayNode) srcVirtual).componentType().getKind() != Kind.Object || ((VirtualArrayNode) destVirtual).componentType().getKind() != Kind.Object) {
+                    return;
+                }
+                if (length < 0 || !checkBounds(srcPos, length, srcVirtual) || !checkBounds(destPos, length, destVirtual)) {
+                    return;
+                }
+                if (!checkEntryTypes(srcPos, length, srcState, destVirtual.type().getComponentType(), tool)) {
+                    return;
+                }
+                for (int i = 0; i < length; i++) {
+                    tool.setVirtualEntry(destState, destPos + i, srcState.getEntry(srcPos + i), false);
+                }
+                tool.delete();
+                if (Debug.isLogEnabled()) {
+                    Debug.log("virtualized arraycopyf(%s, %d, %s, %d, %d)", getSource(), srcPos, getDestination(), destPos, length);
+                }
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java	Tue Sep 16 18:43:39 2014 -0700
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 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.replacements.nodes;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.virtual.*;
+
+@NodeInfo
+public class BasicObjectCloneNode extends MacroStateSplitNode implements VirtualizableAllocation, ArrayLengthProvider {
+
+    public static BasicObjectCloneNode create(Invoke invoke) {
+        return USE_GENERATED_NODES ? new BasicObjectCloneNodeGen(invoke) : new BasicObjectCloneNode(invoke);
+    }
+
+    protected BasicObjectCloneNode(Invoke invoke) {
+        super(invoke);
+    }
+
+    @Override
+    public boolean inferStamp() {
+        return updateStamp(getObject().stamp());
+    }
+
+    public ValueNode getObject() {
+        return arguments.get(0);
+    }
+
+    protected static boolean isCloneableType(ResolvedJavaType type, MetaAccessProvider metaAccess) {
+        return metaAccess.lookupJavaType(Cloneable.class).isAssignableFrom(type);
+    }
+
+    /*
+     * Looks at the given stamp and determines if it is an exact type (or can be assumed to be an
+     * exact type) and if it is a cloneable type.
+     *
+     * If yes, then the exact type is returned, otherwise it returns null.
+     */
+    protected static ResolvedJavaType getConcreteType(Stamp stamp, Assumptions assumptions, MetaAccessProvider metaAccess) {
+        if (!(stamp instanceof ObjectStamp)) {
+            return null;
+        }
+        ObjectStamp objectStamp = (ObjectStamp) stamp;
+        if (objectStamp.type() == null) {
+            return null;
+        } else if (objectStamp.isExactType()) {
+            return isCloneableType(objectStamp.type(), metaAccess) ? objectStamp.type() : null;
+        } else {
+            ResolvedJavaType type = objectStamp.type().findUniqueConcreteSubtype();
+            if (type != null && isCloneableType(type, metaAccess)) {
+                assumptions.recordConcreteSubtype(objectStamp.type(), type);
+                return type;
+            } else {
+                return null;
+            }
+        }
+    }
+
+    @Override
+    public void virtualize(VirtualizerTool tool) {
+        State originalState = tool.getObjectState(getObject());
+        if (originalState != null && originalState.getState() == EscapeState.Virtual) {
+            VirtualObjectNode originalVirtual = originalState.getVirtualObject();
+            if (isCloneableType(originalVirtual.type(), tool.getMetaAccessProvider())) {
+                ValueNode[] newEntryState = new ValueNode[originalVirtual.entryCount()];
+                for (int i = 0; i < newEntryState.length; i++) {
+                    newEntryState[i] = originalState.getEntry(i);
+                }
+                VirtualObjectNode newVirtual = originalVirtual.duplicate();
+                tool.createVirtualObject(newVirtual, newEntryState, Collections.<MonitorIdNode> emptyList());
+                tool.replaceWithVirtual(newVirtual);
+            }
+        } else {
+            ValueNode obj;
+            if (originalState != null) {
+                obj = originalState.getMaterializedValue();
+            } else {
+                obj = tool.getReplacedValue(getObject());
+            }
+            ResolvedJavaType type = getConcreteType(obj.stamp(), tool.getAssumptions(), tool.getMetaAccessProvider());
+            if (type != null && !type.isArray()) {
+                VirtualInstanceNode newVirtual = createVirtualInstanceNode(type, true);
+                ResolvedJavaField[] fields = newVirtual.getFields();
+
+                ValueNode[] state = new ValueNode[fields.length];
+                final LoadFieldNode[] loads = new LoadFieldNode[fields.length];
+                for (int i = 0; i < fields.length; i++) {
+                    state[i] = loads[i] = LoadFieldNode.create(obj, fields[i]);
+                    tool.addNode(loads[i]);
+                }
+                tool.createVirtualObject(newVirtual, state, Collections.<MonitorIdNode> emptyList());
+                tool.replaceWithVirtual(newVirtual);
+            }
+        }
+    }
+
+    protected VirtualInstanceNode createVirtualInstanceNode(ResolvedJavaType type, boolean hasIdentity) {
+        return VirtualInstanceNode.create(type, hasIdentity);
+    }
+
+    @Override
+    public ValueNode length() {
+        if (getObject() instanceof ArrayLengthProvider) {
+            return ((ArrayLengthProvider) getObject()).length();
+        } else {
+            return null;
+        }
+    }
+}