Leverage that most type elements have default interfaces in subtyping checks
Bug: b/422947619
Bug: b/424006396
Change-Id: If87cf909c530f3797d862ff23d4bf9d698cf60e1
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index f2240aa..d567fb6 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -3552,6 +3552,11 @@
.getOrCreateVariant(nullability);
}
+ public InterfaceCollection getLeastUpperBoundOfImplementedInterfacesOrDefault(
+ DexType type, InterfaceCollection defaultValue) {
+ return classTypeInterfaces.getOrDefault(type, defaultValue);
+ }
+
public InterfaceCollection getOrComputeLeastUpperBoundOfImplementedInterfaces(
DexType type, AppView<? extends AppInfoWithClassHierarchy> appView) {
return classTypeInterfaces.computeIfAbsent(
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeElement.java b/src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeElement.java
index 287f94e..a9ee774 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeElement.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/ClassTypeElement.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.ir.analysis.type.InterfaceCollection.Builder;
import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.Box;
+import com.android.tools.r8.utils.ObjectUtils;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.SetUtils;
@@ -105,6 +106,22 @@
return lazyInterfaces;
}
+ public boolean hasDefaultImplementedInterfaces() {
+ assert appView != null : "Unexpected use of hasDefaultImplementedInterfaces() in D8";
+ if (lazyInterfaces == null) {
+ return true;
+ }
+ InterfaceCollection defaultImplementedInterfaces =
+ appView
+ .dexItemFactory()
+ .getLeastUpperBoundOfImplementedInterfacesOrDefault(getClassType(), null);
+ if (ObjectUtils.identical(lazyInterfaces, defaultImplementedInterfaces)) {
+ return true;
+ }
+ assert !lazyInterfaces.equals(defaultImplementedInterfaces);
+ return false;
+ }
+
private ClassTypeElement createVariant(
Nullability nullability, NullabilityVariants<ClassTypeElement> variants) {
assert this.nullability != nullability;
@@ -161,7 +178,7 @@
ImmediateProgramSubtypingInfo immediateSubtypingInfo) {
DexType thisClassType = getClassType();
DexType otherClassType = otherClass.getType();
- if (getInterfaces().isEmpty()) {
+ if (getInterfaces().isEmpty() || hasDefaultImplementedInterfaces()) {
// <= can be implemented by a single class hierarchy check.
if (thisClassType.isIdenticalTo(otherClassType)) {
return true;
@@ -188,7 +205,7 @@
ImmediateProgramSubtypingInfo immediateSubtypingInfo) {
DexType thisClassType = getClassType();
DexType otherClassType = otherClass.getType();
- if (getInterfaces().isEmpty()) {
+ if (getInterfaces().isEmpty() || hasDefaultImplementedInterfaces()) {
// >= can be implemented by a single class hierarchy check.
if (thisClassType.isIdenticalTo(otherClassType)) {
return true;