# HG changeset patch # User Christian Wimmer # Date 1353982634 28800 # Node ID 2e577202843c690bd210c2c6cd06726a23aea013 # Parent d78c83e8b70b221fd8117382e5dd07f3f74d530f Better implementation of UnsafeCastNode diff -r d78c83e8b70b -r 2e577202843c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- 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 cast(Object object, @ConstantNodeParameter Class toType); + public static native T unsafeCast(Object object, @ConstantNodeParameter Stamp stamp); @NodeIntrinsic - public static native 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 unsafeCast(Object object, @ConstantNodeParameter Class toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull); } diff -r d78c83e8b70b -r 2e577202843c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java --- 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); } } diff -r d78c83e8b70b -r 2e577202843c graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/NodeClassSnippets.java --- 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 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) { diff -r d78c83e8b70b -r 2e577202843c graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java --- 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) { diff -r d78c83e8b70b -r 2e577202843c graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java --- 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; }