Test completeness of profile rewriting on tivi
Bug: b/267592755
Change-Id: I4921ec85ead3f2a2a24bd7b2ae2d4a2964690412
diff --git a/build.gradle b/build.gradle
index 870b615..a6feb9b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -2298,6 +2298,12 @@
systemProperty 'runtimes', project.property('runtimes')
}
+ if (project.hasProperty('art_profile_rewriting_completeness_check')) {
+ String key = 'com.android.tools.r8.artprofilerewritingcompletenesscheck'
+ String value = project.property('art_profile_rewriting_completeness_check')
+ systemProperty key, value
+ }
+
if (project.hasProperty('slow_tests')) {
systemProperty 'slow_tests', project.property('slow_tests')
}
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 7fac411..1cc9392 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -71,6 +71,7 @@
import com.android.tools.r8.optimize.interfaces.analysis.CfOpenClosedInterfacesAnalysis;
import com.android.tools.r8.optimize.proto.ProtoNormalizer;
import com.android.tools.r8.origin.CommandLineOrigin;
+import com.android.tools.r8.profile.art.ArtProfileCompletenessChecker;
import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
import com.android.tools.r8.repackaging.Repackaging;
import com.android.tools.r8.repackaging.RepackagingLens;
@@ -279,6 +280,8 @@
SyntheticItems.collectSyntheticInputs(appView);
}
+ assert ArtProfileCompletenessChecker.verify(appView);
+
// Check for potentially having pass-through of Cf-code for kotlin libraries.
options.enableCfByteCodePassThrough =
options.isGeneratingClassFiles() && KotlinMetadataUtils.mayProcessKotlinMetadata(appView);
@@ -374,6 +377,7 @@
assert appView.rootSet().verifyKeptMethodsAreTargetedAndLive(appViewWithLiveness);
assert appView.rootSet().verifyKeptTypesAreLive(appViewWithLiveness);
assert appView.rootSet().verifyKeptItemsAreKept(appView);
+ assert ArtProfileCompletenessChecker.verify(appView);
appView.rootSet().checkAllRulesAreUsed(options);
if (options.apiModelingOptions().reportUnknownApiReferences) {
@@ -482,6 +486,8 @@
classMergingEnqueuerExtensionBuilder.build(appView.graphLens());
classMergingEnqueuerExtensionBuilder = null;
+ assert ArtProfileCompletenessChecker.verify(appView);
+
if (!isKotlinLibraryCompilationWithInlinePassThrough
&& options.getProguardConfiguration().isOptimizing()) {
if (options.enableVerticalClassMerging) {
@@ -502,6 +508,8 @@
}
assert appView.verticallyMergedClasses() != null;
+ assert ArtProfileCompletenessChecker.verify(appView);
+
HorizontalClassMerger.createForInitialClassMerging(appViewWithLiveness)
.runIfNecessary(executorService, timing, runtimeTypeCheckInfo);
}
@@ -524,6 +532,8 @@
// TODO: we should avoid removing liveness.
Set<DexType> prunedTypes = appView.withLiveness().appInfo().getPrunedTypes();
+ assert ArtProfileCompletenessChecker.verify(appView);
+
timing.begin("Create IR");
CfgPrinter printer = options.printCfg ? new CfgPrinter() : null;
try {
@@ -535,6 +545,8 @@
timing.end();
}
+ assert ArtProfileCompletenessChecker.verify(appView);
+
// Clear the reference type lattice element cache to reduce memory pressure.
appView.dexItemFactory().clearTypeElementsCache();
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 6a0652a..b5fe77a 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -199,7 +199,7 @@
public static <T extends AppInfo> AppView<T> createForD8(T appInfo) {
return new AppView<>(
appInfo,
- ArtProfileCollection.createInitialArtProfileCollection(appInfo.options()),
+ ArtProfileCollection.createInitialArtProfileCollection(appInfo, appInfo.options()),
WholeProgramOptimizations.OFF,
defaultTypeRewriter(appInfo));
}
@@ -216,7 +216,7 @@
T appInfo, TypeRewriter mapper, Timing timing) {
return new AppView<>(
appInfo,
- ArtProfileCollection.createInitialArtProfileCollection(appInfo.options()),
+ ArtProfileCollection.createInitialArtProfileCollection(appInfo, appInfo.options()),
WholeProgramOptimizations.OFF,
mapper,
timing);
@@ -240,7 +240,7 @@
startupOrder);
return new AppView<>(
appInfo,
- ArtProfileCollection.createInitialArtProfileCollection(application.options),
+ ArtProfileCollection.createInitialArtProfileCollection(appInfo, appInfo.options()),
WholeProgramOptimizations.ON,
defaultTypeRewriter(appInfo));
}
@@ -248,7 +248,7 @@
public static <T extends AppInfo> AppView<T> createForL8(T appInfo, TypeRewriter mapper) {
return new AppView<>(
appInfo,
- ArtProfileCollection.createInitialArtProfileCollection(appInfo.options()),
+ ArtProfileCollection.createInitialArtProfileCollection(appInfo, appInfo.options()),
WholeProgramOptimizations.OFF,
mapper);
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
index 8050e50..b84809e 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.horizontalclassmerging.code.SyntheticInitializerConverter;
import com.android.tools.r8.ir.code.Invoke.Type;
+import com.android.tools.r8.profile.art.ArtProfileCompletenessChecker;
import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
@@ -91,6 +92,8 @@
: IRCodeProvider.createThrowing();
run(runtimeTypeCheckInfo, codeProvider, executorService, timing);
+ assert ArtProfileCompletenessChecker.verify(appView);
+
// Clear type elements cache after IR building.
appView.dexItemFactory().clearTypeElementsCache();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index dbd19bd..22a544e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -1484,7 +1484,8 @@
// type.
if (castType.isClassType()
&& castType.isAlwaysNull(appViewWithLiveness)
- && !outValue.hasDebugUsers()) {
+ && !outValue.hasDebugUsers()
+ && options.testing.enableUtilityMethodsForCodeOptimizations) {
// Replace all usages of the out-value by null.
it.previous();
Value nullValue = it.insertConstNullInstruction(code, options);
diff --git a/src/main/java/com/android/tools/r8/profile/art/ArtProfileCollection.java b/src/main/java/com/android/tools/r8/profile/art/ArtProfileCollection.java
index 2cdb3e0..e7012b8 100644
--- a/src/main/java/com/android/tools/r8/profile/art/ArtProfileCollection.java
+++ b/src/main/java/com/android/tools/r8/profile/art/ArtProfileCollection.java
@@ -4,11 +4,14 @@
package com.android.tools.r8.profile.art;
+import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.InternalOptions;
import java.util.ArrayList;
import java.util.Collection;
@@ -16,17 +19,15 @@
public abstract class ArtProfileCollection {
- public static ArtProfileCollection createInitialArtProfileCollection(InternalOptions options) {
+ public static ArtProfileCollection createInitialArtProfileCollection(
+ AppInfo appInfo, InternalOptions options) {
ArtProfileOptions artProfileOptions = options.getArtProfileOptions();
Collection<ArtProfileForRewriting> artProfilesForRewriting =
artProfileOptions.getArtProfilesForRewriting();
- if (artProfilesForRewriting.isEmpty()) {
- return empty();
- }
- if (artProfileOptions.isPassthrough()) {
- return passthrough();
- }
- List<ArtProfile> artProfiles = new ArrayList<>(artProfilesForRewriting.size());
+ List<ArtProfile> artProfiles =
+ new ArrayList<>(
+ artProfilesForRewriting.size()
+ + BooleanUtils.intValue(artProfileOptions.isCompletenessCheckForTestingEnabled()));
for (ArtProfileForRewriting artProfileForRewriting :
options.getArtProfileOptions().getArtProfilesForRewriting()) {
ArtProfileProvider artProfileProvider = artProfileForRewriting.getArtProfileProvider();
@@ -35,17 +36,31 @@
artProfileForRewriting.getArtProfileProvider().getArtProfile(artProfileBuilder);
artProfiles.add(artProfileBuilder.build());
}
+ if (artProfileOptions.isCompletenessCheckForTestingEnabled()) {
+ artProfiles.add(createCompleteArtProfile(appInfo));
+ }
+ if (artProfiles.isEmpty()) {
+ return empty();
+ }
return new NonEmptyArtProfileCollection(artProfiles);
}
+ private static ArtProfile createCompleteArtProfile(AppInfo appInfo) {
+ ArtProfile.Builder artProfileBuilder = ArtProfile.builder();
+ for (DexProgramClass clazz : appInfo.classesWithDeterministicOrder()) {
+ artProfileBuilder.addRule(ArtProfileClassRule.builder().setType(clazz.getType()).build());
+ clazz.forEachMethod(
+ method ->
+ artProfileBuilder.addRule(
+ ArtProfileMethodRule.builder().setMethod(method.getReference()).build()));
+ }
+ return artProfileBuilder.build();
+ }
+
public static EmptyArtProfileCollection empty() {
return EmptyArtProfileCollection.getInstance();
}
- public static PassthroughArtProfileCollection passthrough() {
- return PassthroughArtProfileCollection.getInstance();
- }
-
public abstract boolean isNonEmpty();
public abstract NonEmptyArtProfileCollection asNonEmpty();
diff --git a/src/main/java/com/android/tools/r8/profile/art/ArtProfileCompletenessChecker.java b/src/main/java/com/android/tools/r8/profile/art/ArtProfileCompletenessChecker.java
new file mode 100644
index 0000000..581db1b
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/profile/art/ArtProfileCompletenessChecker.java
@@ -0,0 +1,50 @@
+// Copyright (c) 2023, 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.profile.art;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexReference;
+import com.android.tools.r8.utils.StringUtils;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ArtProfileCompletenessChecker {
+
+ public static boolean verify(AppView<?> appView) {
+ if (appView.options().getArtProfileOptions().isCompletenessCheckForTestingEnabled()) {
+ ArtProfile completeArtProfile = appView.getArtProfileCollection().asNonEmpty().getLast();
+ assert verifyProfileIsComplete(appView, completeArtProfile);
+ }
+ return true;
+ }
+
+ private static boolean verifyProfileIsComplete(AppView<?> appView, ArtProfile artProfile) {
+ assert !appView.getSyntheticItems().hasPendingSyntheticClasses();
+ List<DexReference> missing = new ArrayList<>();
+ for (DexProgramClass clazz : appView.appInfo().classesWithDeterministicOrder()) {
+ if (appView.horizontallyMergedClasses().hasBeenMergedIntoDifferentType(clazz.getType())
+ || (appView.hasVerticallyMergedClasses()
+ && appView.verticallyMergedClasses().hasBeenMergedIntoSubtype(clazz.getType()))) {
+ continue;
+ }
+ if (!artProfile.containsClassRule(clazz.getType())) {
+ missing.add(clazz.getType());
+ }
+ for (DexEncodedMethod method : clazz.methods()) {
+ if (!artProfile.containsMethodRule(method.getReference())) {
+ missing.add(method.getReference());
+ }
+ }
+ }
+ if (!missing.isEmpty()) {
+ String message =
+ StringUtils.join(System.lineSeparator(), missing, DexReference::toSmaliString);
+ assert false : message;
+ }
+ return true;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/profile/art/ArtProfileOptions.java b/src/main/java/com/android/tools/r8/profile/art/ArtProfileOptions.java
index 231a2d6..42e11f7 100644
--- a/src/main/java/com/android/tools/r8/profile/art/ArtProfileOptions.java
+++ b/src/main/java/com/android/tools/r8/profile/art/ArtProfileOptions.java
@@ -4,13 +4,17 @@
package com.android.tools.r8.profile.art;
+import static com.android.tools.r8.utils.SystemPropertyUtils.parseSystemPropertyOrDefault;
+
import java.util.Collection;
import java.util.Collections;
public class ArtProfileOptions {
private Collection<ArtProfileForRewriting> artProfilesForRewriting = Collections.emptyList();
- private boolean passthrough;
+ private boolean enableCompletenessCheckForTesting =
+ parseSystemPropertyOrDefault(
+ "com.android.tools.r8.artprofilerewritingcompletenesscheck", false);
public ArtProfileOptions() {}
@@ -18,17 +22,18 @@
return artProfilesForRewriting;
}
+ public boolean isCompletenessCheckForTestingEnabled() {
+ return enableCompletenessCheckForTesting;
+ }
+
public ArtProfileOptions setArtProfilesForRewriting(Collection<ArtProfileForRewriting> inputs) {
this.artProfilesForRewriting = inputs;
return this;
}
- public boolean isPassthrough() {
- return passthrough;
- }
-
- public ArtProfileOptions setPassthrough(boolean passthrough) {
- this.passthrough = passthrough;
+ public ArtProfileOptions setEnableCompletenessCheckForTesting(
+ boolean enableCompletenessCheckForTesting) {
+ this.enableCompletenessCheckForTesting = enableCompletenessCheckForTesting;
return this;
}
}
diff --git a/src/main/java/com/android/tools/r8/profile/art/NonEmptyArtProfileCollection.java b/src/main/java/com/android/tools/r8/profile/art/NonEmptyArtProfileCollection.java
index b196906..d7f72ef 100644
--- a/src/main/java/com/android/tools/r8/profile/art/NonEmptyArtProfileCollection.java
+++ b/src/main/java/com/android/tools/r8/profile/art/NonEmptyArtProfileCollection.java
@@ -10,17 +10,19 @@
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.InternalOptions;
-import com.google.common.collect.ImmutableList;
+import com.android.tools.r8.utils.ListUtils;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
+import java.util.List;
import java.util.function.Function;
public class NonEmptyArtProfileCollection extends ArtProfileCollection
implements Iterable<ArtProfile> {
- private final Collection<ArtProfile> artProfiles;
+ private final List<ArtProfile> artProfiles;
- public NonEmptyArtProfileCollection(Collection<ArtProfile> artProfiles) {
+ public NonEmptyArtProfileCollection(List<ArtProfile> artProfiles) {
this.artProfiles = artProfiles;
}
@@ -34,6 +36,10 @@
return this;
}
+ public ArtProfile getLast() {
+ return ListUtils.last(artProfiles);
+ }
+
@Override
public Iterator<ArtProfile> iterator() {
return artProfiles.iterator();
@@ -53,6 +59,14 @@
@Override
public void supplyConsumers(AppView<?> appView) {
+ if (appView.options().getArtProfileOptions().isCompletenessCheckForTestingEnabled()) {
+ assert ArtProfileCompletenessChecker.verify(appView);
+ ListUtils.removeLast(artProfiles);
+ if (artProfiles.isEmpty()) {
+ appView.setArtProfileCollection(ArtProfileCollection.empty());
+ return;
+ }
+ }
NonEmptyArtProfileCollection collection =
appView.getNamingLens().isIdentityLens()
? this
@@ -75,11 +89,10 @@
}
private NonEmptyArtProfileCollection map(Function<ArtProfile, ArtProfile> fn) {
- ImmutableList.Builder<ArtProfile> newArtProfiles =
- ImmutableList.builderWithExpectedSize(artProfiles.size());
+ List<ArtProfile> newArtProfiles = new ArrayList<>(artProfiles.size());
for (ArtProfile artProfile : artProfiles) {
newArtProfiles.add(fn.apply(artProfile));
}
- return new NonEmptyArtProfileCollection(newArtProfiles.build());
+ return new NonEmptyArtProfileCollection(newArtProfiles);
}
}
diff --git a/src/main/java/com/android/tools/r8/profile/art/PassthroughArtProfileCollection.java b/src/main/java/com/android/tools/r8/profile/art/PassthroughArtProfileCollection.java
deleted file mode 100644
index ac92f64..0000000
--- a/src/main/java/com/android/tools/r8/profile/art/PassthroughArtProfileCollection.java
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (c) 2022, 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.profile.art;
-
-import com.android.tools.r8.TextInputStream;
-import com.android.tools.r8.TextOutputStream;
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.GraphLens;
-import com.android.tools.r8.graph.PrunedItems;
-import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.profile.art.ArtProfileBuilderUtils.MutableArtProfileClassRule;
-import com.android.tools.r8.profile.art.ArtProfileBuilderUtils.MutableArtProfileMethodRule;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.UncheckedIOException;
-import java.util.function.Consumer;
-
-public class PassthroughArtProfileCollection extends ArtProfileCollection {
-
- private static final PassthroughArtProfileCollection INSTANCE =
- new PassthroughArtProfileCollection();
-
- private PassthroughArtProfileCollection() {}
-
- static PassthroughArtProfileCollection getInstance() {
- return INSTANCE;
- }
-
- @Override
- public boolean isNonEmpty() {
- return false;
- }
-
- @Override
- public NonEmptyArtProfileCollection asNonEmpty() {
- return null;
- }
-
- @Override
- public ArtProfileCollection rewrittenWithLens(GraphLens lens) {
- return this;
- }
-
- @Override
- public ArtProfileCollection rewrittenWithLens(NamingLens lens, DexItemFactory dexItemFactory) {
- return this;
- }
-
- @Override
- public void supplyConsumers(AppView<?> appView) {
- for (ArtProfileForRewriting artProfileForRewriting :
- appView.options().getArtProfileOptions().getArtProfilesForRewriting()) {
- ArtProfileProvider artProfileProvider = artProfileForRewriting.getArtProfileProvider();
- ArtProfileConsumer artProfileConsumer =
- EmptyArtProfileConsumer.orEmpty(artProfileForRewriting.getResidualArtProfileConsumer());
- supplyArtProfileConsumer(appView, artProfileConsumer, artProfileProvider);
- artProfileConsumer.finished(appView.reporter());
- }
- }
-
- private void supplyArtProfileConsumer(
- AppView<?> appView,
- ArtProfileConsumer artProfileConsumer,
- ArtProfileProvider artProfileProvider) {
- ArtProfileConsumerSupplier artProfileConsumerSupplier =
- new ArtProfileConsumerSupplier(artProfileConsumer);
- try {
- ArtProfileRuleConsumer ruleConsumer =
- EmptyArtProfileRuleConsumer.orEmpty(artProfileConsumer.getRuleConsumer());
- artProfileProvider.getArtProfile(
- new ArtProfileBuilder() {
-
- @Override
- public ArtProfileBuilder addClassRule(
- Consumer<ArtProfileClassRuleBuilder> classRuleBuilderConsumer) {
- MutableArtProfileClassRule classRule = new MutableArtProfileClassRule();
- classRuleBuilderConsumer.accept(classRule);
- ruleConsumer.acceptClassRule(
- classRule.getClassReference(), classRule.getClassRuleInfo());
- artProfileConsumerSupplier.supply(classRule);
- return this;
- }
-
- @Override
- public ArtProfileBuilder addMethodRule(
- Consumer<ArtProfileMethodRuleBuilder> methodRuleBuilderConsumer) {
- MutableArtProfileMethodRule methodRule = new MutableArtProfileMethodRule();
- methodRuleBuilderConsumer.accept(methodRule);
- ruleConsumer.acceptMethodRule(
- methodRule.getMethodReference(), methodRule.getMethodRuleInfo());
- artProfileConsumerSupplier.supply(methodRule);
- return this;
- }
-
- @Override
- public ArtProfileBuilder addHumanReadableArtProfile(
- TextInputStream textInputStream,
- Consumer<HumanReadableArtProfileParserBuilder> parserBuilderConsumer) {
- HumanReadableArtProfileParser.Builder parserBuilder =
- HumanReadableArtProfileParser.builder()
- .setReporter(appView.reporter())
- .setProfileBuilder(this);
- parserBuilderConsumer.accept(parserBuilder);
- HumanReadableArtProfileParser parser = parserBuilder.build();
- parser.parse(textInputStream, artProfileProvider.getOrigin());
- return this;
- }
- });
- } finally {
- artProfileConsumerSupplier.close();
- }
- }
-
- @Override
- public ArtProfileCollection withoutPrunedItems(PrunedItems prunedItems) {
- return this;
- }
-
- private static class ArtProfileConsumerSupplier {
-
- private final OutputStreamWriter outputStreamWriter;
-
- ArtProfileConsumerSupplier(ArtProfileConsumer artProfileConsumer) {
- TextOutputStream textOutputStream = artProfileConsumer.getHumanReadableArtProfileConsumer();
- this.outputStreamWriter =
- textOutputStream != null
- ? new OutputStreamWriter(
- textOutputStream.getOutputStream(), textOutputStream.getCharset())
- : null;
- ;
- }
-
- void supply(MutableArtProfileClassRule classRule) {
- if (outputStreamWriter != null) {
- try {
- classRule.writeHumanReadableRuleString(outputStreamWriter);
- outputStreamWriter.write('\n');
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
- }
-
- void supply(MutableArtProfileMethodRule methodRule) {
- if (outputStreamWriter != null) {
- try {
- methodRule.writeHumanReadableRuleString(outputStreamWriter);
- outputStreamWriter.write('\n');
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
- }
-
- void close() {
- if (outputStreamWriter != null) {
- try {
- outputStreamWriter.close();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
- }
- }
-}
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 2c06cad..f91b466 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -2095,6 +2095,7 @@
public boolean enableSwitchToIfRewriting = true;
public boolean enableEnumUnboxingDebugLogs =
System.getProperty("com.android.tools.r8.enableEnumUnboxingDebugLogs") != null;
+ public boolean enableUtilityMethodsForCodeOptimizations = true;
public boolean forceRedundantConstNumberRemoval = false;
public boolean enableExperimentalDesugaredLibraryKeepRuleGenerator = false;
public boolean invertConditionals = false;
diff --git a/src/test/java/com/android/tools/r8/internal/opensourceapps/TiviTest.java b/src/test/java/com/android/tools/r8/internal/opensourceapps/TiviTest.java
index eef3dcf..26aa1b1 100644
--- a/src/test/java/com/android/tools/r8/internal/opensourceapps/TiviTest.java
+++ b/src/test/java/com/android/tools/r8/internal/opensourceapps/TiviTest.java
@@ -48,6 +48,17 @@
public void testR8() throws Exception {
testForR8(Backend.DEX)
.addProgramFiles(outDirectory.resolve("program.jar"))
+ .addOptionsModification(options -> options.enableEnumUnboxing = false)
+ .addOptionsModification(options -> options.outline.enabled = false)
+ .addOptionsModification(
+ options -> options.apiModelingOptions().enableOutliningOfMethods = false)
+ .addOptionsModification(
+ options -> options.apiModelingOptions().enableStubbingOfClasses = false)
+ .addOptionsModification(options -> options.callSiteOptimizationOptions().setEnabled(false))
+ .addOptionsModification(
+ options -> options.testing.enableUtilityMethodsForCodeOptimizations = false)
+ .addOptionsModification(
+ options -> options.getArtProfileOptions().setEnableCompletenessCheckForTesting(true))
.apply(this::configure)
.compile();
}
diff --git a/tools/test.py b/tools/test.py
index a4e7b6e..e7e2b99 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -78,6 +78,10 @@
result.add_option('--all-tests', '--all_tests',
help='Run tests in all configurations.',
default=False, action='store_true')
+ result.add_option('--art-profile-rewriting-completeness-check',
+ '--art_profile_rewriting_completeness_check',
+ help='Enable completeness check for ART profile rewriting.',
+ default=False, action='store_true')
result.add_option('--slow-tests', '--slow_tests',
help='Also run slow tests.',
default=False, action='store_true')
@@ -287,6 +291,8 @@
gradle_args.append('-Ponly_internal')
if options.all_tests:
gradle_args.append('-Pall_tests')
+ if options.art_profile_rewriting_completeness_check:
+ gradle_args.append('-Part_profile_rewriting_completeness_check=1')
if options.slow_tests:
gradle_args.append('-Pslow_tests=1')
if options.tool: