changeset 7031:2e577202843c

Better implementation of UnsafeCastNode
author Christian Wimmer <christian.wimmer@oracle.com>
date Mon, 26 Nov 2012 18:17:14 -0800
parents d78c83e8b70b
children 5a1f6e96e163
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/NodeClassSnippets.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java
diffstat 5 files changed, 54 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Mon Nov 26 18:03:47 2012 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Mon Nov 26 18:17:14 2012 -0800
@@ -31,70 +31,67 @@
 /**
  * The {@code UnsafeCastNode} produces the same value as its input, but with a different type.
  */
-public final class UnsafeCastNode extends FloatingNode implements Canonicalizable, LIRLowerable {
+public class UnsafeCastNode extends FloatingNode implements Canonicalizable, LIRLowerable {
 
-    @Input private ValueNode object;
-    private ResolvedJavaType toType;
+    @Input
+    private ValueNode object;
 
     public ValueNode object() {
         return object;
     }
 
-    public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
-        super(toType.getKind().isObject() ? new ObjectStamp(toType, exactType, nonNull, false) : StampFactory.forKind(toType.getKind()));
+    public UnsafeCastNode(ValueNode object, Stamp stamp) {
+        super(stamp);
         this.object = object;
-        this.toType = toType;
     }
 
-    public UnsafeCastNode(ValueNode object, ResolvedJavaType toType) {
-        super(toType.getKind().isObject() ? StampFactory.declared(toType, object.stamp().nonNull()) : StampFactory.forKind(toType.getKind()));
-        this.object = object;
-        this.toType = toType;
+    public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) {
+        this(object, toType.getKind().isObject() ? StampFactory.object(toType, exactType, nonNull || object.stamp().nonNull()) : StampFactory.forKind(toType.getKind()));
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        if (object != null) {
-            if (object.kind().isObject()) {
-                if (object.objectStamp().type() != null && object.objectStamp().type().isSubtypeOf(toType)) {
-                    if (!isNarrower(objectStamp(), object.objectStamp())) {
-                        return object;
-                    }
-                }
-            } else if (object.kind() == kind()) {
-                // Removes redundant casts introduced by WordTypeRewriterPhase
-                return object;
+        if (kind() != object.kind()) {
+            return this;
+        }
+
+        if (kind() == Kind.Object) {
+            ObjectStamp my = objectStamp();
+            ObjectStamp other = object.objectStamp();
+
+            if (my.type() == null || other.type() == null) {
+                return this;
+            }
+            if (my.isExactType() && !other.isExactType()) {
+                return this;
+            }
+            if (my.nonNull() && !other.nonNull()) {
+                return this;
+            }
+            if (my.type() != other.type() && my.type().isSubtypeOf(other.type())) {
+                return this;
             }
         }
-        return this;
+        return object;
     }
 
-    /**
-     * Determines if one object stamp is narrower than another in terms of nullness and exactness.
-     *
-     * @return true if x is definitely non-null and y's nullness is unknown OR
-     *                  x's type is exact and the exactness of y's type is unknown
-     */
-    private static boolean isNarrower(ObjectStamp x, ObjectStamp y) {
-        if (x.nonNull() && !y.nonNull()) {
-            return true;
+    @Override
+    public void generate(LIRGeneratorTool generator) {
+        if (kind() != object.kind()) {
+            assert generator.target().sizeInBytes(kind()) == generator.target().sizeInBytes(object.kind()) : "unsafe cast cannot be used to change the size of a value";
+            Value result = generator.newVariable(kind());
+            generator.emitMove(generator.operand(object), result);
+            generator.setResult(this, result);
+        } else {
+            // The LIR only cares about the kind of an operand, not the actual type of an object. So we do not have to
+            // introduce a new operand when the kind is the same.
+            generator.setResult(this, generator.operand(object));
         }
-        if (x.isExactType() && !y.isExactType()) {
-            return true;
-        }
-        return false;
     }
 
     @NodeIntrinsic
-    public static native <T> T cast(Object object, @ConstantNodeParameter Class<?> toType);
+    public static native <T> T unsafeCast(Object object, @ConstantNodeParameter Stamp stamp);
 
     @NodeIntrinsic
-    public static native <T> T cast(Object object, @ConstantNodeParameter Class<?> toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull);
-
-    @Override
-    public void generate(LIRGeneratorTool generator) {
-        Value result = generator.newVariable(kind());
-        generator.emitMove(generator.operand(object), result);
-        generator.setResult(this, result);
-    }
+    public static native <T> T unsafeCast(Object object, @ConstantNodeParameter Class<T> toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Mon Nov 26 18:03:47 2012 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Mon Nov 26 18:17:14 2012 -0800
@@ -165,13 +165,18 @@
     }
 
     public static Stamp declared(ResolvedJavaType type, boolean nonNull) {
+        return object(type, false, nonNull);
+    }
+
+    public static Stamp object(ResolvedJavaType type, boolean exactType, boolean nonNull) {
         assert type != null;
         assert type.getKind() == Kind.Object;
         ResolvedJavaType exact = type.asExactType();
         if (exact != null) {
+            assert !exactType || type == exact;
             return new ObjectStamp(exact, true, nonNull, false);
         } else {
-            return new ObjectStamp(type, false, nonNull, false);
+            return new ObjectStamp(type, exactType, nonNull, false);
         }
     }
 
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/NodeClassSnippets.java	Mon Nov 26 18:03:47 2012 -0800
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/NodeClassSnippets.java	Mon Nov 26 18:17:14 2012 -0800
@@ -38,11 +38,11 @@
 public class NodeClassSnippets implements SnippetsInterface {
 
     private static Node getNode(Node node, long offset) {
-        return UnsafeCastNode.cast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), Node.class);
+        return UnsafeCastNode.unsafeCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), Node.class, false, false);
     }
 
-    private static NodeList<Node> getNodeList(Node node, long offset) {
-        return UnsafeCastNode.cast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), NodeList.class);
+    private static NodeList getNodeList(Node node, long offset) {
+        return UnsafeCastNode.unsafeCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), NodeList.class, false, false);
     }
 
     private static void putNode(Node node, long offset, Node value) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Mon Nov 26 18:03:47 2012 -0800
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Mon Nov 26 18:17:14 2012 -0800
@@ -182,7 +182,7 @@
                         InliningUtil.inline(invoke, targetGraph, true);
                         Debug.dump(graph, "after inlining %s", callee);
                         if (GraalOptions.OptCanonicalizer) {
-                            new WordTypeRewriterPhase(target.wordKind, wordStamp, runtime.lookupJavaType(target.wordKind.toJavaClass())).apply(graph);
+                            new WordTypeRewriterPhase(target.wordKind, wordStamp).apply(graph);
                             new CanonicalizerPhase(target, runtime, null).apply(graph);
                         }
                     }
