Model api level of referenced types for live methods and fields
Bug: 188388130
Bug: 138781768
Bug: 188499184
Bug: 188498051
Change-Id: I426198648662be0d0b81e9f6079ae07c378dd6e9
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 1e10fa9..0611cdd5 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
import com.android.tools.r8.ir.optimize.info.DefaultFieldOptimizationInfo;
+import com.android.tools.r8.ir.optimize.info.DefaultFieldOptimizationWithMinApiInfo;
import com.android.tools.r8.ir.optimize.info.FieldOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.MutableFieldOptimizationInfo;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
@@ -132,6 +133,10 @@
optimizationInfo = info;
}
+ public void setMinApiOptimizationInfo(DefaultFieldOptimizationWithMinApiInfo info) {
+ optimizationInfo = info;
+ }
+
@Override
public KotlinFieldLevelInfo getKotlinInfo() {
return kotlinMemberInfo;
diff --git a/src/main/java/com/android/tools/r8/graph/DexMember.java b/src/main/java/com/android/tools/r8/graph/DexMember.java
index 9b62855..ae9d9fb 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMember.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMember.java
@@ -3,7 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.google.common.collect.Iterables;
+import java.util.Map;
import java.util.function.Function;
public abstract class DexMember<D extends DexEncodedMember<D, R>, R extends DexMember<D, R>>
@@ -60,4 +62,14 @@
public Iterable<DexType> getReferencedBaseTypes(DexItemFactory dexItemFactory) {
return Iterables.transform(getReferencedTypes(), type -> type.toBaseType(dexItemFactory));
}
+
+ public AndroidApiLevel computeApiLevelForReferencedTypes(
+ AppView<?> appView, Map<DexReference, AndroidApiLevel> apiLevelMap) {
+ AndroidApiLevel minApiLevel = appView.options().minApiLevel;
+ AndroidApiLevel apiLevel = minApiLevel;
+ for (DexType type : getReferencedBaseTypes(appView.dexItemFactory())) {
+ apiLevel = apiLevel.max(apiLevelMap.getOrDefault(type, minApiLevel));
+ }
+ return apiLevel;
+ }
}
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
new file mode 100644
index 0000000..f93437e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/analysis/ApiModelAnalysis.java
@@ -0,0 +1,82 @@
+// 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.graph.analysis;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMember;
+import com.android.tools.r8.graph.DexMember;
+import com.android.tools.r8.graph.DexReference;
+import com.android.tools.r8.graph.ProgramDefinition;
+import com.android.tools.r8.graph.ProgramField;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.optimize.info.DefaultFieldOptimizationWithMinApiInfo;
+import com.android.tools.r8.ir.optimize.info.DefaultMethodOptimizationWithMinApiInfo;
+import com.android.tools.r8.ir.optimize.info.MemberOptimizationInfo;
+import com.android.tools.r8.shaking.DefaultEnqueuerUseRegistry;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.util.Map;
+
+public class ApiModelAnalysis extends EnqueuerAnalysis {
+
+ private final AppView<?> appView;
+ private final AndroidApiLevel minApiLevel;
+ private final Map<DexReference, AndroidApiLevel> referenceToApiLevelMap;
+
+ public ApiModelAnalysis(
+ AppView<?> appView, Map<DexReference, AndroidApiLevel> referenceToApiLevelMap) {
+ this.appView = appView;
+ this.minApiLevel = appView.options().minApiLevel;
+ this.referenceToApiLevelMap = referenceToApiLevelMap;
+ }
+
+ @Override
+ public void processNewlyLiveField(ProgramField field, ProgramDefinition context) {
+ setApiLevelForMember(
+ field.getDefinition(), computeApiLevelForReferencedTypes(field.getReference()));
+ }
+
+ @Override
+ public void processNewlyLiveMethod(ProgramMethod method, ProgramDefinition context) {
+ setApiLevelForMember(
+ method.getDefinition(), computeApiLevelForReferencedTypes(method.getReference()));
+ }
+
+ @Override
+ public void processTracedCode(ProgramMethod method, DefaultEnqueuerUseRegistry registry) {
+ assert registry.getMaxApiReferenceLevel().isGreaterThanOrEqualTo(minApiLevel);
+ setApiLevelForMember(method.getDefinition(), registry.getMaxApiReferenceLevel());
+ }
+
+ private void setApiLevelForMember(DexEncodedMember<?, ?> member, AndroidApiLevel apiLevel) {
+ // To not have mutable update information for all members that all has min api level we
+ // swap the default optimization info for one with that marks the api level to be min api.
+ MemberOptimizationInfo<?> optimizationInfo = member.getOptimizationInfo();
+ if (!optimizationInfo.isMutableOptimizationInfo() && apiLevel == minApiLevel) {
+ member.apply(
+ field -> {
+ field.setMinApiOptimizationInfo(DefaultFieldOptimizationWithMinApiInfo.getInstance());
+ },
+ method -> {
+ method.setMinApiOptimizationInfo(DefaultMethodOptimizationWithMinApiInfo.getInstance());
+ });
+ } else {
+ AndroidApiLevel maxApiLevel =
+ optimizationInfo.hasApiReferenceLevel()
+ ? apiLevel.max(optimizationInfo.getApiReferenceLevel(minApiLevel))
+ : apiLevel;
+ member.apply(
+ field -> {
+ field.getMutableOptimizationInfo().setApiReferenceLevel(maxApiLevel);
+ },
+ method -> {
+ method.getMutableOptimizationInfo().setApiReferenceLevel(maxApiLevel);
+ });
+ }
+ }
+
+ private AndroidApiLevel computeApiLevelForReferencedTypes(DexMember<?, ?> member) {
+ return member.computeApiLevelForReferencedTypes(appView, referenceToApiLevelMap);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
index 9e09724..dc87519 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.ProgramDefinition;
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.shaking.Enqueuer;
import com.android.tools.r8.shaking.EnqueuerWorklist;
import com.android.tools.r8.utils.Timing;
@@ -26,6 +27,9 @@
/** Called when a method is found to be live. */
public void processNewlyLiveMethod(ProgramMethod method, ProgramDefinition context) {}
+ /** Called when a method's code has been processed by the registry. */
+ public void processTracedCode(ProgramMethod method, DefaultEnqueuerUseRegistry registry) {}
+
/**
* Called when the Enqueuer reaches a fixpoint. This may happen multiple times, since each
* analysis may enqueue items into the worklist upon the fixpoint using {@param worklist}.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultFieldOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultFieldOptimizationInfo.java
index 0408418..533174b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultFieldOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultFieldOptimizationInfo.java
@@ -8,12 +8,13 @@
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
+import com.android.tools.r8.utils.AndroidApiLevel;
public class DefaultFieldOptimizationInfo extends FieldOptimizationInfo {
private static final DefaultFieldOptimizationInfo INSTANCE = new DefaultFieldOptimizationInfo();
- private DefaultFieldOptimizationInfo() {}
+ protected DefaultFieldOptimizationInfo() {}
public static DefaultFieldOptimizationInfo getInstance() {
return INSTANCE;
@@ -55,6 +56,11 @@
}
@Override
+ public AndroidApiLevel getApiReferenceLevel(AndroidApiLevel minApi) {
+ throw new RuntimeException("Should never be called");
+ }
+
+ @Override
public MutableFieldOptimizationInfo toMutableOptimizationInfo() {
return new MutableFieldOptimizationInfo();
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultFieldOptimizationWithMinApiInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultFieldOptimizationWithMinApiInfo.java
new file mode 100644
index 0000000..27c6f43
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultFieldOptimizationWithMinApiInfo.java
@@ -0,0 +1,35 @@
+// Copyright (c) 2019, 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.ir.optimize.info;
+
+import com.android.tools.r8.utils.AndroidApiLevel;
+
+public class DefaultFieldOptimizationWithMinApiInfo extends DefaultFieldOptimizationInfo {
+
+ private static final DefaultFieldOptimizationWithMinApiInfo INSTANCE =
+ new DefaultFieldOptimizationWithMinApiInfo();
+
+ public static DefaultFieldOptimizationWithMinApiInfo getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public boolean hasApiReferenceLevel() {
+ return true;
+ }
+
+ @Override
+ public AndroidApiLevel getApiReferenceLevel(AndroidApiLevel minApi) {
+ return minApi;
+ }
+
+ @Override
+ public MutableFieldOptimizationInfo toMutableOptimizationInfo() {
+ MutableFieldOptimizationInfo updatableFieldOptimizationInfo = super.toMutableOptimizationInfo();
+ // Use null to specify that the min api is set to minApi.
+ updatableFieldOptimizationInfo.setMinApiReferenceLevel();
+ return updatableFieldOptimizationInfo;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
index 1df189a..0aed133 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
@@ -180,7 +180,7 @@
@Override
public AndroidApiLevel getApiReferenceLevel(AndroidApiLevel minApi) {
- return UNKNOWN_API_REFERENCE_LEVEL;
+ throw new RuntimeException("Should never be called");
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationWithMinApiInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationWithMinApiInfo.java
index a5e21d9..0638369 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationWithMinApiInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationWithMinApiInfo.java
@@ -30,7 +30,7 @@
MutableMethodOptimizationInfo updatableMethodOptimizationInfo =
super.toMutableOptimizationInfo();
// Use null to specify that the min api is set to minApi.
- updatableMethodOptimizationInfo.setApiReferenceLevel(null);
+ updatableMethodOptimizationInfo.setMinApiReferenceLevel();
return updatableMethodOptimizationInfo;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MemberOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MemberOptimizationInfo.java
index e9ce890..910669d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MemberOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MemberOptimizationInfo.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.ir.optimize.info;
+import com.android.tools.r8.utils.AndroidApiLevel;
+
public interface MemberOptimizationInfo<
T extends MemberOptimizationInfo<T> & MutableOptimizationInfo> {
@@ -19,5 +21,11 @@
return null;
}
+ default boolean hasApiReferenceLevel() {
+ return false;
+ }
+
+ AndroidApiLevel getApiReferenceLevel(AndroidApiLevel minApi);
+
T toMutableOptimizationInfo();
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
index 41c145f..748d82d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
@@ -15,7 +15,6 @@
import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
-import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.OptionalBool;
import java.util.BitSet;
@@ -95,10 +94,6 @@
public abstract boolean returnValueHasBeenPropagated();
- public abstract AndroidApiLevel getApiReferenceLevel(AndroidApiLevel minApi);
-
- public abstract boolean hasApiReferenceLevel();
-
public static OptionalBool isApiSafeForInlining(
MethodOptimizationInfo caller, MethodOptimizationInfo inlinee, InternalOptions options) {
if (!options.apiModelingOptions().enableApiCallerIdentification) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java
index 9150ea0..d00377e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java
@@ -15,6 +15,8 @@
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import java.util.Optional;
import java.util.Set;
/**
@@ -36,6 +38,7 @@
private int readBits = 0;
private ClassTypeElement dynamicLowerBoundType = null;
private TypeElement dynamicUpperBoundType = null;
+ private Optional<AndroidApiLevel> apiReferenceLevel = null;
public MutableFieldOptimizationInfo fixupClassTypeReferences(
AppView<? extends AppInfoWithClassHierarchy> appView, GraphLens lens) {
@@ -150,4 +153,29 @@
public MutableFieldOptimizationInfo asMutableFieldOptimizationInfo() {
return this;
}
+
+ @SuppressWarnings("OptionalAssignedToNull")
+ @Override
+ public boolean hasApiReferenceLevel() {
+ return apiReferenceLevel != null;
+ }
+
+ @Override
+ public AndroidApiLevel getApiReferenceLevel(AndroidApiLevel minApi) {
+ assert hasApiReferenceLevel();
+ return apiReferenceLevel.orElse(minApi);
+ }
+
+ @Override
+ @SuppressWarnings("OptionalAssignedToNull")
+ public void setMinApiReferenceLevel() {
+ assert apiReferenceLevel == null;
+ this.apiReferenceLevel = Optional.empty();
+ }
+
+ @Override
+ public void setApiReferenceLevel(AndroidApiLevel apiReferenceLevel) {
+ assert apiReferenceLevel != null;
+ this.apiReferenceLevel = Optional.of(apiReferenceLevel);
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableMethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableMethodOptimizationInfo.java
index 95d817f..1b47801 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableMethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableMethodOptimizationInfo.java
@@ -498,6 +498,19 @@
}
@Override
+ @SuppressWarnings("OptionalAssignedToNull")
+ public void setMinApiReferenceLevel() {
+ assert apiReferenceLevel == null;
+ this.apiReferenceLevel = Optional.empty();
+ }
+
+ @Override
+ public void setApiReferenceLevel(AndroidApiLevel apiReferenceLevel) {
+ assert apiReferenceLevel != null;
+ this.apiReferenceLevel = Optional.of(apiReferenceLevel);
+ }
+
+ @Override
public boolean isMutableOptimizationInfo() {
return true;
}
@@ -512,11 +525,6 @@
return this;
}
- public MutableMethodOptimizationInfo setApiReferenceLevel(AndroidApiLevel apiReferenceLevel) {
- this.apiReferenceLevel = Optional.ofNullable(apiReferenceLevel);
- return this;
- }
-
public MutableMethodOptimizationInfo mutableCopy() {
return new MutableMethodOptimizationInfo(this);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableOptimizationInfo.java
index bf34966..db7bd1d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableOptimizationInfo.java
@@ -4,4 +4,11 @@
package com.android.tools.r8.ir.optimize.info;
-public interface MutableOptimizationInfo {}
+import com.android.tools.r8.utils.AndroidApiLevel;
+
+public interface MutableOptimizationInfo {
+
+ void setMinApiReferenceLevel();
+
+ void setApiReferenceLevel(AndroidApiLevel apiReferenceLevel);
+}
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 e93af67..b560847 100644
--- a/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
+++ b/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
@@ -182,6 +182,13 @@
}
private void setMaxApiReferenceLevel(DexReference reference) {
+ if (reference.isDexMember()) {
+ this.maxApiReferenceLevel =
+ maxApiReferenceLevel.max(
+ reference
+ .asDexMember()
+ .computeApiLevelForReferencedTypes(appView, apiReferenceMapping));
+ }
this.maxApiReferenceLevel =
maxApiReferenceLevel.max(apiReferenceMapping.getOrDefault(reference, 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 d2c666a..16d8707 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -80,6 +80,7 @@
import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.graph.UseRegistry.MethodHandleUse;
+import com.android.tools.r8.graph.analysis.ApiModelAnalysis;
import com.android.tools.r8.graph.analysis.DesugaredLibraryConversionWrapperAnalysis;
import com.android.tools.r8.graph.analysis.EnqueuerAnalysis;
import com.android.tools.r8.graph.analysis.EnqueuerCheckCastAnalysis;
@@ -102,8 +103,6 @@
import com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter;
import com.android.tools.r8.ir.desugar.LambdaClass;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
-import com.android.tools.r8.ir.optimize.info.DefaultMethodOptimizationInfo;
-import com.android.tools.r8.ir.optimize.info.DefaultMethodOptimizationWithMinApiInfo;
import com.android.tools.r8.kotlin.KotlinMetadataEnqueuerExtension;
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.naming.identifiernamestring.IdentifierNameStringLookupResult;
@@ -2983,6 +2982,9 @@
&& appView.options().getProguardConfiguration().getKeepAttributes().signature) {
registerAnalysis(new GenericSignatureEnqueuerAnalysis(enqueuerDefinitionSupplier));
}
+ if (appView.options().apiModelingOptions().enableApiCallerIdentification) {
+ registerAnalysis(new ApiModelAnalysis(appView, referenceToApiLevelMap));
+ }
if (mode.isInitialTreeShaking()) {
// This is simulating the effect of the "root set" applied rules.
// This is done only in the initial pass, in subsequent passes the "rules" are reapplied
@@ -3910,19 +3912,8 @@
DefaultEnqueuerUseRegistry registry =
useRegistryFactory.create(appView, method, this, referenceToApiLevelMap);
method.registerCodeReferences(registry);
- DexEncodedMethod methodDefinition = method.getDefinition();
- AndroidApiLevel maxApiReferenceLevel = registry.getMaxApiReferenceLevel();
- assert maxApiReferenceLevel.isGreaterThanOrEqualTo(options.minApiLevel);
- // To not have mutable update information for all methods that all has min api level we
- // swap the default optimization info for one with that marks the api level to be min api.
- if (methodDefinition.getOptimizationInfo() == DefaultMethodOptimizationInfo.getInstance()
- && maxApiReferenceLevel == options.minApiLevel) {
- methodDefinition.setMinApiOptimizationInfo(
- DefaultMethodOptimizationWithMinApiInfo.getInstance());
- return;
- }
- methodDefinition.setOptimizationInfo(
- methodDefinition.getMutableOptimizationInfo().setApiReferenceLevel(maxApiReferenceLevel));
+ // Notify analyses.
+ analyses.forEach(analysis -> analysis.processTracedCode(method, registry));
}
private void checkDefinitionForSoftPinning(ProgramDefinition definition) {
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelInlineMethodWithApiTypeTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelInlineMethodWithApiTypeTest.java
index 5a88c7c..f6996e9 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelInlineMethodWithApiTypeTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelInlineMethodWithApiTypeTest.java
@@ -6,6 +6,9 @@
import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForType;
import static com.android.tools.r8.apimodel.ApiModelingTestHelper.verifyThat;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.NoHorizontalClassMerging;
import com.android.tools.r8.TestBase;
@@ -34,9 +37,8 @@
@Test
public void testR8() throws Exception {
- Method apiCallerApiLevel1 = ApiCaller.class.getDeclaredMethod("apiLevel22");
- Method apiCallerCallerApiLevel1 = ApiCallerCaller.class.getDeclaredMethod("apiLevel22");
- Method otherCallerApiLevel1 = OtherCaller.class.getDeclaredMethod("apiLevel1");
+ Method apiCallerApiLevel22 = ApiCaller.class.getDeclaredMethod("apiLevel22");
+ Method apiCallerCallerApiLevel22 = ApiCallerCaller.class.getDeclaredMethod("apiLevel22");
testForR8(parameters.getBackend())
.addProgramClasses(ApiCaller.class, ApiCallerCaller.class, OtherCaller.class, Main.class)
.addLibraryClasses(ApiType.class)
@@ -50,16 +52,15 @@
.addRunClasspathClasses(ApiType.class)
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines(ApiType.class.getName())
- .inspect(verifyThat(parameters, apiCallerApiLevel1).inlinedInto(apiCallerCallerApiLevel1))
- // TODO(b/138781768): Should not be inlined
- .inspect(
- verifyThat(parameters, apiCallerCallerApiLevel1).inlinedInto(otherCallerApiLevel1));
+ .inspect(verifyThat(parameters, apiCallerApiLevel22).inlinedInto(apiCallerCallerApiLevel22))
+ .inspect(inspector -> assertThat(inspector.clazz(OtherCaller.class), not(isPresent())));
}
public static class ApiType {}
@NoHorizontalClassMerging
public static class ApiCaller {
+
public static ApiType apiLevel22() throws Exception {
// The reflective call here is to ensure that the setting of A's api level is not based on
// a method reference to `Api` and only because of the type reference in the field `api`.
@@ -81,6 +82,7 @@
}
}
+ @NoHorizontalClassMerging
public static class OtherCaller {
public static void apiLevel1() throws Exception {