# HG changeset patch # User Doug Simon # Date 1340371183 -7200 # Node ID 0ca242de93836392bcdf61ed85cc2fad62febf6f # Parent f787843c890ca0b62325052f06dcc3f7b96d4040 improved type stamp for value flowing out of a lowered NEW bytecode instruction removed declaredType() and exactType() from Stamp diff -r f787843c890c -r 0ca242de9383 graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ArrayTypeElement.java --- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ArrayTypeElement.java Fri Jun 22 10:43:06 2012 +0200 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ArrayTypeElement.java Fri Jun 22 15:19:43 2012 +0200 @@ -48,14 +48,14 @@ @Override protected void propagateTypesToUsage(BigBang bb, Node use, Set set, Element element) { LoadIndexedNode load = (LoadIndexedNode) use; - ResolvedJavaType declaredType = load.array().stamp().declaredType(); - if (declaredType == null) { - System.out.println("FATAL error: Array access without declared type!"); + ResolvedJavaType type = load.array().objectStamp().type(); + if (type == null) { + System.out.println("FATAL error: Array access without type!"); System.out.println(load.array()); System.out.println(((StructuredGraph) load.graph()).method()); System.exit(-1); } - ResolvedJavaType componentType = declaredType.componentType(); + ResolvedJavaType componentType = type.componentType(); Set newSet = new HashSet<>(); for (ResolvedJavaType myType : set) { if (myType.isSubtypeOf(componentType)) { diff -r f787843c890c -r 0ca242de9383 graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/InvokeElement.java --- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/InvokeElement.java Fri Jun 22 10:43:06 2012 +0200 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/InvokeElement.java Fri Jun 22 15:19:43 2012 +0200 @@ -51,7 +51,7 @@ int index = 0; for (Node arg : methodCallTarget.arguments()) { if (arg == sourceNode) { - System.out.println("source node " + sourceNode + " is at index " + index + " declaredType=" + ((ValueNode) sourceNode).stamp().declaredType()); + System.out.println("source node " + sourceNode + " is at index " + index + " stamp=" + ((ValueNode) sourceNode).stamp()); unionTypes(bb, sourceNode, newSeenTypes, index); } ++index; diff -r f787843c890c -r 0ca242de9383 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CastFromHub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CastFromHub.java Fri Jun 22 15:19:43 2012 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009, 2011, 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.hotspot.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.snippets.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * This node is used by the {@link NewInstanceSnippets} to give a formatted new instance its exact type. + */ +public final class CastFromHub extends FloatingNode implements Canonicalizable { + + @Input private ValueNode object; + @Input private ValueNode hub; + + public ValueNode object() { + return object; + } + + public CastFromHub(ValueNode object, ValueNode hubObject) { + // TODO: the non-nullness should really be derived from 'object' but until + // control flow sensitive type analysis is implemented, the object coming + // from the TLAB fast path is not non-null + super(StampFactory.objectNonNull()); + this.object = object; + this.hub = hubObject; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (hub.isConstant()) { + ResolvedJavaType type = ((HotSpotKlassOop) this.hub.asConstant().asObject()).type; + return graph().unique(new UnsafeCastNode(object, type, true, true)); + } + return this; + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static T castFromHub(Object object, Object hub) { + throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler"); + } +} diff -r f787843c890c -r 0ca242de9383 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Fri Jun 22 10:43:06 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Fri Jun 22 15:19:43 2012 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.snippets; +import static com.oracle.graal.hotspot.nodes.CastFromHub.*; import static com.oracle.graal.hotspot.nodes.RegisterNode.*; import static com.oracle.graal.hotspot.snippets.DirectObjectStoreNode.*; import static com.oracle.graal.nodes.extended.UnsafeLoadNode.*; @@ -74,9 +75,9 @@ if (memory == Word.zero()) { return NewInstanceStubCall.call(hub); } + formatObject(hub, size, memory); Object instance = memory.toObject(); - formatInstance(hub, size, instance); - return verifyOop(instance); + return castFromHub(verifyOop(instance), hub); } private static Object verifyOop(Object object) { @@ -101,15 +102,15 @@ } /** - * Formats the header of a created instance and zeroes out its body. + * Formats some allocated memory with an object header zeroes out the rest. */ - private static void formatInstance(Object hub, int size, Object instance) { + private static void formatObject(Object hub, int size, Word memory) { Word headerPrototype = loadWord(hub, instanceHeaderPrototypeOffset()); - store(instance, 0, 0, headerPrototype); - store(instance, 0, hubOffset(), hub); + store(memory, 0, 0, headerPrototype); + store(memory, 0, hubOffset(), hub); explodeLoop(); for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { - store(instance, 0, offset, 0); + store(memory, 0, offset, 0); } } diff -r f787843c890c -r 0ca242de9383 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 Fri Jun 22 10:43:06 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Fri Jun 22 15:19:43 2012 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; -import com.oracle.graal.cri.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -32,7 +31,7 @@ /** * The {@code UnsafeCastNode} produces the same value as its input, but with a different type. */ -public final class UnsafeCastNode extends FloatingNode implements Canonicalizable, Lowerable, LIRLowerable { +public final class UnsafeCastNode extends FloatingNode implements Canonicalizable, LIRLowerable { @Input private ValueNode object; private ResolvedJavaType toType; @@ -41,6 +40,12 @@ return object; } + public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { + super(toType.kind().isObject() ? new ObjectStamp(toType, exactType, nonNull) : StampFactory.forKind(toType.kind())); + this.object = object; + this.toType = toType; + } + public UnsafeCastNode(ValueNode object, ResolvedJavaType toType) { super(toType.kind().isObject() ? StampFactory.declared(toType, object.stamp().nonNull()) : StampFactory.forKind(toType.kind())); this.object = object; @@ -49,20 +54,35 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - if (object != null && object.kind().isObject() && object.objectStamp().type() != null && object.objectStamp().type().isSubtypeOf(toType)) { - return object; + 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; + } } return this; } - - @Override - public void lower(CiLoweringTool tool) { - if (object.kind() == kind()) { - ((StructuredGraph) graph()).replaceFloating(this, object); - } else { - // Cannot remove an unsafe cast between two different kinds + /** + * 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; } + if (x.isExactType() && !y.isExactType()) { + return true; + } + return false; } @SuppressWarnings("unused") @@ -71,6 +91,12 @@ throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler"); } + @SuppressWarnings("unused") + @NodeIntrinsic + public static T cast(Object object, @ConstantNodeParameter Class toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull) { + throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler"); + } + @Override public void generate(LIRGeneratorTool generator) { Value result = generator.newVariable(kind()); diff -r f787843c890c -r 0ca242de9383 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Fri Jun 22 10:43:06 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Fri Jun 22 15:19:43 2012 +0200 @@ -53,16 +53,6 @@ } @Override - public ResolvedJavaType exactType() { - return exactType ? type : null; - } - - @Override - public ResolvedJavaType declaredType() { - return type; - } - - @Override public String toString() { StringBuilder str = new StringBuilder(); str.append(kind().typeChar); diff -r f787843c890c -r 0ca242de9383 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java Fri Jun 22 10:43:06 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java Fri Jun 22 15:19:43 2012 +0200 @@ -25,7 +25,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.spi.types.*; - +/** + * A stamp is the basis for a type system over the nodes in a graph. + */ public abstract class Stamp { private final Kind kind; @@ -50,14 +52,6 @@ return false; } - public ResolvedJavaType exactType() { - return null; - } - - public ResolvedJavaType declaredType() { - return null; - } - public abstract boolean alwaysDistinct(Stamp other); public abstract Stamp meet(Stamp other); diff -r f787843c890c -r 0ca242de9383 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 Fri Jun 22 10:43:06 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java Fri Jun 22 15:19:43 2012 +0200 @@ -236,7 +236,10 @@ } public static boolean isWord(ValueNode node) { - return isWord(node.stamp().declaredType()); + if (node.kind().isObject()) { + return isWord(node.objectStamp().type()); + } + return false; } public static boolean isWord(ResolvedJavaType type) {