changeset 10647:2ea604c4c6ec

Factor and improve unsafe load/store canonicalization.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sun, 07 Jul 2013 22:28:18 +0200
parents e7c2a0aa1fff
children 8660a090c3e2
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java
diffstat 4 files changed, 56 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Sun Jul 07 21:30:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeAccessNode.java	Sun Jul 07 22:28:18 2013 +0200
@@ -24,9 +24,10 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public abstract class UnsafeAccessNode extends FixedWithNextNode {
+public abstract class UnsafeAccessNode extends FixedWithNextNode implements Canonicalizable {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
@@ -57,4 +58,38 @@
     public Kind accessKind() {
         return accessKind;
     }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (offset().isConstant()) {
+            long constantOffset = offset().asConstant().asLong();
+
+            // Try to canonicalize to a field access.
+            if (object().stamp() instanceof ObjectStamp) {
+                // TODO (gd) remove that once UnsafeAccess only have an object base
+                ObjectStamp receiverStamp = object().objectStamp();
+                ResolvedJavaType receiverType = receiverStamp.type();
+                ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement() + constantOffset);
+
+                // No need for checking that the receiver is non-null. The field access includes the
+                // null check and if a field is found, the offset is so small that this is never a
+                // valid access of an arbitrary address.
+                if (field != null && field.getKind() == this.accessKind()) {
+                    return cloneAsFieldAccess(field);
+                }
+            }
+
+            if (constantOffset != 0 && Integer.MAX_VALUE - displacement() >= constantOffset) {
+                int intDisplacement = (int) (constantOffset + displacement());
+                if (constantOffset == intDisplacement) {
+                    return cloneWithZeroOffset(intDisplacement);
+                }
+            }
+        }
+        return this;
+    }
+
+    protected abstract ValueNode cloneAsFieldAccess(ResolvedJavaField field);
+
+    protected abstract ValueNode cloneWithZeroOffset(int intDisplacement);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Sun Jul 07 21:30:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Sun Jul 07 22:28:18 2013 +0200
@@ -25,7 +25,6 @@
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -35,7 +34,7 @@
  * Load of a value from a location specified as an offset relative to an object. No null check is
  * performed before the load.
  */
-public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable, Canonicalizable {
+public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable {
 
     public UnsafeLoadNode(ValueNode object, int displacement, ValueNode offset, boolean nonNull) {
         this(nonNull ? StampFactory.objectNonNull() : StampFactory.object(), object, displacement, offset, Kind.Object);
@@ -70,29 +69,13 @@
     }
 
     @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
-        if (offset().isConstant()) {
-            long constantOffset = offset().asConstant().asLong();
-            if (constantOffset != 0) {
-                int intDisplacement = (int) (constantOffset + displacement());
-                if (constantOffset == intDisplacement) {
-                    Graph graph = this.graph();
-                    return graph.add(new UnsafeLoadNode(this.stamp(), object(), intDisplacement, graph.unique(ConstantNode.forInt(0, graph)), accessKind()));
-                }
-            } else if (object().stamp() instanceof ObjectStamp) { // TODO (gd) remove that once
-                                                                  // UnsafeAccess only have an
-                                                                  // object base
-                ObjectStamp receiverStamp = object().objectStamp();
-                ResolvedJavaType receiverType = receiverStamp.type();
-                if (receiverStamp.nonNull() && receiverType != null) {
-                    ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement());
-                    if (field != null && field.getKind() == this.accessKind()) {
-                        return this.graph().add(new LoadFieldNode(object(), field));
-                    }
-                }
-            }
-        }
-        return this;
+    protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) {
+        return this.graph().add(new LoadFieldNode(object(), field));
+    }
+
+    @Override
+    protected ValueNode cloneWithZeroOffset(int intDisplacement) {
+        return graph().add(new UnsafeLoadNode(this.stamp(), object(), intDisplacement, graph().unique(ConstantNode.forInt(0, graph())), accessKind()));
     }
 
     @SuppressWarnings("unchecked")
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Sun Jul 07 21:30:25 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Sun Jul 07 22:28:18 2013 +0200
@@ -34,7 +34,7 @@
  * Store of a value at a location specified as an offset relative to an object. No null check is
  * performed before the store.
  */
-public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, Canonicalizable, MemoryCheckpoint.Single {
+public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, MemoryCheckpoint.Single {
 
     @Input private ValueNode value;
     @Input(notDataflow = true) private FrameState stateAfter;
@@ -94,32 +94,17 @@
     }
 
     @Override
-    public ValueNode canonical(CanonicalizerTool tool) {
-        if (offset().isConstant()) {
-            long constantOffset = offset().asConstant().asLong();
-            if (constantOffset != 0) {
-                int intDisplacement = (int) (constantOffset + displacement());
-                if (constantOffset == intDisplacement) {
-                    UnsafeStoreNode unsafeStoreNode = graph().add(new UnsafeStoreNode(stamp(), object(), intDisplacement, ConstantNode.forInt(0, graph()), value(), accessKind()));
-                    unsafeStoreNode.setStateAfter(stateAfter());
-                    return unsafeStoreNode;
-                }
-            } else if (object().stamp() instanceof ObjectStamp) { // TODO (gd) remove that once
-                                                                  // UnsafeAccess only have an
-                                                                  // object base
-                ObjectStamp receiverStamp = object().objectStamp();
-                if (receiverStamp.nonNull()) {
-                    ResolvedJavaType receiverType = receiverStamp.type();
-                    ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(displacement());
-                    if (field != null && field.getKind() == this.accessKind()) {
-                        StoreFieldNode storeFieldNode = graph().add(new StoreFieldNode(object(), field, value()));
-                        storeFieldNode.setStateAfter(stateAfter());
-                        return storeFieldNode;
-                    }
-                }
-            }
-        }
-        return this;
+    protected ValueNode cloneAsFieldAccess(ResolvedJavaField field) {
+        StoreFieldNode storeFieldNode = graph().add(new StoreFieldNode(object(), field, value()));
+        storeFieldNode.setStateAfter(stateAfter());
+        return storeFieldNode;
+    }
+
+    @Override
+    protected ValueNode cloneWithZeroOffset(int intDisplacement) {
+        UnsafeStoreNode unsafeStoreNode = graph().add(new UnsafeStoreNode(stamp(), object(), intDisplacement, ConstantNode.forInt(0, graph()), value(), accessKind()));
+        unsafeStoreNode.setStateAfter(stateAfter());
+        return unsafeStoreNode;
     }
 
     // specialized on value type until boxing/unboxing is sorted out in intrinsification
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java	Sun Jul 07 21:30:25 2013 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java	Sun Jul 07 22:28:18 2013 +0200
@@ -26,7 +26,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.common.*;