@@ -190,7 +190,7 @@
 
                 new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph);
 
-                new WordTypeRewriterPhase(target.wordKind, wordStamp, runtime.lookupJavaType(target.wordKind.toJavaClass())).apply(graph);
+                new WordTypeRewriterPhase(target.wordKind, wordStamp).apply(graph);
 
                 new DeadCodeEliminationPhase().apply(graph);
                 if (GraalOptions.OptCanonicalizer) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Mon Nov 26 18:03:47 2012 -0800
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Mon Nov 26 18:17:14 2012 -0800
@@ -47,11 +47,9 @@
 
     private final Kind wordKind;
     private final Stamp wordStamp;
-    private final ResolvedJavaType wordType;
 
-    public WordTypeRewriterPhase(Kind wordKind, Stamp wordStamp, ResolvedJavaType wordType) {
+    public WordTypeRewriterPhase(Kind wordKind, Stamp wordStamp) {
         this.wordKind = wordKind;
-        this.wordType = wordType;
         this.wordStamp = wordStamp;
     }
 
@@ -169,9 +167,7 @@
                     case W2A: {
                         assert arguments.size() == 1;
                         ValueNode value = arguments.first();
-                        ResolvedJavaType declaringClass = targetMethod.getDeclaringClass();
-                        ResolvedJavaType targetType = targetMethod.getSignature().getReturnType(declaringClass).resolve(declaringClass);
-                        UnsafeCastNode cast = graph.unique(new UnsafeCastNode(value, targetType));
+                        UnsafeCastNode cast = graph.unique(new UnsafeCastNode(value, ((ValueNode) invoke).stamp()));
                         replace(invoke, cast);
                         break;
                     }
@@ -196,7 +192,7 @@
                         assert arguments.size() == 1;
                         ValueNode value = arguments.first();
                         assert value.kind() == Kind.Object : value + ", " + targetMethod;
-                        UnsafeCastNode cast = graph.unique(new UnsafeCastNode(value, wordType));
+                        UnsafeCastNode cast = graph.unique(new UnsafeCastNode(value, wordStamp));
                         replace(invoke, cast);
                         break;
                     }