changeset 13357:dad7737243c6

Canonicalize CompareAndSwapNode to a more precise location identity than ANY if possible
author Gilles Duboscq <duboscq@ssw.jku.at>
date Tue, 17 Dec 2013 11:57:20 +0100
parents 47d184ba15b6
children e1a50eac0eac
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java
diffstat 1 files changed, 28 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Dec 17 11:56:36 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Dec 17 11:57:20 2013 +0100
@@ -25,6 +25,8 @@
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,13 +36,14 @@
  * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the
  * value matched the expected value.
  */
-public class CompareAndSwapNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
+public class CompareAndSwapNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single, Canonicalizable {
 
     @Input private ValueNode object;
     @Input private ValueNode offset;
     @Input private ValueNode expected;
     @Input private ValueNode newValue;
     private final int displacement;
+    private final LocationIdentity locationIdentity;
 
     public ValueNode object() {
         return object;
@@ -63,6 +66,10 @@
     }
 
     public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue) {
+        this(object, displacement, offset, expected, newValue, LocationIdentity.ANY_LOCATION);
+    }
+
+    public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue, LocationIdentity locationIdentity) {
         super(StampFactory.forKind(Kind.Boolean.getStackKind()));
         assert expected.kind() == newValue.kind();
         this.object = object;
@@ -70,11 +77,12 @@
         this.expected = expected;
         this.newValue = newValue;
         this.displacement = displacement;
+        this.locationIdentity = locationIdentity;
     }
 
     @Override
     public LocationIdentity getLocationIdentity() {
-        return LocationIdentity.ANY_LOCATION;
+        return locationIdentity;
     }
 
     @Override
@@ -82,6 +90,24 @@
         tool.getLowerer().lower(this, tool);
     }
 
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        if (getLocationIdentity() == LocationIdentity.ANY_LOCATION) {
+            Constant offsetConstant = offset().asConstant();
+            if (offsetConstant != null) {
+                ResolvedJavaType receiverType = ObjectStamp.typeOrNull(object());
+                if (receiverType != null) {
+                    long constantOffset = offsetConstant.asLong();
+                    ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(constantOffset);
+                    if (field != null && expected().kind() == field.getKind() && newValue().kind() == field.getKind()) {
+                        return graph().add(new CompareAndSwapNode(object, displacement, offset, expected, newValue, field));
+                    }
+                }
+            }
+        }
+        return this;
+    }
+
     // specialized on value type until boxing/unboxing is sorted out in intrinsification
     @NodeIntrinsic
     public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, Object expected, Object newValue) {