Enable member rebinding for platform
Bug: 206178274
Change-Id: I37ceb0bcd5a1ed85a4ddc02fd713fa1ae60c36a6
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index fbddc6c..1483137 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -883,20 +883,16 @@
return true;
}
// This will return false if we find anything in the library which is not modeled.
- appView
- .appInfo()
- .classes()
- .forEach(
- clazz -> {
- clazz.forEachProgramMember(
- member -> {
- assert member.getDefinition().getApiLevel() != AndroidApiLevel.NOT_SET
- : "Every member should have been analyzed";
- assert appView.options().apiModelingOptions().enableApiCallerIdentification
- || member.getDefinition().getApiLevel() == AndroidApiLevel.UNKNOWN
- : "Every member should have level UNKNOWN";
- });
- });
+ for (DexProgramClass clazz : appView.appInfo().classesWithDeterministicOrder()) {
+ clazz.forEachProgramMember(
+ member -> {
+ assert member.getDefinition().getApiLevel() != AndroidApiLevel.NOT_SET
+ : "Every member should have been analyzed";
+ assert appView.options().apiModelingOptions().enableApiCallerIdentification
+ || member.getDefinition().getApiLevel() == AndroidApiLevel.UNKNOWN
+ : "Every member should have level UNKNOWN";
+ });
+ }
return true;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index 3177a9c..a198bb7 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.optimize;
+import static com.android.tools.r8.utils.AndroidApiLevelUtils.isApiSafeForMemberRebinding;
+
import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
@@ -25,7 +27,6 @@
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BiForEachable;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Pair;
@@ -126,7 +127,8 @@
return resolvedMethod.isLibraryMethod()
&& isAccessibleInAllContexts(resolvedMethod, resolutionResult, contexts)
&& !isInvokeSuperToInterfaceMethod(resolvedMethod, invokeType)
- && isPresentSinceMinApi(resolvedMethod.asLibraryMethod());
+ && isApiSafeForMemberRebinding(
+ resolvedMethod.asLibraryMethod(), androidApiLevelCompute, options);
}
private boolean isAccessibleInAllContexts(
@@ -145,13 +147,6 @@
return method.getHolder().isInterface() && invokeType.isSuper();
}
- private boolean isPresentSinceMinApi(LibraryMethod method) {
- AndroidApiLevel apiLevel =
- androidApiLevelCompute.computeApiLevelForLibraryReference(method.getReference());
- return apiLevel != AndroidApiLevel.UNKNOWN
- && apiLevel.isLessThanOrEqualTo(options.getMinApiLevel());
- }
-
public static DexField validMemberRebindingTargetFor(
DexDefinitionSupplier definitions, DexClassAndField field, DexField original) {
if (field.isProgramField()) {
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
index c348770..b0b7f7f 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
@@ -43,8 +43,9 @@
R(30),
S(31),
Sv2(32),
- UNKNOWN(10000),
- NOT_SET(10001);
+ ANDROID_PLATFORM(10000),
+ UNKNOWN(10001),
+ NOT_SET(10002);
// When updating LATEST and a new version goes stable, add a new api-versions.xml to third_party
// and update the version and generated jar in AndroidApiDatabaseBuilderGeneratorTest.
@@ -107,7 +108,7 @@
public static AndroidApiLevel getAndroidApiLevel(int apiLevel) {
assert apiLevel > 0;
- assert UNKNOWN.isGreaterThan(LATEST);
+ assert ANDROID_PLATFORM.isGreaterThan(LATEST);
switch (apiLevel) {
case 1:
return B;
@@ -173,10 +174,12 @@
return S;
case 32:
return Sv2;
+ case 10000:
+ return ANDROID_PLATFORM;
default:
// This has to be updated when we add new api levels.
assert Sv2 == LATEST;
- return UNKNOWN;
+ return LATEST;
}
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java b/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
index 73ee4de..c4a7396 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.utils;
+import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
+import com.android.tools.r8.graph.LibraryMethod;
import com.android.tools.r8.graph.ProgramMethod;
public class AndroidApiLevelUtils {
@@ -13,6 +15,10 @@
if (!options.apiModelingOptions().enableApiCallerIdentification) {
return true;
}
+ if (options.isAndroidPlatform()) {
+ // Don't disable inlining in the Android platform based on the Api database.
+ return true;
+ }
if (caller.getHolderType() == inlinee.getHolderType()) {
return true;
}
@@ -21,4 +27,17 @@
.getApiLevel()
.isGreaterThanOrEqualTo(inlinee.getDefinition().getApiLevelForCode());
}
+
+ public static boolean isApiSafeForMemberRebinding(
+ LibraryMethod method,
+ AndroidApiLevelCompute androidApiLevelCompute,
+ InternalOptions options) {
+ AndroidApiLevel apiLevel =
+ androidApiLevelCompute.computeApiLevelForLibraryReference(method.getReference());
+ if (apiLevel == AndroidApiLevel.UNKNOWN) {
+ return false;
+ }
+ assert options.apiModelingOptions().enableApiCallerIdentification;
+ return apiLevel.isLessThanOrEqualTo(options.getMinApiLevel());
+ }
}
diff --git a/src/main/java/com/android/tools/r8/utils/DexVersion.java b/src/main/java/com/android/tools/r8/utils/DexVersion.java
index 24d374e..241ae90 100644
--- a/src/main/java/com/android/tools/r8/utils/DexVersion.java
+++ b/src/main/java/com/android/tools/r8/utils/DexVersion.java
@@ -40,7 +40,6 @@
switch (androidApiLevel) {
// UNKNOWN is an unknown higher api version we therefore choose the highest known
// version.
- case UNKNOWN:
case Sv2:
case S:
case R:
@@ -77,7 +76,8 @@
case L_MR1:
case M:
return DexVersion.V35;
- default :
+ case UNKNOWN:
+ default:
throw new Unreachable("Unsupported api level " + androidApiLevel);
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 8fd985c..c012686 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -422,6 +422,10 @@
throw new UnsupportedOperationException("Cannot find internal output mode.");
}
+ public boolean isAndroidPlatform() {
+ return minApiLevel == AndroidApiLevel.ANDROID_PLATFORM;
+ }
+
public boolean isDesugaredLibraryCompilation() {
return desugaredLibraryConfiguration.isLibraryCompilation();
}
@@ -559,7 +563,7 @@
public void setMinApiLevel(AndroidApiLevel minApiLevel) {
assert minApiLevel != null;
- assert minApiLevel.isLessThan(AndroidApiLevel.NOT_SET);
+ assert minApiLevel.isLessThan(AndroidApiLevel.UNKNOWN);
this.minApiLevel = minApiLevel;
}
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 11dfa2d..033e512 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -861,6 +861,7 @@
case J_MR1:
case J_MR2:
case K_WATCH:
+ case ANDROID_PLATFORM:
case UNKNOWN:
case NOT_SET:
return false;