< prev index next >
src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java
Print this page
@@ -165,13 +165,29 @@
return javaComponentType == null ? null : runtime().fromClass(javaComponentType);
}
@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();
/*
* If the implementor field contains itself that indicates that the interface has more
* than one implementors (see: InstanceKlass::add_implementor).
@@ -190,12 +206,11 @@
newResult.add(leafConcreteSubtype);
return newResult;
}
return null;
}
-
- return new AssumptionResult<>(implementor, new LeafType(implementor), new ConcreteSubtype(this, implementor));
+ return concreteSubtype(implementor);
} else {
HotSpotResolvedObjectTypeImpl type = this;
while (type.isAbstract()) {
HotSpotResolvedObjectTypeImpl subklass = type.getSubklass();
if (subklass == null || UNSAFE.getAddress(subklass.getMetaspaceKlass() + config.nextSiblingOffset) != 0) {
@@ -205,18 +220,26 @@
}
if (type.isAbstract() || type.isInterface() || !type.isLeafClass()) {
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));
}
}
}
+ 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.
*
* @return true if the type is a leaf class
< prev index next >