changeset 19796:deab43a789ad

Split LeafType off from ConcreteSubtype
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Wed, 11 Mar 2015 17:45:21 -0700
parents 3362ba500371
children 4545e180658c
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Assumptions.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectTypeImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalCodeInstaller.hpp src/share/vm/graal/graalJavaAccess.hpp
diffstat 19 files changed, 144 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Wed Mar 11 17:45:21 2015 -0700
@@ -97,10 +97,10 @@
             exact = targetType;
         } else {
             if (assumptions != null) {
-                AssumptionResult<ResolvedJavaType> uniqueSubtype = targetType == null ? null : targetType.findUniqueConcreteSubtype();
-                if (uniqueSubtype != null) {
-                    assumptions.record(uniqueSubtype);
-                    exact = uniqueSubtype.getResult();
+                AssumptionResult<ResolvedJavaType> leafConcreteSubtype = targetType == null ? null : targetType.findLeafConcreteSubtype();
+                if (leafConcreteSubtype != null) {
+                    assumptions.record(leafConcreteSubtype);
+                    exact = leafConcreteSubtype.getResult();
                 } else {
                     exact = null;
                 }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Wed Mar 11 17:45:21 2015 -0700
@@ -274,30 +274,30 @@
     }
 
     void checkConcreteSubtype(ResolvedJavaType type, ResolvedJavaType expected) {
-        AssumptionResult<ResolvedJavaType> subtype = type.findUniqueConcreteSubtype();
-        if (subtype == null) {
-            // findUniqueConcreteSubtype() is conservative
+        AssumptionResult<ResolvedJavaType> leafConcreteSubtype = type.findLeafConcreteSubtype();
+        if (leafConcreteSubtype == null) {
+            // findLeafConcreteSubtype() is conservative
         } else {
             if (expected == null) {
-                assertNull(subtype);
+                assertNull(leafConcreteSubtype);
             } else {
-                assertTrue(subtype.getResult().equals(expected));
+                assertTrue(leafConcreteSubtype.getResult().equals(expected));
             }
         }
 
         if (!type.isArray()) {
             ResolvedJavaType arrayType = type.getArrayClass();
-            AssumptionResult<ResolvedJavaType> arraySubtype = arrayType.findUniqueConcreteSubtype();
+            AssumptionResult<ResolvedJavaType> arraySubtype = arrayType.findLeafConcreteSubtype();
             if (arraySubtype != null) {
                 assertEquals(arraySubtype.getResult(), arrayType);
             } else {
-                // findUniqueConcreteSubtype() method is conservative
+                // findLeafConcreteSubtype() method is conservative
             }
         }
     }
 
     @Test
-    public void findUniqueConcreteSubtypeTest() {
+    public void findLeafConcreteSubtypeTest() {
         ResolvedJavaType base = metaAccess.lookupJavaType(Base.class);
         checkConcreteSubtype(base, base);
 
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Assumptions.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Assumptions.java	Wed Mar 11 17:45:21 2015 -0700
@@ -110,7 +110,8 @@
     }
 
     /**
-     * An assumption that a given type has a given unique subtype.
+     * An assumption that a given abstract or interface type has one direct concrete subtype. There
+     * is no requirement that the subtype is a leaf type.
      */
     public static final class ConcreteSubtype extends Assumption {
 
@@ -122,14 +123,15 @@
         public final ResolvedJavaType context;
 
         /**
-         * Assumed unique concrete sub-type of the context type.
+         * Assumed concrete sub-type of the context type.
          */
         public final ResolvedJavaType subtype;
 
         public ConcreteSubtype(ResolvedJavaType context, ResolvedJavaType subtype) {
             this.context = context;
             this.subtype = subtype;
-            assert subtype.isConcrete() : subtype.toString() + " : " + context.toString();
+            assert context.isAbstract();
+            assert subtype.isConcrete() || context.isInterface() : subtype.toString() + " : " + context.toString();
             assert !subtype.isArray() || subtype.getElementalType().isFinal() : subtype.toString() + " : " + context.toString();
         }
 
@@ -158,6 +160,45 @@
     }
 
     /**
+     * An assumption that a given type has no subtypes.
+     */
+    public static final class LeafType extends Assumption {
+
+        private static final long serialVersionUID = -1457173265437676252L;
+
+        /**
+         * Type the assumption is made about.
+         */
+        public final ResolvedJavaType context;
+
+        public LeafType(ResolvedJavaType context) {
+            this.context = context;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + context.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof LeafType) {
+                LeafType other = (LeafType) obj;
+                return other.context.equals(context);
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "LeafSubtype[context=" + context.toJavaName() + "]";
+        }
+    }
+
+    /**
      * An assumption that a given virtual method has a given unique implementation.
      */
     public static final class ConcreteMethod extends Assumption {
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Wed Mar 11 17:45:21 2015 -0700
@@ -186,25 +186,27 @@
     ResolvedJavaType findLeastCommonAncestor(ResolvedJavaType otherType);
 
     /**
-     * Attempts to get a unique concrete subclass of this type.
+     * Attempts to get a leaf concrete subclass of this type.
      * <p>
-     * For an {@linkplain #isArray() array} type A, the unique concrete subclass is A if the
+     * For an {@linkplain #isArray() array} type A, the leaf concrete subclass is A if the
      * {@linkplain #getElementalType() elemental} type of A is final (which includes primitive
      * types). Otherwise {@code null} is returned for A.
      * <p>
-     * For a non-array type T, the result is the unique concrete type in the current hierarchy of T.
+     * For a non-array type T, the result is the leaf concrete type in the current hierarchy of T.
      * <p>
      * A runtime may decide not to manage or walk a large hierarchy and so the result is
-     * conservative. That is, a non-null result is guaranteed to be the unique concrete class in T's
+     * conservative. That is, a non-null result is guaranteed to be the leaf concrete class in T's
      * hierarchy <b>at the current point in time</b> but a null result does not necessarily imply
-     * that there is no unique concrete class in T's hierarchy.
+     * that there is no leaf concrete class in T's hierarchy.
      * <p>
-     * If the compiler uses the result of this method for its compilation, it must register an
-     * assumption because dynamic class loading can invalidate the result of this method.
+     * If the compiler uses the result of this method for its compilation, it must register the
+     * {@link AssumptionResult} in its {@link Assumptions} because dynamic class loading can
+     * invalidate the result of this method.
      *
-     * @return the unique concrete subclass for this type as described above
+     * @return an {@link AssumptionResult} containing the leaf concrete subclass for this type as
+     *         described above
      */
-    AssumptionResult<ResolvedJavaType> findUniqueConcreteSubtype();
+    AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype();
 
     ResolvedJavaType getComponentType();
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Wed Mar 11 17:45:21 2015 -0700
@@ -35,7 +35,7 @@
 
     ResolvedJavaType getComponentType();
 
-    AssumptionResult<ResolvedJavaType> findUniqueConcreteSubtype();
+    AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype();
 
     HotSpotResolvedObjectType getSuperclass();
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectTypeImpl.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectTypeImpl.java	Wed Mar 11 17:45:21 2015 -0700
@@ -33,7 +33,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.Assumptions.AssumptionResult;
+import com.oracle.graal.api.meta.Assumptions.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 
@@ -140,25 +140,33 @@
     }
 
     @Override
-    public AssumptionResult<ResolvedJavaType> findUniqueConcreteSubtype() {
+    public AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
         HotSpotVMConfig config = runtime().getConfig();
         if (isArray()) {
             return getElementalType().isFinal() ? new AssumptionResult<>(this) : null;
         } else if (isInterface()) {
-            HotSpotResolvedObjectTypeImpl type = getSingleImplementor();
-            if (type == null) {
+            HotSpotResolvedObjectTypeImpl implementor = getSingleImplementor();
+            /*
+             * If the implementor field contains itself that indicates that the interface has more
+             * than one implementors (see: InstanceKlass::add_implementor).
+             */
+            if (implementor == null || implementor.equals(this)) {
                 return null;
             }
 
-            /*
-             * If the implementor field contains itself that indicates that the interface has more
-             * than one implementors (see: InstanceKlass::add_implementor). The isInterface check
-             * takes care of this fact since this class is an interface.
-             */
-            if (type.isAbstract() || type.isInterface() || !type.isLeafClass()) {
+            assert !implementor.isInterface();
+            if (implementor.isAbstract() || !implementor.isLeafClass()) {
+                AssumptionResult<ResolvedJavaType> leafConcreteSubtype = implementor.findLeafConcreteSubtype();
+                if (leafConcreteSubtype != null) {
+                    assert !leafConcreteSubtype.getResult().equals(implementor);
+                    AssumptionResult<ResolvedJavaType> newResult = new AssumptionResult<>(leafConcreteSubtype.getResult(), new ConcreteSubtype(this, implementor));
+                    newResult.add(leafConcreteSubtype);
+                    return leafConcreteSubtype;
+                }
                 return null;
             }
-            return new AssumptionResult<>(type, new Assumptions.ConcreteSubtype(this, type));
+
+            return new AssumptionResult<>(implementor, new LeafType(implementor), new ConcreteSubtype(this, implementor));
         } else {
             HotSpotResolvedObjectTypeImpl type = this;
             while (type.isAbstract()) {
@@ -171,7 +179,12 @@
             if (type.isAbstract() || type.isInterface() || !type.isLeafClass()) {
                 return null;
             }
-            return new AssumptionResult<>(type, new Assumptions.ConcreteSubtype(this, type));
+            if (this.isAbstract()) {
+                return new AssumptionResult<>(type, new LeafType(type), new ConcreteSubtype(this, type));
+            } else {
+                assert this.equals(type);
+                return new AssumptionResult<>(type, new LeafType(type));
+            }
         }
     }
 
@@ -285,7 +298,7 @@
     public AssumptionResult<Boolean> hasFinalizableSubclass() {
         assert !isArray();
         if (!runtime().getCompilerToVM().hasFinalizableSubclass(getMetaspaceKlass())) {
-            return new AssumptionResult<>(false, new Assumptions.NoFinalizableSubclass(this));
+            return new AssumptionResult<>(false, new NoFinalizableSubclass(this));
         }
         return new AssumptionResult<>(true);
     }
@@ -509,7 +522,7 @@
         if (!declaredHolder.isAssignableFrom(this) || this.isArray() || this.equals(declaredHolder) || !isLinked() || isInterface()) {
             ResolvedJavaMethod result = hmethod.uniqueConcreteMethod(declaredHolder);
             if (result != null) {
-                return new AssumptionResult<>(result, new Assumptions.ConcreteMethod(method, declaredHolder, result));
+                return new AssumptionResult<>(result, new ConcreteMethod(method, declaredHolder, result));
             }
             return null;
         }
@@ -525,7 +538,7 @@
 
         ResolvedJavaMethod result = resolvedMethod.uniqueConcreteMethod(this);
         if (result != null) {
-            return new AssumptionResult<>(result, new Assumptions.ConcreteMethod(method, this, result));
+            return new AssumptionResult<>(result, new ConcreteMethod(method, this, result));
         }
         return null;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java	Wed Mar 11 17:45:21 2015 -0700
@@ -191,7 +191,7 @@
     }
 
     @Override
-    public AssumptionResult<ResolvedJavaType> findUniqueConcreteSubtype() {
+    public AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
         return new AssumptionResult<>(this);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Wed Mar 11 17:45:21 2015 -0700
@@ -99,8 +99,8 @@
             }
         } else if (StampTool.typeOrNull(forValue) != null) {
             ResolvedJavaType type = StampTool.typeOrNull(forValue);
-            AssumptionResult<ResolvedJavaType> uniqueConcrete = type.findUniqueConcreteSubtype();
-            if (uniqueConcrete != null) {
+            AssumptionResult<ResolvedJavaType> leafConcreteSubtype = type.findLeafConcreteSubtype();
+            if (leafConcreteSubtype != null) {
                 // Profile is useless => remove.
                 Debug.log("Profile useless, there is enough static type information available.");
                 return forValue;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Wed Mar 11 17:45:21 2015 -0700
@@ -77,10 +77,10 @@
             if (objectStamp.isExactType()) {
                 exactType = objectStamp.type();
             } else if (objectStamp.type() != null && graph().getAssumptions() != null) {
-                AssumptionResult<ResolvedJavaType> typeResult = objectStamp.type().findUniqueConcreteSubtype();
-                if (typeResult != null) {
-                    exactType = typeResult.getResult();
-                    graph().getAssumptions().record(typeResult);
+                AssumptionResult<ResolvedJavaType> leafConcreteSubtype = objectStamp.type().findLeafConcreteSubtype();
+                if (leafConcreteSubtype != null) {
+                    exactType = leafConcreteSubtype.getResult();
+                    graph().getAssumptions().record(leafConcreteSubtype);
                 }
             }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Wed Mar 11 17:45:21 2015 -0700
@@ -72,10 +72,10 @@
         }
         assert object.stamp() instanceof ObjectStamp : object + ":" + object.stamp();
         if (assumptions != null) {
-            AssumptionResult<ResolvedJavaType> uniqueConcreteType = type.findUniqueConcreteSubtype();
-            if (uniqueConcreteType != null && !uniqueConcreteType.getResult().equals(type)) {
-                assumptions.record(uniqueConcreteType);
-                type = uniqueConcreteType.getResult();
+            AssumptionResult<ResolvedJavaType> leafConcreteSubtype = type.findLeafConcreteSubtype();
+            if (leafConcreteSubtype != null && !leafConcreteSubtype.getResult().equals(type)) {
+                assumptions.record(leafConcreteSubtype);
+                type = leafConcreteSubtype.getResult();
             }
         }
         return new CheckCastNode(type, object, profile, forStoreCheck);
@@ -170,11 +170,11 @@
 
         Assumptions assumptions = graph().getAssumptions();
         if (assumptions != null) {
-            AssumptionResult<ResolvedJavaType> exactTypeResult = type.findUniqueConcreteSubtype();
-            if (exactTypeResult != null && !exactTypeResult.getResult().equals(type)) {
+            AssumptionResult<ResolvedJavaType> leafConcreteSubtype = type.findLeafConcreteSubtype();
+            if (leafConcreteSubtype != null && !leafConcreteSubtype.getResult().equals(type)) {
                 // Propagate more precise type information to usages of the checkcast.
-                assumptions.record(exactTypeResult);
-                return new CheckCastNode(exactTypeResult.getResult(), object, profile, forStoreCheck);
+                assumptions.record(leafConcreteSubtype);
+                return new CheckCastNode(leafConcreteSubtype.getResult(), object, profile, forStoreCheck);
             }
         }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Wed Mar 11 17:45:21 2015 -0700
@@ -82,11 +82,11 @@
             }
             Assumptions assumptions = graph().getAssumptions();
             if (assumptions != null) {
-                AssumptionResult<ResolvedJavaType> typeResult = stampType.findUniqueConcreteSubtype();
-                if (typeResult != null) {
-                    result = checkInstanceOf(forValue, typeResult.getResult(), objectStamp.nonNull(), true);
+                AssumptionResult<ResolvedJavaType> leafConcreteSubtype = stampType.findLeafConcreteSubtype();
+                if (leafConcreteSubtype != null) {
+                    result = checkInstanceOf(forValue, leafConcreteSubtype.getResult(), objectStamp.nonNull(), true);
                     if (result != null) {
-                        assumptions.record(typeResult);
+                        assumptions.record(leafConcreteSubtype);
                         return result;
                     }
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java	Wed Mar 11 17:45:21 2015 -0700
@@ -126,11 +126,11 @@
             }
             Assumptions assumptions = receiver.graph().getAssumptions();
             if (assumptions != null) {
-                AssumptionResult<ResolvedJavaType> uniqueConcreteType = type.findUniqueConcreteSubtype();
-                if (uniqueConcreteType != null) {
-                    ResolvedJavaMethod methodFromUniqueType = uniqueConcreteType.getResult().resolveConcreteMethod(targetMethod, contextType);
+                AssumptionResult<ResolvedJavaType> leafConcreteSubtype = type.findLeafConcreteSubtype();
+                if (leafConcreteSubtype != null) {
+                    ResolvedJavaMethod methodFromUniqueType = leafConcreteSubtype.getResult().resolveConcreteMethod(targetMethod, contextType);
                     if (methodFromUniqueType != null) {
-                        assumptions.record(uniqueConcreteType);
+                        assumptions.record(leafConcreteSubtype);
                         return methodFromUniqueType;
                     }
                 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningData.java	Wed Mar 11 17:45:21 2015 -0700
@@ -195,11 +195,11 @@
         }
 
         if (callTarget.graph().getAssumptions() != null) {
-            AssumptionResult<ResolvedJavaType> uniqueSubtype = holder.findUniqueConcreteSubtype();
-            if (uniqueSubtype != null) {
-                ResolvedJavaMethod resolvedMethod = uniqueSubtype.getResult().resolveConcreteMethod(targetMethod, contextType);
+            AssumptionResult<ResolvedJavaType> leafConcreteSubtype = holder.findLeafConcreteSubtype();
+            if (leafConcreteSubtype != null) {
+                ResolvedJavaMethod resolvedMethod = leafConcreteSubtype.getResult().resolveConcreteMethod(targetMethod, contextType);
                 if (resolvedMethod != null) {
-                    return getAssumptionInlineInfo(invoke, resolvedMethod, uniqueSubtype);
+                    return getAssumptionInlineInfo(invoke, resolvedMethod, leafConcreteSubtype);
                 }
             }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java	Wed Mar 11 17:32:04 2015 -0700
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java	Wed Mar 11 17:45:21 2015 -0700
@@ -77,10 +77,10 @@
         } else if (objectStamp.isExactType()) {
             return isCloneableType(objectStamp.type(), metaAccess) ? objectStamp.type() : null;
         } else {
-            AssumptionResult<ResolvedJavaType> typeResult = objectStamp.type().findUniqueConcreteSubtype();
-            if (typeResult != null && isCloneableType(typeResult.getResult(), metaAccess)) {
-                assumptions.record(typeResult);
-                return typeResult.getResult();
+            AssumptionResult<ResolvedJavaType> leafConcreteSubtype = objectStamp.type().findLeafConcreteSubtype();
+            if (leafConcreteSubtype != null && isCloneableType(leafConcreteSubtype.getResult(), metaAccess)) {
+                assumptions.record(leafConcreteSubtype);
+                return leafConcreteSubtype.getResult();
             } else {
                 return null;
             }
--- a/src/share/vm/classfile/systemDictionary.hpp	Wed Mar 11 17:32:04 2015 -0700
+++ b/src/share/vm/classfile/systemDictionary.hpp	Wed Mar 11 17:45:21 2015 -0700
@@ -207,6 +207,7 @@
   GRAAL_ONLY(do_klass(Assumptions_ConcreteMethod_klass,      com_oracle_graal_api_meta_Assumptions_ConcreteMethod,         Graal)) \
   GRAAL_ONLY(do_klass(Assumptions_NoFinalizableSubclass_klass, com_oracle_graal_api_meta_Assumptions_NoFinalizableSubclass, Graal))\
   GRAAL_ONLY(do_klass(Assumptions_ConcreteSubtype_klass,     com_oracle_graal_api_meta_Assumptions_ConcreteSubtype,        Graal)) \
+  GRAAL_ONLY(do_klass(Assumptions_LeafType_klass,            com_oracle_graal_api_meta_Assumptions_LeafType,               Graal)) \
   GRAAL_ONLY(do_klass(Assumptions_CallSiteTargetValue_klass, com_oracle_graal_api_meta_Assumptions_CallSiteTargetValue,    Graal)) \
   GRAAL_ONLY(do_klass(BytecodePosition_klass,                com_oracle_graal_api_code_BytecodePosition,                   Graal)) \
   GRAAL_ONLY(do_klass(DebugInfo_klass,                       com_oracle_graal_api_code_DebugInfo,                          Graal)) \
--- a/src/share/vm/classfile/vmSymbols.hpp	Wed Mar 11 17:32:04 2015 -0700
+++ b/src/share/vm/classfile/vmSymbols.hpp	Wed Mar 11 17:45:21 2015 -0700
@@ -322,6 +322,7 @@
   GRAAL_ONLY(template(com_oracle_graal_api_meta_LIRKind,                        "com/oracle/graal/api/meta/LIRKind"))                             \
   GRAAL_ONLY(template(com_oracle_graal_api_meta_AbstractValue,                  "com/oracle/graal/api/meta/AbstractValue"))                       \
   GRAAL_ONLY(template(com_oracle_graal_api_meta_Assumptions_ConcreteSubtype,    "com/oracle/graal/api/meta/Assumptions$ConcreteSubtype"))         \
+  GRAAL_ONLY(template(com_oracle_graal_api_meta_Assumptions_LeafType,           "com/oracle/graal/api/meta/Assumptions$LeafType"))                \
   GRAAL_ONLY(template(com_oracle_graal_api_meta_Assumptions_NoFinalizableSubclass, "com/oracle/graal/api/meta/Assumptions$NoFinalizableSubclass")) \
   GRAAL_ONLY(template(com_oracle_graal_api_meta_Assumptions_ConcreteMethod,     "com/oracle/graal/api/meta/Assumptions$ConcreteMethod"))          \
   GRAAL_ONLY(template(com_oracle_graal_api_meta_Assumptions_CallSiteTargetValue,"com/oracle/graal/api/meta/Assumptions$CallSiteTargetValue"))     \
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Wed Mar 11 17:32:04 2015 -0700
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Wed Mar 11 17:45:21 2015 -0700
@@ -400,6 +400,8 @@
           assumption_NoFinalizableSubclass(assumption);
         } else if (assumption->klass() == Assumptions_ConcreteSubtype::klass()) {
           assumption_ConcreteSubtype(assumption);
+        } else if (assumption->klass() == Assumptions_LeafType::klass()) {
+          assumption_LeafType(assumption);
         } else if (assumption->klass() == Assumptions_ConcreteMethod::klass()) {
           assumption_ConcreteMethod(assumption);
         } else if (assumption->klass() == Assumptions_CallSiteTargetValue::klass()) {
@@ -658,11 +660,15 @@
   Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
   Klass* subtype = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(subtype_handle));
 
-  if (context != subtype) {
-    assert(context->is_abstract(), "");
-    _dependencies->assert_abstract_with_unique_concrete_subtype(context, subtype);
-  }
-  _dependencies->assert_leaf_type(subtype);
+  assert(context->is_abstract(), "");
+  _dependencies->assert_abstract_with_unique_concrete_subtype(context, subtype);
+}
+
+void CodeInstaller::assumption_LeafType(Handle assumption) {
+  Handle context_handle = Assumptions_LeafType::context(assumption());
+  Klass* context = java_lang_Class::as_Klass(HotSpotResolvedObjectTypeImpl::javaClass(context_handle));
+
+  _dependencies->assert_leaf_type(context);
 }
 
 void CodeInstaller::assumption_ConcreteMethod(Handle assumption) {
--- a/src/share/vm/graal/graalCodeInstaller.hpp	Wed Mar 11 17:32:04 2015 -0700
+++ b/src/share/vm/graal/graalCodeInstaller.hpp	Wed Mar 11 17:45:21 2015 -0700
@@ -131,6 +131,7 @@
 
   void assumption_NoFinalizableSubclass(Handle assumption);
   void assumption_ConcreteSubtype(Handle assumption);
+  void assumption_LeafType(Handle assumption);
   void assumption_ConcreteMethod(Handle assumption);
   void assumption_CallSiteTargetValue(Handle assumption);
 
--- a/src/share/vm/graal/graalJavaAccess.hpp	Wed Mar 11 17:32:04 2015 -0700
+++ b/src/share/vm/graal/graalJavaAccess.hpp	Wed Mar 11 17:45:21 2015 -0700
@@ -108,6 +108,9 @@
     oop_field(Assumptions_ConcreteSubtype, context, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                            \
     oop_field(Assumptions_ConcreteSubtype, subtype, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                            \
   end_class                                                                                                                                                    \
+  start_class(Assumptions_LeafType)                                                                                                                            \
+    oop_field(Assumptions_LeafType, context, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                                   \
+  end_class                                                                                                                                                    \
   start_class(Assumptions_ConcreteMethod)                                                                                                                      \
     oop_field(Assumptions_ConcreteMethod, method, "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;")                                                            \
     oop_field(Assumptions_ConcreteMethod, context, "Lcom/oracle/graal/api/meta/ResolvedJavaType;")                                                             \