Update handling of API outline stubs
Include library exception guards in method API level calculation when
the class is never stubbed.
Bug: b/342961827
Change-Id: I8d33aaeee0412599a3bdc4fe3abc2fb8454e88eb
diff --git a/src/main/java/com/android/tools/r8/GlobalSyntheticsGenerator.java b/src/main/java/com/android/tools/r8/GlobalSyntheticsGenerator.java
index 6b6d239..9b9989a 100644
--- a/src/main/java/com/android/tools/r8/GlobalSyntheticsGenerator.java
+++ b/src/main/java/com/android/tools/r8/GlobalSyntheticsGenerator.java
@@ -289,7 +289,7 @@
if (notModeledTypes.contains(libraryClass.getClassReference().getTypeName())) {
return;
}
- if (ApiReferenceStubber.isJavaType(libraryClass.getType(), factory)) {
+ if (ApiReferenceStubber.isNeverStubbedType(libraryClass.getType(), factory)) {
return;
}
KnownApiLevel knownApiLevel =
diff --git a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
index d3fafc4..4a2dc9a 100644
--- a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
+++ b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
@@ -159,7 +159,7 @@
}
private void findReferencedLibraryClasses(DexType type, DexProgramClass context) {
- if (!type.isClassType() || isJavaType(type, appView.dexItemFactory())) {
+ if (!type.isClassType() || isNeverStubbedType(type, appView.dexItemFactory())) {
return;
}
DexClass clazz = appView.definitionFor(type);
@@ -182,10 +182,17 @@
}
}
- @SuppressWarnings("ReferenceEquality")
- public static boolean isJavaType(DexType type, DexItemFactory factory) {
+ public static boolean isAlwaysStubbedType(DexType type, DexItemFactory factory) {
+ return !isNeverStubbedType(type, factory);
+ }
+
+ public static boolean isNeverStubbedType(DexType type, DexItemFactory factory) {
+ return isJavaType(type, factory);
+ }
+
+ private static boolean isJavaType(DexType type, DexItemFactory factory) {
DexString typeDescriptor = type.getDescriptor();
- return type == factory.objectType
+ return type.isIdenticalTo(factory.objectType)
|| typeDescriptor.startsWith(factory.comSunDescriptorPrefix)
|| typeDescriptor.startsWith(factory.javaDescriptorPrefix)
|| typeDescriptor.startsWith(factory.javaxDescriptorPrefix)
@@ -201,7 +208,7 @@
ApiReferenceStubberEventConsumer eventConsumer) {
DexItemFactory factory = appView.dexItemFactory();
// Do not stub the anything starting with java (including the object type).
- if (isJavaType(libraryClass.getType(), factory)) {
+ if (isNeverStubbedType(libraryClass.getType(), factory)) {
return;
}
// Check if desugared library will bridge the type.
diff --git a/src/main/java/com/android/tools/r8/shaking/ComputeApiLevelUseRegistry.java b/src/main/java/com/android/tools/r8/shaking/ComputeApiLevelUseRegistry.java
index ea26098..2f841a5 100644
--- a/src/main/java/com/android/tools/r8/shaking/ComputeApiLevelUseRegistry.java
+++ b/src/main/java/com/android/tools/r8/shaking/ComputeApiLevelUseRegistry.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.shaking;
import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
+import com.android.tools.r8.androidapi.ApiReferenceStubber;
import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.dex.code.CfOrDexInstruction;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
@@ -141,9 +142,9 @@
@Override
public void registerExceptionGuard(DexType guard) {
- // Type references as exception guard are OK unless unknown. Library exception guards will be
- // stubbed.
- setMaxApiReferenceLevelIfUnknown(guard);
+ // Type references as exception guard are OK for stubbed exception guards as they are always
+ // present at runtime.
+ setMaxApiReferenceLevelIfNeverStubbedOrUnknown(guard);
}
@Override
@@ -172,10 +173,15 @@
}
}
- private void setMaxApiReferenceLevelIfUnknown(DexType type) {
+ private void setMaxApiReferenceLevelIfNeverStubbedOrUnknown(DexType type) {
if (isEnabled) {
+ if (ApiReferenceStubber.isAlwaysStubbedType(
+ type, appInfoWithClassHierarchy.dexItemFactory())) {
+ return;
+ }
ComputedApiLevel computedApiLevel = apiLevelCompute.computeApiLevelForLibraryReference(type);
- if (computedApiLevel.isUnknownApiLevel()) {
+ if (ApiReferenceStubber.isNeverStubbedType(type, appInfoWithClassHierarchy.dexItemFactory())
+ || computedApiLevel.isUnknownApiLevel()) {
maxApiReferenceLevel = maxApiReferenceLevel.max(computedApiLevel);
}
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithLibraryTypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithLibraryTypeTest.java
index ea19697..ebe5ac8 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithLibraryTypeTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineCatchHandlerWithLibraryTypeTest.java
@@ -87,10 +87,17 @@
.transform();
}
+ private static boolean isNeverStubbed(String exception) {
+ // Note: this is a simplified version of ApiReferenceStubber.isNeverStubbedType only testing
+ // the types relevant for this test.
+ return exception.startsWith("java.");
+ }
+
private boolean compilationTargetIsMissingExceptionType() {
// A CF target could target any API in the end.
return parameters.isCfRuntime()
- || parameters.getApiLevel().getLevel() < EXCEPTIONS.get(exception);
+ || (parameters.getApiLevel().getLevel() < EXCEPTIONS.get(exception)
+ && isNeverStubbed(exception));
}
@Test