8155047: [JVMCI] findLeafConcreteSubtype should handle arrays of leaf concrete subtype
Reviewed-by: twisti
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Thu May 12 18:11:14 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Thu May 12 22:06:55 2016 +0000
@@ -166,9 +166,25 @@
@Override
public AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
+ if (isLeaf()) {
+ // No assumptions are required.
+ return new AssumptionResult<>(this);
+ }
HotSpotVMConfig config = config();
if (isArray()) {
- return getElementalType().isLeaf() ? new AssumptionResult<>(this) : null;
+ ResolvedJavaType elementalType = getElementalType();
+ AssumptionResult<ResolvedJavaType> elementType = elementalType.findLeafConcreteSubtype();
+ if (elementType != null && elementType.getResult().equals(elementalType)) {
+ /*
+ * If the elementType is leaf then the array is leaf under the same assumptions but
+ * only if the element type is exactly the leaf type. The element type can be
+ * abstract even if there is only one implementor of the abstract type.
+ */
+ AssumptionResult<ResolvedJavaType> result = new AssumptionResult<>(this);
+ result.add(elementType);
+ return result;
+ }
+ return null;
} else if (isInterface()) {
HotSpotResolvedObjectTypeImpl implementor = getSingleImplementor();
/*
@@ -191,8 +207,7 @@
}
return null;
}
-
- return new AssumptionResult<>(implementor, new LeafType(implementor), new ConcreteSubtype(this, implementor));
+ return concreteSubtype(implementor);
} else {
HotSpotResolvedObjectTypeImpl type = this;
while (type.isAbstract()) {
@@ -206,7 +221,7 @@
return null;
}
if (this.isAbstract()) {
- return new AssumptionResult<>(type, new LeafType(type), new ConcreteSubtype(this, type));
+ return concreteSubtype(type);
} else {
assert this.equals(type);
return new AssumptionResult<>(type, new LeafType(type));
@@ -214,6 +229,14 @@
}
}
+ private AssumptionResult<ResolvedJavaType> concreteSubtype(HotSpotResolvedObjectTypeImpl type) {
+ if (type.isLeaf()) {
+ return new AssumptionResult<>(type, new ConcreteSubtype(this, type));
+ } else {
+ return new AssumptionResult<>(type, new LeafType(type), new ConcreteSubtype(this, type));
+ }
+ }
+
/**
* Returns if type {@code type} is a leaf class. This is the case if the
* {@code Klass::_subklass} field of the underlying class is zero.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java Thu May 12 18:11:14 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java Thu May 12 22:06:55 2016 +0000
@@ -44,7 +44,10 @@
/**
* A class for providing information that is only valid in association with a set of
- * {@link Assumption}s.
+ * {@link Assumption}s. It is permissible for AssumptionResults to have no assumptions at all.
+ * For instance, if {@link ResolvedJavaType#isLeaf()} returns true for a type
+ * {@link ResolvedJavaType#findLeafConcreteSubtype()} can return an AssumptionResult with no
+ * assumptions since the leaf information is statically true.
*
* @param <T>
*/
@@ -187,6 +190,7 @@
public final ResolvedJavaType context;
public LeafType(ResolvedJavaType context) {
+ assert !context.isLeaf() : "assumption isn't required for leaf types";
this.context = context;
}
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java Thu May 12 18:11:14 2016 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java Thu May 12 22:06:55 2016 +0000
@@ -328,6 +328,7 @@
} else {
assertTrue(leafConcreteSubtype.getResult().equals(expected));
}
+ assertTrue(!type.isLeaf() || leafConcreteSubtype.isAssumptionFree());
}
if (!type.isArray()) {
@@ -372,8 +373,10 @@
ResolvedJavaType a1a = metaAccess.lookupJavaType(Abstract1[].class);
checkConcreteSubtype(a1a, null);
+ ResolvedJavaType i1a = metaAccess.lookupJavaType(Interface1[].class);
+ checkConcreteSubtype(i1a, null);
ResolvedJavaType c1a = metaAccess.lookupJavaType(Concrete1[].class);
- checkConcreteSubtype(c1a, null);
+ checkConcreteSubtype(c1a, c1a);
ResolvedJavaType f1a = metaAccess.lookupJavaType(Final1[].class);
checkConcreteSubtype(f1a, f1a);