Reland "[ApiModel] Use ComputedApiLevel instead of AndroidApiLevel"
This reverts commit ab84d34a0141d2cb892ab78d98c27d2450512a5a.
Bug: 207452750
Change-Id: I67dc36d1983bad82df910366b4ecf2d69f39c8b8
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 72c0cbb..722ae3e 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -104,7 +104,6 @@
import com.android.tools.r8.shaking.WhyAreYouKeepingConsumer;
import com.android.tools.r8.synthesis.SyntheticFinalization;
import com.android.tools.r8.synthesis.SyntheticItems;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.CfgPrinter;
import com.android.tools.r8.utils.CollectionUtils;
@@ -880,10 +879,10 @@
for (DexProgramClass clazz : appView.appInfo().classesWithDeterministicOrder()) {
clazz.forEachProgramMember(
member -> {
- assert member.getDefinition().getApiLevel() != AndroidApiLevel.NOT_SET
+ assert !member.getDefinition().getApiLevel().isNotSetApiLevel()
: "Every member should have been analyzed";
assert appView.options().apiModelingOptions().enableApiCallerIdentification
- || member.getDefinition().getApiLevel() == AndroidApiLevel.UNKNOWN
+ || member.getDefinition().getApiLevel().isUnknownApiLevel()
: "Every member should have level UNKNOWN";
});
}
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelCompute.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelCompute.java
index 34a2d65..48d4d4f 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelCompute.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelCompute.java
@@ -4,67 +4,108 @@
package com.android.tools.r8.androidapi;
-import static com.android.tools.r8.utils.AndroidApiLevel.UNKNOWN;
-
+import com.android.tools.r8.androidapi.ComputedApiLevel.KnownApiLevel;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMember;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.InternalOptions;
-public interface AndroidApiLevelCompute {
+public abstract class AndroidApiLevelCompute {
- AndroidApiLevel computeApiLevelForLibraryReference(DexReference reference);
+ private final KnownApiLevel[] knownApiLevelCache;
- AndroidApiLevel computeApiLevelForDefinition(Iterable<DexType> types);
-
- default AndroidApiLevel computeApiLevelForDefinition(
- DexMember<?, ?> reference, DexItemFactory factory) {
- return computeApiLevelForDefinition(reference.getReferencedBaseTypes(factory));
+ public AndroidApiLevelCompute() {
+ knownApiLevelCache = new KnownApiLevel[AndroidApiLevel.LATEST.getLevel() + 1];
+ for (AndroidApiLevel value : AndroidApiLevel.values()) {
+ if (value != AndroidApiLevel.ANDROID_PLATFORM) {
+ knownApiLevelCache[value.getLevel()] = new KnownApiLevel(value);
+ }
+ }
}
- static AndroidApiLevelCompute create(AppView<?> appView) {
+ public KnownApiLevel of(AndroidApiLevel apiLevel) {
+ if (apiLevel == AndroidApiLevel.ANDROID_PLATFORM) {
+ return ComputedApiLevel.platform();
+ }
+ return knownApiLevelCache[apiLevel.getLevel()];
+ }
+
+ public abstract ComputedApiLevel computeApiLevelForLibraryReference(
+ DexReference reference, ComputedApiLevel unknownValue);
+
+ public abstract ComputedApiLevel computeApiLevelForDefinition(
+ Iterable<DexType> types, ComputedApiLevel unknownValue);
+
+ public ComputedApiLevel computeApiLevelForDefinition(
+ DexMember<?, ?> reference, DexItemFactory factory, ComputedApiLevel unknownValue) {
+ return computeApiLevelForDefinition(reference.getReferencedBaseTypes(factory), unknownValue);
+ }
+
+ public static AndroidApiLevelCompute create(AppView<?> appView) {
return appView.options().apiModelingOptions().enableApiCallerIdentification
? new DefaultAndroidApiLevelCompute(appView)
: new NoAndroidApiLevelCompute();
}
- class NoAndroidApiLevelCompute implements AndroidApiLevelCompute {
-
- @Override
- public AndroidApiLevel computeApiLevelForDefinition(Iterable<DexType> types) {
- return UNKNOWN;
- }
-
- @Override
- public AndroidApiLevel computeApiLevelForLibraryReference(DexReference reference) {
- return UNKNOWN;
+ public static ComputedApiLevel computeInitialMinApiLevel(InternalOptions options) {
+ if (options.apiModelingOptions().enableApiCallerIdentification) {
+ return options.getMinApiLevel() == AndroidApiLevel.ANDROID_PLATFORM
+ ? ComputedApiLevel.platform()
+ : new KnownApiLevel(options.getMinApiLevel());
+ } else {
+ return ComputedApiLevel.unknown();
}
}
- class DefaultAndroidApiLevelCompute implements AndroidApiLevelCompute {
+ public ComputedApiLevel getPlatformApiLevelOrUnknown(AppView<?> appView) {
+ if (appView.options().getMinApiLevel() == AndroidApiLevel.ANDROID_PLATFORM) {
+ return ComputedApiLevel.platform();
+ }
+ return ComputedApiLevel.unknown();
+ }
- private final AndroidApiReferenceLevelCache cache;
- private final AndroidApiLevel minApiLevel;
+ public static class NoAndroidApiLevelCompute extends AndroidApiLevelCompute {
- public DefaultAndroidApiLevelCompute(AppView<?> appView) {
- this.cache = AndroidApiReferenceLevelCache.create(appView);
- this.minApiLevel = appView.options().getMinApiLevel();
+ @Override
+ public ComputedApiLevel computeApiLevelForDefinition(
+ Iterable<DexType> types, ComputedApiLevel unknownValue) {
+ return unknownValue;
}
@Override
- public AndroidApiLevel computeApiLevelForDefinition(Iterable<DexType> types) {
- AndroidApiLevel computedLevel = minApiLevel;
+ public ComputedApiLevel computeApiLevelForLibraryReference(
+ DexReference reference, ComputedApiLevel unknownValue) {
+ return unknownValue;
+ }
+ }
+
+ public static class DefaultAndroidApiLevelCompute extends AndroidApiLevelCompute {
+
+ private final AndroidApiReferenceLevelCache cache;
+ private final ComputedApiLevel minApiLevel;
+
+ public DefaultAndroidApiLevelCompute(AppView<?> appView) {
+ this.cache = AndroidApiReferenceLevelCache.create(appView, this);
+ this.minApiLevel = of(appView.options().getMinApiLevel());
+ }
+
+ @Override
+ public ComputedApiLevel computeApiLevelForDefinition(
+ Iterable<DexType> types, ComputedApiLevel unknownValue) {
+ ComputedApiLevel computedLevel = minApiLevel;
for (DexType type : types) {
- computedLevel = cache.lookupMax(type, computedLevel);
+ computedLevel = cache.lookupMax(type, computedLevel, unknownValue);
}
return computedLevel;
}
@Override
- public AndroidApiLevel computeApiLevelForLibraryReference(DexReference reference) {
- return cache.lookup(reference);
+ public ComputedApiLevel computeApiLevelForLibraryReference(
+ DexReference reference, ComputedApiLevel unknownValue) {
+ return cache.lookup(reference, unknownValue);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelHashingDatabaseImpl.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelHashingDatabaseImpl.java
index 551085a..bedc254 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelHashingDatabaseImpl.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelHashingDatabaseImpl.java
@@ -4,12 +4,10 @@
package com.android.tools.r8.androidapi;
-import static com.android.tools.r8.utils.AndroidApiLevel.NOT_SET;
-import static com.android.tools.r8.utils.AndroidApiLevel.UNKNOWN;
+import static com.android.tools.r8.utils.AndroidApiLevel.ANDROID_PLATFORM;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
@@ -41,25 +39,23 @@
new Int2ReferenceOpenHashMap<AndroidApiLevel>();
private final Map<String, AndroidApiLevel> ambiguousHashesWithApiLevel = new HashMap<>();
private final Map<DexReference, AndroidApiLevel> ambiguousCache = new IdentityHashMap<>();
- private final DexItemFactory factory;
public AndroidApiLevelHashingDatabaseImpl(
- DexItemFactory factory, List<AndroidApiForHashingClass> predefinedApiTypeLookup) {
- this.factory = factory;
+ List<AndroidApiForHashingClass> predefinedApiTypeLookup) {
loadData();
predefinedApiTypeLookup.forEach(
apiClass -> {
DexType type = apiClass.getType();
- lookupNonAmbiguousCache.put(type.hashCode(), NOT_SET);
+ lookupNonAmbiguousCache.put(type.hashCode(), null);
ambiguousCache.put(type, apiClass.getApiLevel());
apiClass.visitMethodsWithApiLevels(
(method, apiLevel) -> {
- lookupNonAmbiguousCache.put(method.hashCode(), NOT_SET);
+ lookupNonAmbiguousCache.put(method.hashCode(), null);
ambiguousCache.put(method, apiLevel);
});
apiClass.visitFieldsWithApiLevels(
(field, apiLevel) -> {
- lookupNonAmbiguousCache.put(field.hashCode(), NOT_SET);
+ lookupNonAmbiguousCache.put(field.hashCode(), null);
ambiguousCache.put(field, apiLevel);
});
});
@@ -96,7 +92,7 @@
for (int i = 0; i < hashIndices.length; i++) {
byte apiLevel = apiLevels[i];
lookupNonAmbiguousCache.put(
- hashIndices[i], apiLevel == -1 ? NOT_SET : AndroidApiLevel.getAndroidApiLevel(apiLevel));
+ hashIndices[i], apiLevel == -1 ? null : AndroidApiLevel.getAndroidApiLevel(apiLevel));
}
ambiguous.forEach(this::parseAmbiguous);
}
@@ -130,9 +126,12 @@
}
private AndroidApiLevel lookupApiLevel(DexReference reference) {
- AndroidApiLevel result = lookupNonAmbiguousCache.getOrDefault(reference.hashCode(), UNKNOWN);
- if (result != NOT_SET) {
- return result;
+ // We use Android platform to track if an element is unknown since no occurrences of that api
+ // level exists in the database.
+ AndroidApiLevel result =
+ lookupNonAmbiguousCache.getOrDefault(reference.hashCode(), ANDROID_PLATFORM);
+ if (result != null) {
+ return result == ANDROID_PLATFORM ? null : result;
}
return ambiguousCache.computeIfAbsent(
reference,
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java
index 3cb2b7d..4e17f60 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java
@@ -17,87 +17,89 @@
public class AndroidApiReferenceLevelCache {
private final DesugaredLibraryConfiguration desugaredLibraryConfiguration;
+ private final AndroidApiLevelCompute apiLevelCompute;
private final AndroidApiLevelDatabase androidApiLevelDatabase;
private final AppView<?> appView;
private final DexItemFactory factory;
- private AndroidApiReferenceLevelCache(AppView<?> appView) {
- this(appView, ImmutableList.of());
- }
-
private AndroidApiReferenceLevelCache(
- AppView<?> appView, List<AndroidApiForHashingClass> predefinedApiTypeLookupForHashing) {
+ AppView<?> appView,
+ AndroidApiLevelCompute apiLevelCompute,
+ List<AndroidApiForHashingClass> predefinedApiTypeLookupForHashing) {
this.appView = appView;
+ this.apiLevelCompute = apiLevelCompute;
factory = appView.dexItemFactory();
androidApiLevelDatabase =
- new AndroidApiLevelHashingDatabaseImpl(factory, predefinedApiTypeLookupForHashing);
+ new AndroidApiLevelHashingDatabaseImpl(predefinedApiTypeLookupForHashing);
desugaredLibraryConfiguration = appView.options().desugaredLibraryConfiguration;
}
- public static AndroidApiReferenceLevelCache create(AppView<?> appView) {
- if (!appView.options().apiModelingOptions().enableApiCallerIdentification) {
- // If enableApiCallerIdentification is not enabled then override lookup to always return
- // AndroidApiLevel.B.
- return new AndroidApiReferenceLevelCache(appView) {
- @Override
- public AndroidApiLevel lookup(DexReference reference) {
- return AndroidApiLevel.B;
- }
- };
- }
+ public static AndroidApiReferenceLevelCache create(
+ AppView<?> appView, AndroidApiLevelCompute apiLevelCompute) {
+ assert appView.options().apiModelingOptions().enableApiCallerIdentification;
ImmutableList.Builder<AndroidApiForHashingClass> builder = ImmutableList.builder();
appView
.options()
.apiModelingOptions()
.visitMockedApiLevelsForReferences(appView.dexItemFactory(), builder::add);
- return new AndroidApiReferenceLevelCache(appView, builder.build());
+ return new AndroidApiReferenceLevelCache(appView, apiLevelCompute, builder.build());
}
- public AndroidApiLevel lookupMax(DexReference reference, AndroidApiLevel minApiLevel) {
- return lookup(reference).max(minApiLevel);
+ public ComputedApiLevel lookupMax(
+ DexReference reference, ComputedApiLevel minApiLevel, ComputedApiLevel unknownValue) {
+ assert !minApiLevel.isNotSetApiLevel();
+ return lookup(reference, unknownValue).max(minApiLevel);
}
- public AndroidApiLevel lookup(DexReference reference) {
+ public ComputedApiLevel lookup(DexReference reference, ComputedApiLevel unknownValue) {
DexType contextType = reference.getContextType();
if (contextType.isArrayType()) {
if (reference.isDexMethod() && reference.asDexMethod().match(factory.objectMembers.clone)) {
- return appView.options().getMinApiLevel();
+ return appView.computedMinApiLevel();
}
- return lookup(contextType.toBaseType(factory));
+ return lookup(contextType.toBaseType(factory), unknownValue);
}
if (contextType.isPrimitiveType() || contextType.isVoidType()) {
- return appView.options().getMinApiLevel();
+ return appView.computedMinApiLevel();
}
DexClass clazz = appView.definitionFor(contextType);
if (clazz == null) {
- return AndroidApiLevel.UNKNOWN;
+ return unknownValue;
}
if (!clazz.isLibraryClass()) {
- return appView.options().getMinApiLevel();
+ return appView.computedMinApiLevel();
}
if (reference.getContextType() == factory.objectType) {
- return appView.options().getMinApiLevel();
+ return appView.computedMinApiLevel();
}
if (desugaredLibraryConfiguration.isSupported(reference, appView)) {
// If we end up desugaring the reference, the library classes is bridged by j$ which is part
// of the program.
- return appView.options().getMinApiLevel();
+ return appView.computedMinApiLevel();
}
- if (reference.isDexMethod() && factory.objectMembers.isObjectMember(reference.asDexMethod())) {
+ if (reference.isDexMethod()
+ && !reference.asDexMethod().isInstanceInitializer(factory)
+ && factory.objectMembers.isObjectMember(reference.asDexMethod())) {
// If we can lookup the method it was introduced/overwritten later. Take for example
- // a default constructor that was not available before som api level. If unknown we default
+ // a default toString that was not available before some api level. If unknown we default
// back to the static holder.
AndroidApiLevel methodApiLevel =
androidApiLevelDatabase.getMethodApiLevel(reference.asDexMethod());
- return methodApiLevel == AndroidApiLevel.UNKNOWN
- ? androidApiLevelDatabase.getTypeApiLevel(reference.getContextType())
- : methodApiLevel;
+ if (methodApiLevel != null) {
+ return apiLevelCompute.of(methodApiLevel);
+ }
+ AndroidApiLevel typeApiLevel =
+ androidApiLevelDatabase.getTypeApiLevel(reference.getContextType());
+ // TODO(b/207452750): Investigate if we can return minApi here.
+ return typeApiLevel == null ? ComputedApiLevel.unknown() : apiLevelCompute.of(typeApiLevel);
}
- return reference
- .apply(
+ AndroidApiLevel foundApiLevel =
+ reference.apply(
androidApiLevelDatabase::getTypeApiLevel,
androidApiLevelDatabase::getFieldApiLevel,
- androidApiLevelDatabase::getMethodApiLevel)
- .max(appView.options().getMinApiLevel());
+ androidApiLevelDatabase::getMethodApiLevel);
+ return (foundApiLevel == null)
+ ? unknownValue
+ : apiLevelCompute.of(foundApiLevel.max(appView.options().getMinApiLevel()));
}
}
diff --git a/src/main/java/com/android/tools/r8/androidapi/ComputedApiLevel.java b/src/main/java/com/android/tools/r8/androidapi/ComputedApiLevel.java
new file mode 100644
index 0000000..2f5ab5e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/androidapi/ComputedApiLevel.java
@@ -0,0 +1,165 @@
+// Copyright (c) 2021, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.androidapi;
+
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.structural.Equatable;
+import java.util.Objects;
+
+/**
+ * The ComputedApiLevel encodes a lattice over AndroidApiLevel with a bottom (NotSet) and a top
+ * (Unknown).
+ */
+public interface ComputedApiLevel extends Equatable<ComputedApiLevel> {
+
+ static NotSetApiLevel notSet() {
+ return NotSetApiLevel.INSTANCE;
+ }
+
+ static UnknownApiLevel unknown() {
+ return UnknownApiLevel.INSTANCE;
+ }
+
+ static KnownApiLevel platform() {
+ return KnownApiLevel.PLATFORM_INSTANCE;
+ }
+
+ default boolean isNotSetApiLevel() {
+ return false;
+ }
+
+ default boolean isUnknownApiLevel() {
+ return false;
+ }
+
+ default ComputedApiLevel max(ComputedApiLevel other) {
+ return isGreaterThanOrEqualTo(other) ? this : other;
+ }
+
+ default boolean isGreaterThanOrEqualTo(ComputedApiLevel other) {
+ assert !isNotSetApiLevel() && !other.isNotSetApiLevel()
+ : "Cannot compute relationship for not set";
+ if (isUnknownApiLevel()) {
+ return true;
+ }
+ if (other.isUnknownApiLevel()) {
+ return false;
+ }
+ assert isKnownApiLevel() && other.isKnownApiLevel();
+ return asKnownApiLevel()
+ .getApiLevel()
+ .isGreaterThanOrEqualTo(other.asKnownApiLevel().getApiLevel());
+ }
+
+ default boolean isKnownApiLevel() {
+ return false;
+ }
+
+ default KnownApiLevel asKnownApiLevel() {
+ return null;
+ }
+
+ @Override
+ default boolean isEqualTo(ComputedApiLevel other) {
+ return this.equals(other);
+ }
+
+ class NotSetApiLevel implements ComputedApiLevel {
+
+ private static final NotSetApiLevel INSTANCE = new NotSetApiLevel();
+
+ private NotSetApiLevel() {}
+
+ @Override
+ public boolean isNotSetApiLevel() {
+ return true;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return this == obj;
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+ }
+
+ class UnknownApiLevel implements ComputedApiLevel {
+
+ private static final UnknownApiLevel INSTANCE = new UnknownApiLevel();
+
+ private UnknownApiLevel() {}
+
+ @Override
+ public boolean isUnknownApiLevel() {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "UNKNOWN";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return this == obj;
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+ }
+
+ class KnownApiLevel implements ComputedApiLevel {
+
+ private static final KnownApiLevel PLATFORM_INSTANCE =
+ new KnownApiLevel(AndroidApiLevel.ANDROID_PLATFORM);
+
+ private final AndroidApiLevel apiLevel;
+
+ KnownApiLevel(AndroidApiLevel apiLevel) {
+ this.apiLevel = apiLevel;
+ }
+
+ public AndroidApiLevel getApiLevel() {
+ return apiLevel;
+ }
+
+ @Override
+ public boolean isKnownApiLevel() {
+ return true;
+ }
+
+ @Override
+ public KnownApiLevel asKnownApiLevel() {
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return apiLevel.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof KnownApiLevel)) {
+ return false;
+ }
+ KnownApiLevel that = (KnownApiLevel) o;
+ return apiLevel == that.apiLevel;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(apiLevel);
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 32e1f64..e21fbf4 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.graph;
+import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.contexts.CompilationContext;
import com.android.tools.r8.contexts.CompilationContext.ProcessorContext;
import com.android.tools.r8.errors.dontwarn.DontWarnConfiguration;
@@ -116,6 +118,8 @@
private final Thread mainThread = Thread.currentThread();
+ private final ComputedApiLevel computedMinApiLevel;
+
private AppView(
T appInfo,
WholeProgramOptimizations wholeProgramOptimizations,
@@ -137,6 +141,8 @@
this.libraryMethodSideEffectModelCollection = new LibraryMethodSideEffectModelCollection(this);
this.libraryMemberOptimizer = new LibraryMemberOptimizer(this);
this.protoShrinker = ProtoShrinker.create(withLiveness());
+
+ this.computedMinApiLevel = AndroidApiLevelCompute.computeInitialMinApiLevel(appInfo.options());
}
public boolean verifyMainThread() {
@@ -827,4 +833,8 @@
public boolean checkForTesting(Supplier<Boolean> test) {
return testing().enableTestAssertions ? test.get() : true;
}
+
+ public ComputedApiLevel computedMinApiLevel() {
+ return computedMinApiLevel;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
index 56a302d..44a5132 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
@@ -7,6 +7,7 @@
import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.getNoKotlinInfo;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
import com.android.tools.r8.ir.analysis.type.TypeElement;
@@ -21,7 +22,6 @@
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
import com.android.tools.r8.kotlin.KotlinFieldLevelInfo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.structural.StructuralItem;
import com.android.tools.r8.utils.structural.StructuralMapping;
@@ -59,7 +59,7 @@
FieldTypeSignature genericSignature,
DexAnnotationSet annotations,
DexValue staticValue,
- AndroidApiLevel apiLevel,
+ ComputedApiLevel apiLevel,
boolean deprecated,
boolean d8R8Synthesized) {
super(field, annotations, d8R8Synthesized, apiLevel);
@@ -103,7 +103,7 @@
}
@Override
- public AndroidApiLevel getApiLevel() {
+ public ComputedApiLevel getApiLevel() {
return getApiLevelForDefinition();
}
@@ -365,7 +365,7 @@
private FieldAccessFlags accessFlags;
private FieldTypeSignature genericSignature = FieldTypeSignature.noSignature();
private DexValue staticValue = null;
- private AndroidApiLevel apiLevel = AndroidApiLevel.NOT_SET;
+ private ComputedApiLevel apiLevel = ComputedApiLevel.notSet();
private FieldOptimizationInfo optimizationInfo = DefaultFieldOptimizationInfo.getInstance();
private boolean deprecated;
private final boolean d8R8Synthesized;
@@ -438,7 +438,7 @@
return this;
}
- public Builder setApiLevel(AndroidApiLevel apiLevel) {
+ public Builder setApiLevel(ComputedApiLevel apiLevel) {
this.apiLevel = apiLevel;
return this;
}
@@ -474,7 +474,7 @@
assert accessFlags != null;
assert genericSignature != null;
assert annotations != null;
- assert !checkAndroidApiLevel || apiLevel != AndroidApiLevel.NOT_SET;
+ assert !checkAndroidApiLevel || !apiLevel.isNotSetApiLevel();
DexEncodedField dexEncodedField =
new DexEncodedField(
field,
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java
index a5ea49e..7f42e49 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java
@@ -3,11 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
-import static com.android.tools.r8.utils.AndroidApiLevel.NOT_SET;
-
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.ir.optimize.info.MemberOptimizationInfo;
import com.android.tools.r8.kotlin.KotlinMemberLevelInfo;
-import com.android.tools.r8.utils.AndroidApiLevel;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -23,7 +21,7 @@
private final boolean d8R8Synthesized;
/** apiLevelForDefinition describes the api level needed for knowing all types */
- private AndroidApiLevel apiLevelForDefinition;
+ private ComputedApiLevel apiLevelForDefinition;
private final R reference;
@@ -31,7 +29,7 @@
R reference,
DexAnnotationSet annotations,
boolean d8R8Synthesized,
- AndroidApiLevel apiLevelForDefinition) {
+ ComputedApiLevel apiLevelForDefinition) {
super(annotations);
this.reference = reference;
this.d8R8Synthesized = d8R8Synthesized;
@@ -95,18 +93,18 @@
public abstract MemberOptimizationInfo<?> getOptimizationInfo();
- public abstract AndroidApiLevel getApiLevel();
+ public abstract ComputedApiLevel getApiLevel();
- public AndroidApiLevel getApiLevelForDefinition() {
+ public ComputedApiLevel getApiLevelForDefinition() {
return apiLevelForDefinition;
}
- public void setApiLevelForDefinition(AndroidApiLevel apiLevelForDefinition) {
+ public void setApiLevelForDefinition(ComputedApiLevel apiLevelForDefinition) {
this.apiLevelForDefinition = apiLevelForDefinition;
}
public boolean hasComputedApiReferenceLevel() {
- return getApiLevel() != NOT_SET;
+ return !getApiLevel().isNotSetApiLevel();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index ccf7d83..a8709ec 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -11,10 +11,10 @@
import static com.android.tools.r8.graph.DexEncodedMethod.CompilationState.PROCESSED_NOT_INLINING_CANDIDATE;
import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.getNoKotlinInfo;
-import static com.android.tools.r8.utils.AndroidApiLevel.NOT_SET;
import static com.android.tools.r8.utils.ConsumerUtils.emptyConsumer;
import static java.util.Objects.requireNonNull;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.cf.code.CfConstNumber;
import com.android.tools.r8.cf.code.CfConstString;
@@ -71,7 +71,6 @@
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.position.MethodPosition;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.InternalOptions;
@@ -148,8 +147,8 @@
ParameterAnnotationsList.empty(),
null,
false,
- NOT_SET,
- NOT_SET,
+ ComputedApiLevel.notSet(),
+ ComputedApiLevel.notSet(),
null,
CallSiteOptimizationInfo.top(),
DefaultMethodOptimizationInfo.getInstance(),
@@ -168,7 +167,7 @@
private CallSiteOptimizationInfo callSiteOptimizationInfo;
private CfVersion classFileVersion;
/** The apiLevelForCode describes the api level needed for knowing all references in the code */
- private AndroidApiLevel apiLevelForCode;
+ private ComputedApiLevel apiLevelForCode;
private KotlinMethodLevelInfo kotlinMemberInfo = getNoKotlinInfo();
/** Generic signature information if the attribute is present in the input */
@@ -242,8 +241,8 @@
ParameterAnnotationsList parameterAnnotationsList,
Code code,
boolean d8R8Synthesized,
- AndroidApiLevel apiLevelForDefinition,
- AndroidApiLevel apiLevelForCode,
+ ComputedApiLevel apiLevelForDefinition,
+ ComputedApiLevel apiLevelForCode,
CfVersion classFileVersion,
CallSiteOptimizationInfo callSiteOptimizationInfo,
MethodOptimizationInfo optimizationInfo,
@@ -1232,7 +1231,7 @@
.fixupOptimizationInfo(appView, prototypeChanges.createMethodOptimizationInfoFixer())
.setGenericSignature(MethodTypeSignature.noSignature());
DexEncodedMethod method = builder.build();
- method.copyMetadata(this);
+ method.copyMetadata(appView, this);
setObsolete();
return method;
}
@@ -1268,23 +1267,23 @@
return optimizationInfo;
}
- public AndroidApiLevel getApiLevelForCode() {
+ public ComputedApiLevel getApiLevelForCode() {
return apiLevelForCode;
}
- public void clearApiLevelForCode(AppView<?> appView) {
- this.apiLevelForCode = AndroidApiLevel.minApiLevelIfEnabledOrUnknown(appView);
+ public void clearApiLevelForCode() {
+ this.apiLevelForCode = ComputedApiLevel.notSet();
}
- public void setApiLevelForCode(AndroidApiLevel apiLevel) {
+ public void setApiLevelForCode(ComputedApiLevel apiLevel) {
assert apiLevel != null;
this.apiLevelForCode = apiLevel;
}
@Override
- public AndroidApiLevel getApiLevel() {
- return (shouldNotHaveCode() ? AndroidApiLevel.B : getApiLevelForCode())
- .max(getApiLevelForDefinition());
+ public ComputedApiLevel getApiLevel() {
+ ComputedApiLevel apiLevelForDefinition = getApiLevelForDefinition();
+ return shouldNotHaveCode() ? apiLevelForDefinition : apiLevelForDefinition.max(apiLevelForCode);
}
public synchronized MutableMethodOptimizationInfo getMutableOptimizationInfo() {
@@ -1320,12 +1319,14 @@
this.callSiteOptimizationInfo = callSiteOptimizationInfo;
}
- public void copyMetadata(DexEncodedMethod from) {
+ public void copyMetadata(AppView<?> appView, DexEncodedMethod from) {
checkIfObsolete();
if (from.hasClassFileVersion()) {
upgradeClassFileVersion(from.getClassFileVersion());
}
- apiLevelForCode = getApiLevelForCode().max(from.getApiLevelForCode());
+ if (appView.options().apiModelingOptions().enableApiCallerIdentification) {
+ apiLevelForCode = getApiLevelForCode().max(from.getApiLevelForCode());
+ }
}
public MethodTypeSignature getGenericSignature() {
@@ -1374,8 +1375,8 @@
private MethodOptimizationInfo optimizationInfo = DefaultMethodOptimizationInfo.getInstance();
private KotlinMethodLevelInfo kotlinInfo = getNoKotlinInfo();
private CfVersion classFileVersion = null;
- private AndroidApiLevel apiLevelForDefinition = NOT_SET;
- private AndroidApiLevel apiLevelForCode = NOT_SET;
+ private ComputedApiLevel apiLevelForDefinition = ComputedApiLevel.notSet();
+ private ComputedApiLevel apiLevelForCode = ComputedApiLevel.notSet();
private final boolean d8R8Synthesized;
private boolean deprecated = false;
@@ -1611,12 +1612,12 @@
return this;
}
- public Builder setApiLevelForDefinition(AndroidApiLevel apiLevelForDefinition) {
+ public Builder setApiLevelForDefinition(ComputedApiLevel apiLevelForDefinition) {
this.apiLevelForDefinition = apiLevelForDefinition;
return this;
}
- public Builder setApiLevelForCode(AndroidApiLevel apiLevelForCode) {
+ public Builder setApiLevelForCode(ComputedApiLevel apiLevelForCode) {
this.apiLevelForCode = apiLevelForCode;
return this;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index e297bd4..900e79c 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -4,11 +4,12 @@
package com.android.tools.r8.graph;
import static com.android.tools.r8.kotlin.KotlinMetadataUtils.getNoKotlinInfo;
-import static com.android.tools.r8.utils.AndroidApiLevel.minApiLevelIfEnabledOrUnknown;
import static com.google.common.base.Predicates.alwaysTrue;
import com.android.tools.r8.ProgramResource;
import com.android.tools.r8.ProgramResource.Kind;
+import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
@@ -21,7 +22,6 @@
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.synthesis.SyntheticMarker;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.TraversalContinuation;
import com.android.tools.r8.utils.structural.Ordered;
import com.android.tools.r8.utils.structural.StructuralItem;
@@ -34,7 +34,6 @@
import java.util.Iterator;
import java.util.List;
import java.util.Set;
-import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -823,26 +822,19 @@
return checksumSupplier;
}
- public AndroidApiLevel getApiReferenceLevel(
- AppView<?> appView,
- BiFunction<DexReference, AndroidApiLevel, AndroidApiLevel> apiLevelLookup) {
+ public ComputedApiLevel getApiReferenceLevel(
+ AppView<?> appView, AndroidApiLevelCompute apiLevelCompute) {
// The api level of a class is the max level of it's members, super class and interfaces.
- AndroidApiLevel computedApiLevel = minApiLevelIfEnabledOrUnknown(appView);
- for (DexType superType : allImmediateSupertypes()) {
- computedApiLevel = apiLevelLookup.apply(superType, computedApiLevel);
- if (computedApiLevel == AndroidApiLevel.UNKNOWN) {
- return AndroidApiLevel.UNKNOWN;
- }
- }
- return computedApiLevel.max(getMembersApiReferenceLevel(appView));
+ return getMembersApiReferenceLevel(
+ apiLevelCompute.computeApiLevelForDefinition(
+ allImmediateSupertypes(), apiLevelCompute.getPlatformApiLevelOrUnknown(appView)));
}
- public AndroidApiLevel getMembersApiReferenceLevel(AppView<?> appView) {
- AndroidApiLevel memberLevel = minApiLevelIfEnabledOrUnknown(appView);
+ public ComputedApiLevel getMembersApiReferenceLevel(ComputedApiLevel memberLevel) {
for (DexEncodedMember<?, ?> member : members()) {
memberLevel = memberLevel.max(member.getApiLevel());
- if (memberLevel == AndroidApiLevel.UNKNOWN) {
- return AndroidApiLevel.UNKNOWN;
+ if (memberLevel.isUnknownApiLevel()) {
+ return memberLevel;
}
}
return memberLevel;
diff --git a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
index 844b45e..cf866d4 100644
--- a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.MethodPosition;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.utils.AndroidApiLevel;
/** Type representing a method definition in the programs compilation unit and its holder. */
public final class ProgramMethod extends DexClassAndMethod
@@ -95,7 +94,7 @@
accessFlags.demoteFromStrict();
accessFlags.demoteFromSynchronized();
accessFlags.promoteToAbstract();
- getDefinition().clearApiLevelForCode(appView);
+ getDefinition().clearApiLevelForCode();
getDefinition().unsetCode();
getSimpleFeedback().unsetOptimizationInfoForAbstractMethod(this);
}
@@ -105,7 +104,7 @@
public void convertToThrowNullMethod(AppView<?> appView) {
MethodAccessFlags accessFlags = getAccessFlags();
accessFlags.demoteFromAbstract();
- getDefinition().setApiLevelForCode(AndroidApiLevel.minApiLevelIfEnabledOrUnknown(appView));
+ getDefinition().setApiLevelForCode(appView.computedMinApiLevel());
getDefinition().setCode(ThrowNullCode.get(), appView);
getSimpleFeedback().markProcessed(getDefinition(), ConstraintWithTarget.ALWAYS);
getSimpleFeedback().unsetOptimizationInfoForThrowNullMethod(this);
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/ApiModelAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/ApiModelAnalysis.java
index 7f4b9f9..45e2065 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/ApiModelAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/ApiModelAnalysis.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.graph.analysis;
import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClassAndMember;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -13,18 +14,17 @@
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.shaking.DefaultEnqueuerUseRegistry;
-import com.android.tools.r8.utils.AndroidApiLevel;
public class ApiModelAnalysis extends EnqueuerAnalysis {
private final AppView<?> appView;
- private final AndroidApiLevel minApiLevel;
private final AndroidApiLevelCompute apiCompute;
+ private final ComputedApiLevel minApiLevel;
public ApiModelAnalysis(AppView<?> appView, AndroidApiLevelCompute apiCompute) {
this.appView = appView;
- this.minApiLevel = appView.options().getMinApiLevel();
this.apiCompute = apiCompute;
+ this.minApiLevel = appView.computedMinApiLevel();
}
@Override
@@ -73,7 +73,7 @@
@Override
public void notifyFailedMethodResolutionTarget(DexEncodedMethod method) {
// We may not trace into failed resolution targets.
- method.setApiLevelForCode(AndroidApiLevel.UNKNOWN);
+ method.setApiLevelForCode(ComputedApiLevel.unknown());
}
private void computeAndSetApiLevelForDefinition(DexClassAndMember<?, ?> member) {
@@ -81,6 +81,8 @@
.getDefinition()
.setApiLevelForDefinition(
apiCompute.computeApiLevelForDefinition(
- member.getReference(), appView.dexItemFactory()));
+ member.getReference(),
+ appView.dexItemFactory(),
+ apiCompute.getPlatformApiLevelOrUnknown(appView)));
}
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
index b1055ef..c76f43f 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
@@ -4,9 +4,9 @@
package com.android.tools.r8.horizontalclassmerging;
-import static com.android.tools.r8.utils.AndroidApiLevel.minApiLevelIfEnabledOrUnknown;
import static com.google.common.base.Predicates.not;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
@@ -29,7 +29,6 @@
import com.android.tools.r8.ir.analysis.value.NumberFromIntervalValue;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.SetUtils;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
@@ -125,7 +124,7 @@
newMethodReference.withName("$r8$clinit$synthetic", dexItemFactory);
lensBuilder.recordNewMethodSignature(syntheticMethodReference, newMethodReference, true);
- AndroidApiLevel apiReferenceLevel = classInitializerMerger.getApiReferenceLevel(appView);
+ ComputedApiLevel apiReferenceLevel = classInitializerMerger.getApiReferenceLevel(appView);
DexEncodedMethod definition =
DexEncodedMethod.syntheticBuilder()
.setMethod(newMethodReference)
@@ -215,7 +214,7 @@
DexEncodedField.syntheticBuilder()
.setField(group.getClassIdField())
.setAccessFlags(FieldAccessFlags.createPublicFinalSynthetic())
- .setApiLevel(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevel(appView.computedMinApiLevel())
.build();
// For the $r8$classId synthesized fields, we try to over-approximate the set of values it may
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ClassInitializerMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ClassInitializerMerger.java
index 085276f..b1219c4 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ClassInitializerMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/code/ClassInitializerMerger.java
@@ -4,9 +4,9 @@
package com.android.tools.r8.horizontalclassmerging.code;
-import static com.android.tools.r8.utils.AndroidApiLevel.minApiLevelIfEnabledOrUnknown;
import static java.lang.Integer.max;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.cf.code.CfGoto;
import com.android.tools.r8.cf.code.CfInstruction;
@@ -36,7 +36,6 @@
import com.android.tools.r8.ir.code.Return;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.CfVersionUtils;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.ListUtils;
@@ -101,11 +100,11 @@
return null;
}
- public AndroidApiLevel getApiReferenceLevel(AppView<?> appView) {
+ public ComputedApiLevel getApiReferenceLevel(AppView<?> appView) {
assert !classInitializers.isEmpty();
return ListUtils.fold(
classInitializers,
- minApiLevelIfEnabledOrUnknown(appView),
+ appView.computedMinApiLevel(),
(accApiLevel, method) -> accApiLevel.max(method.getDefinition().getApiLevel()));
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDifferentApiReferenceLevel.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDifferentApiReferenceLevel.java
index 3b7e1e0..1f953f4 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDifferentApiReferenceLevel.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDifferentApiReferenceLevel.java
@@ -4,21 +4,21 @@
package com.android.tools.r8.horizontalclassmerging.policies;
-import com.android.tools.r8.androidapi.AndroidApiReferenceLevelCache;
+import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.horizontalclassmerging.MultiClassSameReferencePolicy;
-import com.android.tools.r8.utils.AndroidApiLevel;
-public class NoDifferentApiReferenceLevel extends MultiClassSameReferencePolicy<AndroidApiLevel> {
+public class NoDifferentApiReferenceLevel extends MultiClassSameReferencePolicy<ComputedApiLevel> {
- private final AndroidApiReferenceLevelCache apiReferenceLevelCache;
+ private final AndroidApiLevelCompute apiLevelCompute;
private final AppView<?> appView;
// TODO(b/188388130): Remove when stabilized.
private final boolean enableApiCallerIdentification;
public NoDifferentApiReferenceLevel(AppView<?> appView) {
- apiReferenceLevelCache = AndroidApiReferenceLevelCache.create(appView);
+ apiLevelCompute = AndroidApiLevelCompute.create(appView);
this.appView = appView;
enableApiCallerIdentification =
appView.options().apiModelingOptions().enableApiCallerIdentification;
@@ -35,8 +35,8 @@
}
@Override
- public AndroidApiLevel getMergeKey(DexProgramClass clazz) {
+ public ComputedApiLevel getMergeKey(DexProgramClass clazz) {
assert enableApiCallerIdentification;
- return clazz.getApiReferenceLevel(appView, apiReferenceLevelCache::lookupMax);
+ return clazz.getApiReferenceLevel(appView, apiLevelCompute);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 2b72d1e..37ce381 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -205,7 +205,6 @@
.map(prefix -> "L" + DescriptorUtils.getPackageBinaryNameFromJavaType(prefix))
.map(options.itemFactory::createString)
.collect(Collectors.toList());
- AndroidApiLevelCompute apiLevelCompute = AndroidApiLevelCompute.create(appView);
if (options.isDesugaredLibraryCompilation()) {
// Specific L8 Settings, performs all desugaring including L8 specific desugaring.
//
@@ -223,8 +222,7 @@
// - nest based access desugaring,
// - invoke-special desugaring.
assert options.desugarState.isOn();
- this.instructionDesugaring =
- CfInstructionDesugaringCollection.create(appView, apiLevelCompute);
+ this.instructionDesugaring = CfInstructionDesugaringCollection.create(appView);
this.covariantReturnTypeAnnotationTransformer = null;
this.dynamicTypeOptimization = null;
this.classInliner = null;
@@ -249,7 +247,7 @@
this.instructionDesugaring =
appView.enableWholeProgramOptimizations()
? CfInstructionDesugaringCollection.empty()
- : CfInstructionDesugaringCollection.create(appView, apiLevelCompute);
+ : CfInstructionDesugaringCollection.create(appView);
this.covariantReturnTypeAnnotationTransformer =
options.processCovariantReturnTypeAnnotations
? new CovariantReturnTypeAnnotationTransformer(this, appView.dexItemFactory())
@@ -288,7 +286,8 @@
this.typeChecker = new TypeChecker(appViewWithLiveness, VerifyTypesHelper.create(appView));
this.serviceLoaderRewriter =
options.enableServiceLoaderRewriting
- ? new ServiceLoaderRewriter(appViewWithLiveness, apiLevelCompute)
+ ? new ServiceLoaderRewriter(
+ appViewWithLiveness, AndroidApiLevelCompute.create(appView))
: null;
this.enumValueOptimizer =
options.enableEnumValueOptimization ? new EnumValueOptimizer(appViewWithLiveness) : null;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index c516da4..ed1260e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -4,8 +4,6 @@
package com.android.tools.r8.ir.desugar;
-import static com.android.tools.r8.utils.AndroidApiLevel.minApiLevelIfEnabledOrUnknown;
-
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
@@ -1470,8 +1468,7 @@
appView,
builder ->
builder
- .setApiLevelForDefinition(minApiLevelIfEnabledOrUnknown(appView))
- .setApiLevelForCode(minApiLevelIfEnabledOrUnknown(appView))
+ .disableAndroidApiLevelCheck()
.setProto(getProto(appView.dexItemFactory()))
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
.setCode(methodSig -> generateTemplateMethod(appView.options(), methodSig)));
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringCollection.java
index 8328e9b..b34a515 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringCollection.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.ir.desugar;
-import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.graph.AppView;
@@ -28,19 +27,16 @@
*/
public abstract class CfInstructionDesugaringCollection {
- public static CfInstructionDesugaringCollection create(
- AppView<?> appView, AndroidApiLevelCompute apiLevelCompute) {
+ public static CfInstructionDesugaringCollection create(AppView<?> appView) {
if (appView.options().desugarState.isOn()) {
- return new NonEmptyCfInstructionDesugaringCollection(appView, apiLevelCompute);
+ return new NonEmptyCfInstructionDesugaringCollection(appView);
}
// TODO(b/145775365): invoke-special desugaring is mandatory, since we currently can't map
// invoke-special instructions that require desugaring into IR.
if (appView.options().isGeneratingClassFiles()) {
- return NonEmptyCfInstructionDesugaringCollection.createForCfToCfNonDesugar(
- appView, apiLevelCompute);
+ return NonEmptyCfInstructionDesugaringCollection.createForCfToCfNonDesugar(appView);
}
- return NonEmptyCfInstructionDesugaringCollection.createForCfToDexNonDesugar(
- appView, apiLevelCompute);
+ return NonEmptyCfInstructionDesugaringCollection.createForCfToDexNonDesugar(appView);
}
public static CfInstructionDesugaringCollection empty() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index cd17565..a014283 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -645,7 +645,7 @@
.setApiLevelForDefinition(encodedMethod.getApiLevelForDefinition())
.setApiLevelForCode(encodedMethod.getApiLevelForCode())
.build();
- newMethod.copyMetadata(encodedMethod);
+ newMethod.copyMetadata(appView, encodedMethod);
forcefullyMovedLambdaMethodConsumer.acceptForcefullyMovedLambdaMethod(
encodedMethod.getReference(), callTarget);
@@ -736,7 +736,7 @@
.setApiLevelForDefinition(encodedMethod.getApiLevelForDefinition())
.setApiLevelForCode(encodedMethod.getApiLevelForCode())
.build();
- newMethod.copyMetadata(encodedMethod);
+ newMethod.copyMetadata(appView, encodedMethod);
forcefullyMovedLambdaMethodConsumer.acceptForcefullyMovedLambdaMethod(
encodedMethod.getReference(), callTarget);
return newMethod;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
index 66d3a56..bc5c0fa 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.ir.desugar;
-import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.errors.Unreachable;
@@ -52,12 +51,9 @@
private final DesugaredLibraryRetargeter desugaredLibraryRetargeter;
private final InterfaceMethodRewriter interfaceMethodRewriter;
private final DesugaredLibraryAPIConverter desugaredLibraryAPIConverter;
- private final AndroidApiLevelCompute apiLevelCompute;
- NonEmptyCfInstructionDesugaringCollection(
- AppView<?> appView, AndroidApiLevelCompute apiLevelCompute) {
+ NonEmptyCfInstructionDesugaringCollection(AppView<?> appView) {
this.appView = appView;
- this.apiLevelCompute = apiLevelCompute;
AlwaysThrowingInstructionDesugaring alwaysThrowingInstructionDesugaring =
appView.enableWholeProgramOptimizations()
? new AlwaysThrowingInstructionDesugaring(appView.withClassHierarchy())
@@ -131,24 +127,22 @@
}
}
- static NonEmptyCfInstructionDesugaringCollection createForCfToCfNonDesugar(
- AppView<?> appView, AndroidApiLevelCompute computeApiLevel) {
+ static NonEmptyCfInstructionDesugaringCollection createForCfToCfNonDesugar(AppView<?> appView) {
assert appView.options().desugarState.isOff();
assert appView.options().isGeneratingClassFiles();
NonEmptyCfInstructionDesugaringCollection desugaringCollection =
- new NonEmptyCfInstructionDesugaringCollection(appView, computeApiLevel);
+ new NonEmptyCfInstructionDesugaringCollection(appView);
// TODO(b/145775365): special constructor for cf-to-cf compilations with desugaring disabled.
// This should be removed once we can represent invoke-special instructions in the IR.
desugaringCollection.desugarings.add(new InvokeSpecialToSelfDesugaring(appView));
return desugaringCollection;
}
- static NonEmptyCfInstructionDesugaringCollection createForCfToDexNonDesugar(
- AppView<?> appView, AndroidApiLevelCompute computeApiLevel) {
+ static NonEmptyCfInstructionDesugaringCollection createForCfToDexNonDesugar(AppView<?> appView) {
assert appView.options().desugarState.isOff();
assert appView.options().isGeneratingDex();
NonEmptyCfInstructionDesugaringCollection desugaringCollection =
- new NonEmptyCfInstructionDesugaringCollection(appView, computeApiLevel);
+ new NonEmptyCfInstructionDesugaringCollection(appView);
desugaringCollection.desugarings.add(new InvokeSpecialToSelfDesugaring(appView));
desugaringCollection.desugarings.add(new InvokeToPrivateRewriter());
return desugaringCollection;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/ConstantDynamicClass.java b/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/ConstantDynamicClass.java
index 3f9e078..fb848df 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/ConstantDynamicClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/ConstantDynamicClass.java
@@ -6,7 +6,6 @@
import static com.android.tools.r8.ir.desugar.constantdynamic.ConstantDynamicClass.Behaviour.CACHE_CONSTANT;
import static com.android.tools.r8.ir.desugar.constantdynamic.ConstantDynamicClass.Behaviour.THROW_ICCE;
import static com.android.tools.r8.ir.desugar.constantdynamic.ConstantDynamicClass.Behaviour.THROW_NSME;
-import static com.android.tools.r8.utils.AndroidApiLevel.minApiLevelIfEnabledOrUnknown;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import com.android.tools.r8.cf.code.CfCheckCast;
@@ -56,7 +55,6 @@
import com.android.tools.r8.ir.optimize.UtilityMethodsForCodeOptimizations.MethodSynthesizerConsumer;
import com.android.tools.r8.ir.optimize.UtilityMethodsForCodeOptimizations.UtilityMethodForCodeOptimizations;
import com.android.tools.r8.synthesis.SyntheticProgramClassBuilder;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.collections.ImmutableDeque;
import com.android.tools.r8.utils.collections.ImmutableInt2ReferenceSortedMap;
import com.google.common.collect.ImmutableList;
@@ -194,12 +192,12 @@
DexEncodedField.syntheticBuilder()
.setField(this.initializedValueField)
.setAccessFlags(FieldAccessFlags.createPrivateStaticSynthetic())
- .setApiLevel(minApiLevelIfEnabledOrUnknown(appView))
+ .disableAndroidApiLevelCheck()
.build(),
DexEncodedField.syntheticBuilder()
.setField(this.constantValueField)
.setAccessFlags(FieldAccessFlags.createPrivateStaticSynthetic())
- .setApiLevel(minApiLevelIfEnabledOrUnknown(appView))
+ .disableAndroidApiLevelCheck()
.build()));
}
@@ -210,8 +208,7 @@
.setMethod(getConstMethod)
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
.setCode(generateGetterCode(builder))
- .setApiLevelForDefinition(AndroidApiLevel.S)
- .setApiLevelForCode(AndroidApiLevel.S)
+ .disableAndroidApiLevelCheck()
.build()));
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryWrapperSynthesizer.java
index 5d9e05e..14240a6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/DesugaredLibraryWrapperSynthesizer.java
@@ -4,8 +4,7 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary;
-import static com.android.tools.r8.utils.AndroidApiLevel.NOT_SET;
-
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
@@ -595,7 +594,8 @@
.setAccessFlags(newFlags)
.setCode(code)
.setApiLevelForDefinition(template.getApiLevelForDefinition())
- .setApiLevelForCode(code == null ? NOT_SET : template.getApiLevelForCode())
+ .setApiLevelForCode(
+ code == null ? ComputedApiLevel.notSet() : template.getApiLevelForCode())
.build();
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
index e1462ea..36519f8 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
@@ -4,8 +4,6 @@
package com.android.tools.r8.ir.desugar.itf;
-import static com.android.tools.r8.utils.AndroidApiLevel.minApiLevelIfEnabledOrUnknown;
-
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfNew;
import com.android.tools.r8.cf.code.CfStackInstruction;
@@ -802,8 +800,7 @@
.setAccessFlags(accessFlags)
.setCode(
createExceptionThrowingCfCode(newMethod, accessFlags, errorType, dexItemFactory))
- .setApiLevelForDefinition(minApiLevelIfEnabledOrUnknown(appView))
- .setApiLevelForCode(minApiLevelIfEnabledOrUnknown(appView))
+ .disableAndroidApiLevelCheck()
.build();
addSyntheticMethod(clazz.asProgramClass(), newEncodedMethod);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 674493f..510331b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -1088,7 +1088,7 @@
context.getDefinition().accessFlags.demoteFromSynthetic();
}
- context.getDefinition().copyMetadata(singleTargetMethod);
+ context.getDefinition().copyMetadata(appView, singleTargetMethod);
if (inlineeMayHaveInvokeMethod && options.applyInliningToInlinee) {
if (inlineeStack.size() + 1 > options.applyInliningToInlineeMaxDepth
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java
index d73ac60..7ef7216 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java
@@ -7,6 +7,7 @@
import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.contexts.CompilationContext.ProcessorContext;
import com.android.tools.r8.dex.Constants;
@@ -68,7 +69,6 @@
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
import com.android.tools.r8.utils.ListUtils;
@@ -1527,8 +1527,8 @@
.setProto(outline.buildProto())
// It is OK to set the api level to UNKNOWN since we are not interested in
// inlining the outlines anyway.
- .setApiLevelForDefinition(AndroidApiLevel.UNKNOWN)
- .setApiLevelForCode(AndroidApiLevel.UNKNOWN)
+ .setApiLevelForDefinition(ComputedApiLevel.unknown())
+ .setApiLevelForCode(ComputedApiLevel.unknown())
.setCode(m -> new OutlineCode(outline));
if (appView.options().isGeneratingClassFiles()) {
builder.setClassFileVersion(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
index a735ad9..260a5a3 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
@@ -4,8 +4,6 @@
package com.android.tools.r8.ir.optimize;
-import static com.android.tools.r8.utils.AndroidApiLevel.minApiLevelIfEnabledOrUnknown;
-
import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.graph.AppView;
@@ -180,7 +178,8 @@
DexEncodedMethod addedMethod =
createSynthesizedMethod(service, classes, methodProcessingContext);
if (appView.options().isGeneratingClassFiles()) {
- addedMethod.upgradeClassFileVersion(code.method().getClassFileVersion());
+ addedMethod.upgradeClassFileVersion(
+ code.context().getDefinition().getClassFileVersion());
}
return addedMethod;
});
@@ -206,10 +205,11 @@
builder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
.setProto(proto)
- .setApiLevelForDefinition(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevelForDefinition(appView.computedMinApiLevel())
.setApiLevelForCode(
apiLevelCompute.computeApiLevelForDefinition(
- ListUtils.map(classes, clazz -> clazz.type)))
+ ListUtils.map(classes, clazz -> clazz.type),
+ apiLevelCompute.getPlatformApiLevelOrUnknown(appView)))
.setCode(
m ->
ServiceLoaderSourceCode.generate(
@@ -248,7 +248,7 @@
private final IRCode code;
private final InvokeStatic serviceLoaderLoad;
- private InstructionListIterator iterator;
+ private final InstructionListIterator iterator;
Rewriter(IRCode code, InstructionListIterator iterator, InvokeStatic serviceLoaderLoad) {
this.iterator = iterator;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java b/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java
index aaeb960..5639925 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java
@@ -4,8 +4,6 @@
package com.android.tools.r8.ir.optimize;
-import static com.android.tools.r8.utils.AndroidApiLevel.minApiLevelIfEnabledOrUnknown;
-
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.contexts.CompilationContext.UniqueContext;
@@ -45,8 +43,8 @@
builder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
.setClassFileVersion(CfVersion.V1_8)
- .setApiLevelForDefinition(minApiLevelIfEnabledOrUnknown(appView))
- .setApiLevelForCode(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevelForDefinition(appView.computedMinApiLevel())
+ .setApiLevelForCode(appView.computedMinApiLevel())
.setCode(method -> getToStringIfNotNullCodeTemplate(method, options))
.setProto(proto));
return new UtilityMethodForCodeOptimizations(syntheticMethod);
@@ -74,8 +72,8 @@
builder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
.setClassFileVersion(CfVersion.V1_8)
- .setApiLevelForDefinition(minApiLevelIfEnabledOrUnknown(appView))
- .setApiLevelForCode(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevelForDefinition(appView.computedMinApiLevel())
+ .setApiLevelForCode(appView.computedMinApiLevel())
.setCode(
method -> getThrowClassCastExceptionIfNotNullCodeTemplate(method, options))
.setProto(proto));
@@ -104,8 +102,8 @@
builder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
.setClassFileVersion(CfVersion.V1_8)
- .setApiLevelForDefinition(minApiLevelIfEnabledOrUnknown(appView))
- .setApiLevelForCode(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevelForDefinition(appView.computedMinApiLevel())
+ .setApiLevelForCode(appView.computedMinApiLevel())
.setCode(method -> getThrowIllegalAccessErrorCodeTemplate(method, options))
.setProto(proto));
return new UtilityMethodForCodeOptimizations(syntheticMethod);
@@ -132,8 +130,8 @@
builder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
.setClassFileVersion(CfVersion.V1_8)
- .setApiLevelForDefinition(minApiLevelIfEnabledOrUnknown(appView))
- .setApiLevelForCode(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevelForDefinition(appView.computedMinApiLevel())
+ .setApiLevelForCode(appView.computedMinApiLevel())
.setCode(
method -> getThrowIncompatibleClassChangeErrorCodeTemplate(method, options))
.setProto(proto));
@@ -162,8 +160,8 @@
builder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
.setClassFileVersion(CfVersion.V1_8)
- .setApiLevelForDefinition(minApiLevelIfEnabledOrUnknown(appView))
- .setApiLevelForCode(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevelForDefinition(appView.computedMinApiLevel())
+ .setApiLevelForCode(appView.computedMinApiLevel())
.setCode(method -> getThrowNoSuchMethodErrorCodeTemplate(method, options))
.setProto(proto));
return new UtilityMethodForCodeOptimizations(syntheticMethod);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
index e392248..9997cc0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
@@ -5,7 +5,6 @@
package com.android.tools.r8.ir.optimize.enums;
import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
-import static com.android.tools.r8.utils.AndroidApiLevel.minApiLevelIfEnabledOrUnknown;
import com.android.tools.r8.contexts.CompilationContext.ProcessorContext;
import com.android.tools.r8.graph.AppView;
@@ -186,8 +185,8 @@
checkNotNullMethod
.getDefinition()
.getClassFileVersionOrElse(null))
- .setApiLevelForDefinition(minApiLevelIfEnabledOrUnknown(appView))
- .setApiLevelForCode(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevelForDefinition(appView.computedMinApiLevel())
+ .setApiLevelForCode(appView.computedMinApiLevel())
.setCode(method -> new CheckNotZeroCode(checkNotNullMethod))
.setOptimizationInfo(
checkNotNullMethod
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/LocalEnumUnboxingUtilityClass.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/LocalEnumUnboxingUtilityClass.java
index ddf8c42..ed8958d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/LocalEnumUnboxingUtilityClass.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/LocalEnumUnboxingUtilityClass.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.ir.optimize.enums;
-import static com.android.tools.r8.utils.AndroidApiLevel.minApiLevelIfEnabledOrUnknown;
import static com.android.tools.r8.utils.ConsumerUtils.emptyConsumer;
import com.android.tools.r8.cf.CfVersion;
@@ -131,8 +130,8 @@
methodBuilder ->
methodBuilder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
- .setApiLevelForDefinition(minApiLevelIfEnabledOrUnknown(appView))
- .setApiLevelForCode(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevelForDefinition(appView.computedMinApiLevel())
+ .setApiLevelForCode(appView.computedMinApiLevel())
.setCode(codeGenerator)
.setClassFileVersion(CfVersion.V1_6));
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java
index 90d49ac..182b415 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java
@@ -4,8 +4,6 @@
package com.android.tools.r8.ir.optimize.enums;
-import static com.android.tools.r8.utils.AndroidApiLevel.minApiLevelIfEnabledOrUnknown;
-
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.cf.code.CfArrayStore;
import com.android.tools.r8.cf.code.CfConstNumber;
@@ -149,8 +147,8 @@
methodBuilder ->
methodBuilder
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
- .setApiLevelForDefinition(minApiLevelIfEnabledOrUnknown(appView))
- .setApiLevelForCode(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevelForDefinition(appView.computedMinApiLevel())
+ .setApiLevelForCode(appView.computedMinApiLevel())
.setCode(codeGenerator)
.setClassFileVersion(CfVersion.V1_6));
}
@@ -232,7 +230,7 @@
dexItemFactory.createField(
sharedUtilityClassType, dexItemFactory.intArrayType, "$VALUES"))
.setAccessFlags(FieldAccessFlags.createPublicStaticFinalSynthetic())
- .setApiLevel(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevel(appView.computedMinApiLevel())
.build();
fieldAccessInfoCollectionModifierBuilder
.recordFieldReadInUnknownContext(valuesField.getReference())
@@ -249,8 +247,8 @@
.setAccessFlags(MethodAccessFlags.createForClassInitializer())
.setCode(createClassInitializerCode(sharedUtilityClassType, valuesField))
.setClassFileVersion(CfVersion.V1_6)
- .setApiLevelForDefinition(minApiLevelIfEnabledOrUnknown(appView))
- .setApiLevelForCode(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevelForDefinition(appView.computedMinApiLevel())
+ .setApiLevelForCode(appView.computedMinApiLevel())
.build();
}
@@ -295,8 +293,8 @@
.setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
.setCode(createValuesMethodCode(sharedUtilityClassType, valuesField))
.setClassFileVersion(CfVersion.V1_6)
- .setApiLevelForDefinition(minApiLevelIfEnabledOrUnknown(appView))
- .setApiLevelForCode(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevelForDefinition(appView.computedMinApiLevel())
+ .setApiLevelForCode(appView.computedMinApiLevel())
.build();
this.valuesMethod = valuesMethod;
return valuesMethod;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryFieldSynthesis.java b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryFieldSynthesis.java
index 27fa69a..5cb256c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryFieldSynthesis.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryFieldSynthesis.java
@@ -5,7 +5,6 @@
package com.android.tools.r8.ir.optimize.library;
import static com.android.tools.r8.graph.DexLibraryClass.asLibraryClassOrNull;
-import static com.android.tools.r8.utils.AndroidApiLevel.minApiLevelIfEnabledOrUnknown;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
@@ -39,7 +38,7 @@
.setAccessFlags(
FieldAccessFlags.fromCfAccessFlags(
Constants.ACC_PRIVATE | Constants.ACC_FINAL))
- .setApiLevel(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevel(appView.computedMinApiLevel())
// Will be traced by the enqueuer.
.disableAndroidApiLevelCheck()
.build());
diff --git a/src/main/java/com/android/tools/r8/shaking/ClassInitFieldSynthesizer.java b/src/main/java/com/android/tools/r8/shaking/ClassInitFieldSynthesizer.java
index 129acae..19bbe92 100644
--- a/src/main/java/com/android/tools/r8/shaking/ClassInitFieldSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/shaking/ClassInitFieldSynthesizer.java
@@ -5,7 +5,6 @@
package com.android.tools.r8.shaking;
import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
-import static com.android.tools.r8.utils.AndroidApiLevel.minApiLevelIfEnabledOrUnknown;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
@@ -87,7 +86,7 @@
.dexItemFactory()
.createField(clazz.type, clinitField.type, clinitField.name))
.setAccessFlags(accessFlags)
- .setApiLevel(minApiLevelIfEnabledOrUnknown(appView))
+ .setApiLevel(appView.computedMinApiLevel())
.build();
clazz.appendStaticField(encodedClinitField);
}
diff --git a/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java b/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
index 941bcff..227cbf7 100644
--- a/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
+++ b/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
@@ -7,6 +7,7 @@
import static com.android.tools.r8.ir.desugar.records.RecordRewriterHelper.isInvokeDynamicOnRecord;
import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.code.CfOrDexInstruction;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
@@ -21,26 +22,25 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.UseRegistry;
-import com.android.tools.r8.utils.AndroidApiLevel;
import java.util.ListIterator;
public class DefaultEnqueuerUseRegistry extends UseRegistry<ProgramMethod> {
protected final AppView<? extends AppInfoWithClassHierarchy> appView;
protected final Enqueuer enqueuer;
- private final AndroidApiLevelCompute computeApiLevel;
- private AndroidApiLevel maxApiReferenceLevel;
+ private final AndroidApiLevelCompute apiLevelCompute;
+ private ComputedApiLevel maxApiReferenceLevel;
public DefaultEnqueuerUseRegistry(
AppView<? extends AppInfoWithClassHierarchy> appView,
ProgramMethod context,
Enqueuer enqueuer,
- AndroidApiLevelCompute computeApiLevel) {
+ AndroidApiLevelCompute apiLevelCompute) {
super(appView, context);
this.appView = appView;
this.enqueuer = enqueuer;
- this.computeApiLevel = computeApiLevel;
- this.maxApiReferenceLevel = appView.options().getMinApiLevel();
+ this.apiLevelCompute = apiLevelCompute;
+ maxApiReferenceLevel = appView.computedMinApiLevel();
}
public DexProgramClass getContextHolder() {
@@ -223,14 +223,18 @@
if (reference.isDexMember()) {
maxApiReferenceLevel =
maxApiReferenceLevel.max(
- computeApiLevel.computeApiLevelForDefinition(
- reference.asDexMember(), appView.dexItemFactory()));
+ apiLevelCompute.computeApiLevelForDefinition(
+ reference.asDexMember(),
+ appView.dexItemFactory(),
+ apiLevelCompute.getPlatformApiLevelOrUnknown(appView)));
}
maxApiReferenceLevel =
- maxApiReferenceLevel.max(computeApiLevel.computeApiLevelForLibraryReference(reference));
+ maxApiReferenceLevel.max(
+ apiLevelCompute.computeApiLevelForLibraryReference(
+ reference, apiLevelCompute.getPlatformApiLevelOrUnknown(appView)));
}
- public AndroidApiLevel getMaxApiReferenceLevel() {
+ public ComputedApiLevel getMaxApiReferenceLevel() {
return maxApiReferenceLevel;
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index c539364..9f30d38 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -502,7 +502,7 @@
liveFields = new LiveFieldsSet(graphReporter::registerField);
apiLevelCompute = AndroidApiLevelCompute.create(appView);
if (mode.isInitialTreeShaking()) {
- desugaring = CfInstructionDesugaringCollection.create(appView, apiLevelCompute);
+ desugaring = CfInstructionDesugaringCollection.create(appView);
interfaceProcessor = new InterfaceProcessor(appView);
} else {
desugaring = CfInstructionDesugaringCollection.empty();
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 4f116de..9396f50 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -8,7 +8,8 @@
import static com.android.tools.r8.ir.code.Invoke.Type.DIRECT;
import static com.android.tools.r8.ir.code.Invoke.Type.STATIC;
-import com.android.tools.r8.androidapi.AndroidApiReferenceLevelCache;
+import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
@@ -66,7 +67,6 @@
import com.android.tools.r8.ir.synthetic.AbstractSynthesizedCode;
import com.android.tools.r8.ir.synthetic.ForwardMethodSourceCode;
import com.android.tools.r8.logging.Log;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.CollectionUtils;
import com.android.tools.r8.utils.FieldSignatureEquivalence;
@@ -222,7 +222,7 @@
private final MethodPoolCollection methodPoolCollection;
private final Timing timing;
private Collection<DexMethod> invokes;
- private final AndroidApiReferenceLevelCache apiReferenceLevelCache;
+ private final AndroidApiLevelCompute apiLevelCompute;
private final OptimizationFeedback feedback = OptimizationFeedbackSimple.getInstance();
@@ -261,7 +261,7 @@
this.executorService = executorService;
this.methodPoolCollection = new MethodPoolCollection(appView, subtypingInfo);
this.lensBuilder = new VerticalClassMergerGraphLens.Builder(appView.dexItemFactory());
- this.apiReferenceLevelCache = AndroidApiReferenceLevelCache.create(appView);
+ this.apiLevelCompute = AndroidApiLevelCompute.create(appView);
this.timing = timing;
Iterable<DexProgramClass> classes = application.classesWithDeterministicOrder();
@@ -531,11 +531,9 @@
// Only merge if api reference level of source class is equal to target class. The check is
// somewhat expensive.
if (appView.options().apiModelingOptions().enableApiCallerIdentification) {
- AndroidApiLevel sourceApiLevel =
- sourceClass.getApiReferenceLevel(appView, apiReferenceLevelCache::lookupMax);
- AndroidApiLevel targetApiLevel =
- targetClass.getApiReferenceLevel(appView, apiReferenceLevelCache::lookupMax);
- if (sourceApiLevel != targetApiLevel) {
+ ComputedApiLevel sourceApiLevel = sourceClass.getApiReferenceLevel(appView, apiLevelCompute);
+ ComputedApiLevel targetApiLevel = targetClass.getApiReferenceLevel(appView, apiLevelCompute);
+ if (!sourceApiLevel.equals(targetApiLevel)) {
if (Log.ENABLED) {
AbortReason.API_REFERENCE_LEVEL.printLogMessageForClass(sourceClass);
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java
index 56a9d20..0af4bf0 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java
@@ -3,8 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.synthesis;
-import static com.android.tools.r8.utils.AndroidApiLevel.NOT_SET;
-
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexAnnotationSet;
@@ -20,7 +19,6 @@
import com.android.tools.r8.ir.optimize.info.DefaultMethodOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
-import com.android.tools.r8.utils.AndroidApiLevel;
public class SyntheticMethodBuilder {
@@ -39,8 +37,8 @@
private MethodTypeSignature genericSignature = MethodTypeSignature.noSignature();
private DexAnnotationSet annotations = DexAnnotationSet.empty();
private ParameterAnnotationsList parameterAnnotationsList = ParameterAnnotationsList.empty();
- private AndroidApiLevel apiLevelForDefinition = NOT_SET;
- private AndroidApiLevel apiLevelForCode = NOT_SET;
+ private ComputedApiLevel apiLevelForDefinition = ComputedApiLevel.notSet();
+ private ComputedApiLevel apiLevelForCode = ComputedApiLevel.notSet();
private MethodOptimizationInfo optimizationInfo = DefaultMethodOptimizationInfo.getInstance();
private boolean checkAndroidApiLevels = true;
@@ -109,12 +107,12 @@
return this;
}
- public SyntheticMethodBuilder setApiLevelForDefinition(AndroidApiLevel apiLevelForDefinition) {
+ public SyntheticMethodBuilder setApiLevelForDefinition(ComputedApiLevel apiLevelForDefinition) {
this.apiLevelForDefinition = apiLevelForDefinition;
return this;
}
- public SyntheticMethodBuilder setApiLevelForCode(AndroidApiLevel apiLevelForCode) {
+ public SyntheticMethodBuilder setApiLevelForCode(ComputedApiLevel apiLevelForCode) {
this.apiLevelForCode = apiLevelForCode;
return this;
}
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 6b82664..38934f2 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.utils;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.utils.structural.Ordered;
import java.util.Arrays;
import java.util.List;
@@ -43,9 +42,7 @@
R(30),
S(31),
Sv2(32),
- ANDROID_PLATFORM(10000),
- UNKNOWN(10001),
- NOT_SET(10002);
+ ANDROID_PLATFORM(10000);
// 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.
@@ -78,13 +75,6 @@
return DexVersion.getDexVersion(this);
}
- public static AndroidApiLevel minApiLevelIfEnabledOrUnknown(AppView<?> appView) {
- InternalOptions options = appView.options();
- return options.apiModelingOptions().enableApiCallerIdentification
- ? options.getMinApiLevel()
- : UNKNOWN;
- }
-
public static List<AndroidApiLevel> getAndroidApiLevelsSorted() {
return Arrays.asList(AndroidApiLevel.values());
}
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 c4a7396..73cf09f 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.utils;
import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.graph.LibraryMethod;
import com.android.tools.r8.graph.ProgramMethod;
@@ -15,10 +16,6 @@
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;
}
@@ -32,12 +29,13 @@
LibraryMethod method,
AndroidApiLevelCompute androidApiLevelCompute,
InternalOptions options) {
- AndroidApiLevel apiLevel =
- androidApiLevelCompute.computeApiLevelForLibraryReference(method.getReference());
- if (apiLevel == AndroidApiLevel.UNKNOWN) {
+ ComputedApiLevel apiLevel =
+ androidApiLevelCompute.computeApiLevelForLibraryReference(
+ method.getReference(), ComputedApiLevel.unknown());
+ if (apiLevel.isUnknownApiLevel()) {
return false;
}
assert options.apiModelingOptions().enableApiCallerIdentification;
- return apiLevel.isLessThanOrEqualTo(options.getMinApiLevel());
+ return apiLevel.asKnownApiLevel().getApiLevel().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 a807bba..624e70e 100644
--- a/src/main/java/com/android/tools/r8/utils/DexVersion.java
+++ b/src/main/java/com/android/tools/r8/utils/DexVersion.java
@@ -77,7 +77,6 @@
case L_MR1:
case M:
return DexVersion.V35;
- 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 ea7c922..1cbbc21 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;
+import static com.android.tools.r8.utils.AndroidApiLevel.ANDROID_PLATFORM;
+
import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.DataResourceConsumer;
@@ -17,6 +19,7 @@
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.Version;
import com.android.tools.r8.androidapi.AndroidApiForHashingClass;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.dex.Marker;
import com.android.tools.r8.dex.Marker.Backend;
@@ -424,7 +427,7 @@
}
public boolean isAndroidPlatform() {
- return minApiLevel == AndroidApiLevel.ANDROID_PLATFORM;
+ return minApiLevel == ANDROID_PLATFORM;
}
public boolean isDesugaredLibraryCompilation() {
@@ -564,7 +567,6 @@
public void setMinApiLevel(AndroidApiLevel minApiLevel) {
assert minApiLevel != null;
- assert minApiLevel.isLessThan(AndroidApiLevel.UNKNOWN);
this.minApiLevel = minApiLevel;
}
@@ -1470,7 +1472,7 @@
public Map<MethodReference, AndroidApiLevel> methodApiMapping = new HashMap<>();
public Map<FieldReference, AndroidApiLevel> fieldApiMapping = new HashMap<>();
public Map<ClassReference, AndroidApiLevel> classApiMapping = new HashMap<>();
- public BiConsumer<MethodReference, AndroidApiLevel> tracedMethodApiLevelCallback = null;
+ public BiConsumer<MethodReference, ComputedApiLevel> tracedMethodApiLevelCallback = null;
public boolean enableApiCallerIdentification = true;
public boolean checkAllApiReferencesAreSet = true;
@@ -1498,7 +1500,7 @@
@Override
public AndroidApiLevel getApiLevel() {
- return classApiMapping.getOrDefault(classReference, AndroidApiLevel.UNKNOWN);
+ return classApiMapping.getOrDefault(classReference, ANDROID_PLATFORM);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 53886e2..2d0cc12 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -867,8 +867,6 @@
case J_MR2:
case K_WATCH:
case ANDROID_PLATFORM:
- case UNKNOWN:
- case NOT_SET:
return false;
default:
return true;
diff --git a/src/test/java/com/android/tools/r8/apimodel/AndroidApiHashingDatabaseBuilderGenerator.java b/src/test/java/com/android/tools/r8/apimodel/AndroidApiHashingDatabaseBuilderGenerator.java
index d7db635..300eed5 100644
--- a/src/test/java/com/android/tools/r8/apimodel/AndroidApiHashingDatabaseBuilderGenerator.java
+++ b/src/test/java/com/android/tools/r8/apimodel/AndroidApiHashingDatabaseBuilderGenerator.java
@@ -103,8 +103,7 @@
for (int i = 0; i < integers.size(); i++) {
indices[i] = integers.get(i);
AndroidApiLevel androidApiLevel = apiLevelMap.get(integers.get(i));
- apiLevel[i] =
- (byte) (androidApiLevel == AndroidApiLevel.NOT_SET ? -1 : androidApiLevel.getLevel());
+ apiLevel[i] = (byte) (androidApiLevel == null ? -1 : androidApiLevel.getLevel());
}
try (FileOutputStream fileOutputStream = new FileOutputStream(pathToIndices.toFile());
@@ -160,7 +159,7 @@
return ((reference, apiLevel) -> {
AndroidApiLevel existingMethod = apiLevelMap.put(reference.hashCode(), apiLevel);
if (existingMethod != null) {
- apiLevelMap.put(reference.hashCode(), AndroidApiLevel.NOT_SET);
+ apiLevelMap.put(reference.hashCode(), null);
Pair<DexReference, AndroidApiLevel> existingPair = reverseMap.get(reference.hashCode());
addAmbiguousEntry(existingPair.getSecond(), existingPair.getFirst(), ambiguousMap);
addAmbiguousEntry(apiLevel, reference, ambiguousMap);
diff --git a/src/test/java/com/android/tools/r8/apimodel/AndroidApiHashingDatabaseBuilderGeneratorTest.java b/src/test/java/com/android/tools/r8/apimodel/AndroidApiHashingDatabaseBuilderGeneratorTest.java
index 88d53c1..9bbc751 100644
--- a/src/test/java/com/android/tools/r8/apimodel/AndroidApiHashingDatabaseBuilderGeneratorTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/AndroidApiHashingDatabaseBuilderGeneratorTest.java
@@ -126,7 +126,7 @@
AndroidApiVersionsXmlParser.getParsedApiClasses(API_VERSIONS_XML.toFile(), API_LEVEL);
DexItemFactory factory = new DexItemFactory();
AndroidApiLevelHashingDatabaseImpl androidApiLevelDatabase =
- new AndroidApiLevelHashingDatabaseImpl(factory, ImmutableList.of());
+ new AndroidApiLevelHashingDatabaseImpl(ImmutableList.of());
parsedApiClasses.forEach(
parsedApiClass -> {
DexType type = factory.createType(parsedApiClass.getClassReference().getDescriptor());
@@ -137,9 +137,13 @@
methodReferences.forEach(
methodReference -> {
DexMethod method = factory.createMethod(methodReference);
- androidApiLevelDatabase
- .getMethodApiLevel(method)
- .isLessThanOrEqualTo(methodApiLevel);
+ AndroidApiLevel androidApiLevel;
+ if (factory.objectMembers.isObjectMember(method)) {
+ androidApiLevel = AndroidApiLevel.B;
+ } else {
+ androidApiLevel = androidApiLevelDatabase.getMethodApiLevel(method);
+ }
+ androidApiLevel.isLessThanOrEqualTo(methodApiLevel);
}));
parsedApiClass.visitFieldReferences(
(fieldApiLevel, fieldReferences) ->
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelVirtualDispatchLinkInterfaceTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelVirtualDispatchLinkInterfaceTest.java
index c87f2cc..d4127e8 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelVirtualDispatchLinkInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelVirtualDispatchLinkInterfaceTest.java
@@ -63,15 +63,22 @@
}
public static class AccessibilityNodeInfo$AccessibilityAction {
+
+ private int i;
+
+ public AccessibilityNodeInfo$AccessibilityAction(int i, CharSequence sequence) {
+ this.i = i;
+ }
+
int describeContents() {
- return 42;
+ return i;
}
}
public static class Main {
public static void main(String[] args) {
- new AccessibilityNodeInfo$AccessibilityAction().describeContents();
+ new AccessibilityNodeInfo$AccessibilityAction(42, "foobar").describeContents();
}
}
}
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
index 8e5cc58..c8ee027 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
@@ -7,6 +7,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestCompilerBuilder;
import com.android.tools.r8.TestParameters;
@@ -42,7 +43,7 @@
public static <T extends TestCompilerBuilder<?, ?, ?, ?, ?>>
ThrowableConsumer<T> setMockApiLevelForMethod(
- Constructor constructor, AndroidApiLevel apiLevel) {
+ Constructor<?> constructor, AndroidApiLevel apiLevel) {
return compilerBuilder -> {
compilerBuilder.addOptionsModification(
options -> {
@@ -118,7 +119,12 @@
return compilerBuilder -> {
compilerBuilder.addOptionsModification(
options -> {
- options.apiModelingOptions().tracedMethodApiLevelCallback = consumer;
+ options.apiModelingOptions().tracedMethodApiLevelCallback =
+ (methodReference, computedApiLevel) -> {
+ assertTrue(computedApiLevel.isKnownApiLevel());
+ consumer.accept(
+ methodReference, computedApiLevel.asKnownApiLevel().getApiLevel());
+ };
});
};
}
diff --git a/src/test/java/com/android/tools/r8/shaking/ServiceLoaderTest.java b/src/test/java/com/android/tools/r8/shaking/ServiceLoaderTest.java
index 86ccd24..51bd0cf 100644
--- a/src/test/java/com/android/tools/r8/shaking/ServiceLoaderTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/ServiceLoaderTest.java
@@ -189,7 +189,7 @@
new DataResourceConsumerForTesting(options.dataResourceConsumer);
options.dataResourceConsumer = dataResourceConsumer;
})
- .setMinApi(parameters.getRuntime())
+ .setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), OtherTestClass.class)
.assertSuccessWithOutput(expectedOutput)
.inspector();