Implement ProfileAdditions using StartupProfile
Bug: b/271822426
Change-Id: I20a52ca8bb1c77136d959c056a2d2fcaef88c6c8
diff --git a/src/main/java/com/android/tools/r8/dex/StartupMixedSectionLayoutStrategy.java b/src/main/java/com/android/tools/r8/dex/StartupMixedSectionLayoutStrategy.java
index afab1b3..e848e3b 100644
--- a/src/main/java/com/android/tools/r8/dex/StartupMixedSectionLayoutStrategy.java
+++ b/src/main/java/com/android/tools/r8/dex/StartupMixedSectionLayoutStrategy.java
@@ -6,9 +6,9 @@
import com.android.tools.r8.dex.FileWriter.MixedSectionOffsets;
import com.android.tools.r8.experimental.startup.StartupProfile;
-import com.android.tools.r8.experimental.startup.profile.StartupClass;
-import com.android.tools.r8.experimental.startup.profile.StartupItem;
-import com.android.tools.r8.experimental.startup.profile.StartupMethod;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileClassRule;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileMethodRule;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileRule;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationDirectory;
@@ -82,7 +82,7 @@
virtualFile.classes().size());
LensCodeRewriterUtils rewriter = new LensCodeRewriterUtils(appView, true);
StartupIndexedItemCollection indexedItemCollection = new StartupIndexedItemCollection();
- for (StartupItem startupItem : startupProfileForWriting.getItems()) {
+ for (StartupProfileRule startupItem : startupProfileForWriting.getRules()) {
startupItem.accept(
startupClass ->
collectStartupItems(startupClass, indexedItemCollection, virtualFileDefinitions),
@@ -93,7 +93,7 @@
}
private void collectStartupItems(
- StartupClass startupClass,
+ StartupProfileClassRule startupClass,
StartupIndexedItemCollection indexedItemCollection,
Map<DexType, DexProgramClass> virtualFileDefinitions) {
DexProgramClass definition = virtualFileDefinitions.get(startupClass.getReference());
@@ -116,7 +116,7 @@
}
private void collectStartupItems(
- StartupMethod startupMethod,
+ StartupProfileMethodRule startupMethod,
StartupIndexedItemCollection indexedItemCollection,
Map<DexType, DexProgramClass> virtualFileDefinitions,
LensCodeRewriterUtils rewriter) {
diff --git a/src/main/java/com/android/tools/r8/dex/VirtualFile.java b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
index aea0add..cf56867 100644
--- a/src/main/java/com/android/tools/r8/dex/VirtualFile.java
+++ b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
@@ -1335,7 +1335,7 @@
private static Predicate<DexProgramClass> getStartupClassPredicate(
StartupProfile startupProfile) {
- return clazz -> startupProfile.contains(clazz.getType());
+ return clazz -> startupProfile.containsClassRule(clazz.getType());
}
public List<DexProgramClass> getStartupClasses() {
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/EmptyStartupProfile.java b/src/main/java/com/android/tools/r8/experimental/startup/EmptyStartupProfile.java
index 36e470b..a2e3fe9 100644
--- a/src/main/java/com/android/tools/r8/experimental/startup/EmptyStartupProfile.java
+++ b/src/main/java/com/android/tools/r8/experimental/startup/EmptyStartupProfile.java
@@ -4,13 +4,16 @@
package com.android.tools.r8.experimental.startup;
-import com.android.tools.r8.experimental.startup.profile.StartupItem;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileClassRule;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileMethodRule;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileRule;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.synthesis.SyntheticItems;
+import com.android.tools.r8.utils.ThrowingConsumer;
import java.util.Collection;
import java.util.Collections;
@@ -19,17 +22,34 @@
EmptyStartupProfile() {}
@Override
- public boolean contains(DexMethod method) {
+ public boolean containsClassRule(DexType type) {
return false;
}
@Override
- public boolean contains(DexType type) {
+ public boolean containsMethodRule(DexMethod method) {
return false;
}
@Override
- public Collection<StartupItem> getItems() {
+ public <E1 extends Exception, E2 extends Exception> void forEachRule(
+ ThrowingConsumer<StartupProfileClassRule, E1> classRuleConsumer,
+ ThrowingConsumer<StartupProfileMethodRule, E2> methodRuleConsumer) {
+ // Intentionally empty.
+ }
+
+ @Override
+ public StartupProfileClassRule getClassRule(DexType type) {
+ return null;
+ }
+
+ @Override
+ public StartupProfileMethodRule getMethodRule(DexMethod method) {
+ return null;
+ }
+
+ @Override
+ public Collection<StartupProfileRule> getRules() {
return Collections.emptyList();
}
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/StartupCompleteness.java b/src/main/java/com/android/tools/r8/experimental/startup/StartupCompleteness.java
index 68764cd..c7ae80d 100644
--- a/src/main/java/com/android/tools/r8/experimental/startup/StartupCompleteness.java
+++ b/src/main/java/com/android/tools/r8/experimental/startup/StartupCompleteness.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.experimental.startup;
-import com.android.tools.r8.experimental.startup.profile.StartupItem;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileRule;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProgramClass;
@@ -72,7 +72,7 @@
private Set<DexReference> computeStartupItems() {
Set<DexReference> startupItems = Sets.newIdentityHashSet();
- for (StartupItem startupItem : startupProfile.getItems()) {
+ for (StartupProfileRule startupItem : startupProfile.getRules()) {
startupItem.accept(
startupClass -> startupItems.add(startupClass.getReference()),
startupMethod -> startupItems.add(startupMethod.getReference()));
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/StartupProfile.java b/src/main/java/com/android/tools/r8/experimental/startup/StartupProfile.java
index fe54f24..3e4f660 100644
--- a/src/main/java/com/android/tools/r8/experimental/startup/StartupProfile.java
+++ b/src/main/java/com/android/tools/r8/experimental/startup/StartupProfile.java
@@ -6,18 +6,18 @@
import com.android.tools.r8.TextInputStream;
import com.android.tools.r8.experimental.startup.profile.NonEmptyStartupProfile;
-import com.android.tools.r8.experimental.startup.profile.StartupClass;
-import com.android.tools.r8.experimental.startup.profile.StartupItem;
-import com.android.tools.r8.experimental.startup.profile.StartupMethod;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileClassRule;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileMethodRule;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileRule;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexDefinitionSupplier;
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;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.PrunedItems;
+import com.android.tools.r8.profile.AbstractProfile;
+import com.android.tools.r8.profile.AbstractProfileRule;
import com.android.tools.r8.profile.art.ArtProfileBuilderUtils;
import com.android.tools.r8.profile.art.HumanReadableArtProfileParser;
import com.android.tools.r8.profile.art.HumanReadableArtProfileParserBuilder;
@@ -35,7 +35,8 @@
import java.util.List;
import java.util.function.Consumer;
-public abstract class StartupProfile {
+public abstract class StartupProfile
+ implements AbstractProfile<StartupProfileClassRule, StartupProfileMethodRule> {
protected StartupProfile() {}
@@ -57,7 +58,7 @@
return empty();
}
StartupProfile.Builder builder = StartupProfile.builder();
- for (StartupItem startupItem : startupProfile.getItems()) {
+ for (StartupProfileRule startupItem : startupProfile.getRules()) {
builder.addStartupItem(startupItem);
}
return builder.build();
@@ -78,7 +79,7 @@
public static StartupProfile merge(Collection<StartupProfile> startupProfiles) {
Builder builder = builder();
for (StartupProfile startupProfile : startupProfiles) {
- startupProfile.getItems().forEach(builder::addStartupItem);
+ startupProfile.getRules().forEach(builder::addStartupItem);
}
return builder.build();
}
@@ -121,11 +122,7 @@
return StartupProfile.merge(startupProfiles);
}
- public abstract boolean contains(DexMethod method);
-
- public abstract boolean contains(DexType type);
-
- public abstract Collection<StartupItem> getItems();
+ public abstract Collection<StartupProfileRule> getRules();
public abstract boolean isEmpty();
@@ -136,14 +133,18 @@
public abstract StartupProfile withoutPrunedItems(
PrunedItems prunedItems, SyntheticItems syntheticItems);
- public static class Builder implements StartupProfileBuilder {
+ public static class Builder
+ implements AbstractProfile.Builder<
+ StartupProfileClassRule, StartupProfileMethodRule, StartupProfile, Builder>,
+ StartupProfileBuilder {
private final DexItemFactory dexItemFactory;
private final MissingStartupProfileItemsDiagnostic.Builder missingItemsDiagnosticBuilder;
private Reporter reporter;
private final StartupProfileProvider startupProfileProvider;
- private final LinkedHashMap<DexReference, StartupItem> startupItems = new LinkedHashMap<>();
+ private final LinkedHashMap<DexReference, StartupProfileRule> startupItems =
+ new LinkedHashMap<>();
Builder() {
this.dexItemFactory = null;
@@ -163,10 +164,26 @@
}
@Override
+ public Builder addRule(AbstractProfileRule rule) {
+ return addStartupItem(rule.asStartupProfileRule());
+ }
+
+ @Override
+ public Builder addClassRule(StartupProfileClassRule classRule) {
+ return addStartupItem(classRule);
+ }
+
+ @Override
+ public Builder addMethodRule(StartupProfileMethodRule methodRule) {
+ return addStartupItem(methodRule);
+ }
+
+ @Override
public Builder addStartupClass(Consumer<StartupClassBuilder> startupClassBuilderConsumer) {
- StartupClass.Builder startupClassBuilder = StartupClass.builder(dexItemFactory);
+ StartupProfileClassRule.Builder startupClassBuilder =
+ StartupProfileClassRule.builder(dexItemFactory);
startupClassBuilderConsumer.accept(startupClassBuilder);
- StartupClass startupClass = startupClassBuilder.build();
+ StartupProfileClassRule startupClass = startupClassBuilder.build();
if (missingItemsDiagnosticBuilder.registerStartupClass(startupClass)) {
return this;
}
@@ -175,9 +192,10 @@
@Override
public Builder addStartupMethod(Consumer<StartupMethodBuilder> startupMethodBuilderConsumer) {
- StartupMethod.Builder startupMethodBuilder = StartupMethod.builder(dexItemFactory);
+ StartupProfileMethodRule.Builder startupMethodBuilder =
+ StartupProfileMethodRule.builder(dexItemFactory);
startupMethodBuilderConsumer.accept(startupMethodBuilder);
- StartupMethod startupMethod = startupMethodBuilder.build();
+ StartupProfileMethodRule startupMethod = startupMethodBuilder.build();
if (missingItemsDiagnosticBuilder.registerStartupMethod(startupMethod)) {
return this;
}
@@ -200,7 +218,7 @@
return this;
}
- public Builder addStartupItem(StartupItem startupItem) {
+ public Builder addStartupItem(StartupProfileRule startupItem) {
startupItems.put(startupItem.getReference(), startupItem);
return this;
}
@@ -219,6 +237,7 @@
return this;
}
+ @Override
public StartupProfile build() {
if (startupItems.isEmpty()) {
return empty();
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/StartupProfileProviderUtils.java b/src/main/java/com/android/tools/r8/experimental/startup/StartupProfileProviderUtils.java
index c5ec563..e5b6b58 100644
--- a/src/main/java/com/android/tools/r8/experimental/startup/StartupProfileProviderUtils.java
+++ b/src/main/java/com/android/tools/r8/experimental/startup/StartupProfileProviderUtils.java
@@ -6,7 +6,7 @@
import static com.android.tools.r8.utils.ConsumerUtils.emptyConsumer;
-import com.android.tools.r8.experimental.startup.profile.StartupItem;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileRule;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.profile.art.HumanReadableArtProfileParserBuilder;
@@ -61,7 +61,7 @@
startupProfileProvider.getStartupProfile(startupProfileBuilder);
// Serialize the startup items.
StringBuilder resultBuilder = new StringBuilder();
- for (StartupItem startupItem : startupProfileBuilder.build().getItems()) {
+ for (StartupProfileRule startupItem : startupProfileBuilder.build().getRules()) {
startupItem.write(resultBuilder);
resultBuilder.append('\n');
}
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/profile/NonEmptyStartupProfile.java b/src/main/java/com/android/tools/r8/experimental/startup/profile/NonEmptyStartupProfile.java
index 8ebd821..90a8e7d 100644
--- a/src/main/java/com/android/tools/r8/experimental/startup/profile/NonEmptyStartupProfile.java
+++ b/src/main/java/com/android/tools/r8/experimental/startup/profile/NonEmptyStartupProfile.java
@@ -13,30 +13,51 @@
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.PrunedItems;
import com.android.tools.r8.synthesis.SyntheticItems;
+import com.android.tools.r8.utils.ThrowingConsumer;
import java.util.Collection;
import java.util.LinkedHashMap;
public class NonEmptyStartupProfile extends StartupProfile {
- private final LinkedHashMap<DexReference, StartupItem> startupItems;
+ private final LinkedHashMap<DexReference, StartupProfileRule> startupItems;
- public NonEmptyStartupProfile(LinkedHashMap<DexReference, StartupItem> startupItems) {
+ public NonEmptyStartupProfile(LinkedHashMap<DexReference, StartupProfileRule> startupItems) {
assert !startupItems.isEmpty();
this.startupItems = startupItems;
}
@Override
- public boolean contains(DexMethod method) {
+ public boolean containsMethodRule(DexMethod method) {
return startupItems.containsKey(method);
}
@Override
- public boolean contains(DexType type) {
+ public boolean containsClassRule(DexType type) {
return startupItems.containsKey(type);
}
@Override
- public Collection<StartupItem> getItems() {
+ public <E1 extends Exception, E2 extends Exception> void forEachRule(
+ ThrowingConsumer<StartupProfileClassRule, E1> classRuleConsumer,
+ ThrowingConsumer<StartupProfileMethodRule, E2> methodRuleConsumer)
+ throws E1, E2 {
+ for (StartupProfileRule rule : getRules()) {
+ rule.accept(classRuleConsumer, methodRuleConsumer);
+ }
+ }
+
+ @Override
+ public StartupProfileClassRule getClassRule(DexType type) {
+ return (StartupProfileClassRule) startupItems.get(type);
+ }
+
+ @Override
+ public StartupProfileMethodRule getMethodRule(DexMethod method) {
+ return (StartupProfileMethodRule) startupItems.get(method);
+ }
+
+ @Override
+ public Collection<StartupProfileRule> getRules() {
return startupItems.values();
}
@@ -47,24 +68,23 @@
@Override
public StartupProfile rewrittenWithLens(GraphLens graphLens) {
- LinkedHashMap<DexReference, StartupItem> rewrittenStartupItems =
+ LinkedHashMap<DexReference, StartupProfileRule> rewrittenStartupItems =
new LinkedHashMap<>(startupItems.size());
- for (StartupItem startupItem : startupItems.values()) {
+ for (StartupProfileRule startupItem : startupItems.values()) {
// TODO(b/271822426): This should account for one-to-many mappings. e.g., when a bridge is
// created.
startupItem.apply(
startupClass ->
rewrittenStartupItems.put(
startupClass.getReference(),
- StartupClass.builder()
+ StartupProfileClassRule.builder()
.setClassReference(graphLens.lookupType(startupClass.getReference()))
.build()),
startupMethod ->
rewrittenStartupItems.put(
startupMethod.getReference(),
- StartupMethod.builder()
- .setMethodReference(
- graphLens.getRenamedMethodSignature(startupMethod.getReference()))
+ StartupProfileMethodRule.builder()
+ .setMethod(graphLens.getRenamedMethodSignature(startupMethod.getReference()))
.build()));
}
return createNonEmpty(rewrittenStartupItems);
@@ -95,17 +115,17 @@
*/
@Override
public StartupProfile toStartupOrderForWriting(AppView<?> appView) {
- LinkedHashMap<DexReference, StartupItem> rewrittenStartupItems =
+ LinkedHashMap<DexReference, StartupProfileRule> rewrittenStartupItems =
new LinkedHashMap<>(startupItems.size());
- for (StartupItem startupItem : startupItems.values()) {
+ for (StartupProfileRule startupItem : startupItems.values()) {
addStartupItem(startupItem, rewrittenStartupItems, appView);
}
return createNonEmpty(rewrittenStartupItems);
}
private static void addStartupItem(
- StartupItem startupItem,
- LinkedHashMap<DexReference, StartupItem> rewrittenStartupItems,
+ StartupProfileRule startupItem,
+ LinkedHashMap<DexReference, StartupProfileRule> rewrittenStartupItems,
AppView<?> appView) {
startupItem.accept(
startupClass ->
@@ -114,16 +134,18 @@
}
private static boolean addClass(
- DexProgramClass clazz, LinkedHashMap<DexReference, StartupItem> rewrittenStartupItems) {
- StartupItem previous =
+ DexProgramClass clazz,
+ LinkedHashMap<DexReference, StartupProfileRule> rewrittenStartupItems) {
+ StartupProfileRule previous =
rewrittenStartupItems.put(
- clazz.getType(), StartupClass.builder().setClassReference(clazz.getType()).build());
+ clazz.getType(),
+ StartupProfileClassRule.builder().setClassReference(clazz.getType()).build());
return previous == null;
}
private static void addClassAndParentClasses(
DexType type,
- LinkedHashMap<DexReference, StartupItem> rewrittenStartupItems,
+ LinkedHashMap<DexReference, StartupProfileRule> rewrittenStartupItems,
AppView<?> appView) {
DexProgramClass definition = appView.app().programDefinitionFor(type);
if (definition != null) {
@@ -133,7 +155,7 @@
private static void addClassAndParentClasses(
DexProgramClass clazz,
- LinkedHashMap<DexReference, StartupItem> rewrittenStartupItems,
+ LinkedHashMap<DexReference, StartupProfileRule> rewrittenStartupItems,
AppView<?> appView) {
if (addClass(clazz, rewrittenStartupItems)) {
addParentClasses(clazz, rewrittenStartupItems, appView);
@@ -142,7 +164,7 @@
private static void addParentClasses(
DexProgramClass clazz,
- LinkedHashMap<DexReference, StartupItem> rewrittenStartupItems,
+ LinkedHashMap<DexReference, StartupProfileRule> rewrittenStartupItems,
AppView<?> appView) {
clazz.forEachImmediateSupertype(
supertype -> addClassAndParentClasses(supertype, rewrittenStartupItems, appView));
@@ -150,9 +172,9 @@
@Override
public StartupProfile withoutPrunedItems(PrunedItems prunedItems, SyntheticItems syntheticItems) {
- LinkedHashMap<DexReference, StartupItem> rewrittenStartupItems =
+ LinkedHashMap<DexReference, StartupProfileRule> rewrittenStartupItems =
new LinkedHashMap<>(startupItems.size());
- for (StartupItem startupItem : startupItems.values()) {
+ for (StartupProfileRule startupItem : startupItems.values()) {
// Only prune non-synthetic classes, since the pruning of a class does not imply that all
// classes synthesized from it have been pruned.
startupItem.accept(
@@ -170,7 +192,8 @@
return createNonEmpty(rewrittenStartupItems);
}
- private StartupProfile createNonEmpty(LinkedHashMap<DexReference, StartupItem> startupItems) {
+ private StartupProfile createNonEmpty(
+ LinkedHashMap<DexReference, StartupProfileRule> startupItems) {
if (startupItems.isEmpty()) {
assert false;
return empty();
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupItem.java b/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupItem.java
deleted file mode 100644
index 6ab6ec1..0000000
--- a/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupItem.java
+++ /dev/null
@@ -1,23 +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.experimental.startup.profile;
-
-import com.android.tools.r8.graph.DexReference;
-import java.io.IOException;
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-public abstract class StartupItem {
-
- public abstract void accept(
- Consumer<StartupClass> classConsumer, Consumer<StartupMethod> methodConsumer);
-
- public abstract <T> T apply(
- Function<StartupClass, T> classFunction, Function<StartupMethod, T> methodFunction);
-
- public abstract DexReference getReference();
-
- public abstract void write(Appendable appendable) throws IOException;
-}
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupMethod.java b/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupMethod.java
deleted file mode 100644
index 5d7448b..0000000
--- a/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupMethod.java
+++ /dev/null
@@ -1,99 +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.experimental.startup.profile;
-
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.references.MethodReference;
-import com.android.tools.r8.startup.StartupMethodBuilder;
-import com.android.tools.r8.utils.MethodReferenceUtils;
-import java.io.IOException;
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-public class StartupMethod extends StartupItem {
-
- private final DexMethod method;
-
- StartupMethod(DexMethod method) {
- this.method = method;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static Builder builder(DexItemFactory dexItemFactory) {
- return new Builder(dexItemFactory);
- }
-
- @Override
- public void accept(Consumer<StartupClass> classConsumer, Consumer<StartupMethod> methodConsumer) {
- methodConsumer.accept(this);
- }
-
- @Override
- public <T> T apply(
- Function<StartupClass, T> classFunction, Function<StartupMethod, T> methodFunction) {
- return methodFunction.apply(this);
- }
-
- @Override
- public DexMethod getReference() {
- return method;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- StartupMethod that = (StartupMethod) o;
- return method == that.method;
- }
-
- @Override
- public int hashCode() {
- return method.hashCode();
- }
-
- @Override
- public void write(Appendable appendable) throws IOException {
- appendable.append(method.toSmaliString());
- }
-
- public static class Builder implements StartupMethodBuilder {
-
- private final DexItemFactory dexItemFactory;
-
- private DexMethod method;
-
- Builder() {
- this(null);
- }
-
- Builder(DexItemFactory dexItemFactory) {
- this.dexItemFactory = dexItemFactory;
- }
-
- @Override
- public Builder setMethodReference(MethodReference classReference) {
- assert dexItemFactory != null;
- return setMethodReference(MethodReferenceUtils.toDexMethod(classReference, dexItemFactory));
- }
-
- public Builder setMethodReference(DexMethod method) {
- this.method = method;
- return this;
- }
-
- public StartupMethod build() {
- return new StartupMethod(method);
- }
- }
-}
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupClass.java b/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupProfileClassRule.java
similarity index 68%
rename from src/main/java/com/android/tools/r8/experimental/startup/profile/StartupClass.java
rename to src/main/java/com/android/tools/r8/experimental/startup/profile/StartupProfileClassRule.java
index 8e4efdb..c474ff2 100644
--- a/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupClass.java
+++ b/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupProfileClassRule.java
@@ -6,18 +6,20 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.profile.AbstractProfileClassRule;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.startup.StartupClassBuilder;
import com.android.tools.r8.utils.ClassReferenceUtils;
+import com.android.tools.r8.utils.ThrowingConsumer;
import java.io.IOException;
-import java.util.function.Consumer;
import java.util.function.Function;
-public class StartupClass extends StartupItem {
+public class StartupProfileClassRule extends StartupProfileRule
+ implements AbstractProfileClassRule {
private final DexType type;
- StartupClass(DexType type) {
+ StartupProfileClassRule(DexType type) {
this.type = type;
}
@@ -30,13 +32,17 @@
}
@Override
- public void accept(Consumer<StartupClass> classConsumer, Consumer<StartupMethod> methodConsumer) {
+ public <E1 extends Exception, E2 extends Exception> void accept(
+ ThrowingConsumer<StartupProfileClassRule, E1> classConsumer,
+ ThrowingConsumer<StartupProfileMethodRule, E2> methodConsumer)
+ throws E1 {
classConsumer.accept(this);
}
@Override
public <T> T apply(
- Function<StartupClass, T> classFunction, Function<StartupMethod, T> methodFunction) {
+ Function<StartupProfileClassRule, T> classFunction,
+ Function<StartupProfileMethodRule, T> methodFunction) {
return classFunction.apply(this);
}
@@ -53,7 +59,7 @@
if (o == null || getClass() != o.getClass()) {
return false;
}
- StartupClass that = (StartupClass) o;
+ StartupProfileClassRule that = (StartupProfileClassRule) o;
return type == that.type;
}
@@ -67,7 +73,8 @@
appendable.append(getReference().toDescriptorString());
}
- public static class Builder implements StartupClassBuilder {
+ public static class Builder
+ implements AbstractProfileClassRule.Builder<StartupProfileClassRule>, StartupClassBuilder {
private final DexItemFactory dexItemFactory;
@@ -92,8 +99,9 @@
return this;
}
- public StartupClass build() {
- return new StartupClass(type);
+ @Override
+ public StartupProfileClassRule build() {
+ return new StartupProfileClassRule(type);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupProfileMethodRule.java b/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupProfileMethodRule.java
new file mode 100644
index 0000000..0a3a36a
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupProfileMethodRule.java
@@ -0,0 +1,124 @@
+// 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.experimental.startup.profile;
+
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.profile.AbstractProfileMethodRule;
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.startup.StartupMethodBuilder;
+import com.android.tools.r8.utils.MethodReferenceUtils;
+import com.android.tools.r8.utils.ThrowingConsumer;
+import java.io.IOException;
+import java.util.function.Function;
+
+public class StartupProfileMethodRule extends StartupProfileRule
+ implements AbstractProfileMethodRule {
+
+ private final DexMethod method;
+
+ StartupProfileMethodRule(DexMethod method) {
+ this.method = method;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static Builder builder(DexItemFactory dexItemFactory) {
+ return new Builder(dexItemFactory);
+ }
+
+ @Override
+ public <E1 extends Exception, E2 extends Exception> void accept(
+ ThrowingConsumer<StartupProfileClassRule, E1> classConsumer,
+ ThrowingConsumer<StartupProfileMethodRule, E2> methodConsumer)
+ throws E2 {
+ methodConsumer.accept(this);
+ }
+
+ @Override
+ public <T> T apply(
+ Function<StartupProfileClassRule, T> classFunction,
+ Function<StartupProfileMethodRule, T> methodFunction) {
+ return methodFunction.apply(this);
+ }
+
+ @Override
+ public DexMethod getReference() {
+ return method;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ StartupProfileMethodRule that = (StartupProfileMethodRule) o;
+ return method == that.method;
+ }
+
+ @Override
+ public int hashCode() {
+ return method.hashCode();
+ }
+
+ @Override
+ public void write(Appendable appendable) throws IOException {
+ appendable.append(method.toSmaliString());
+ }
+
+ public static class Builder
+ implements AbstractProfileMethodRule.Builder<StartupProfileMethodRule, Builder>,
+ StartupMethodBuilder {
+
+ private final DexItemFactory dexItemFactory;
+
+ private DexMethod method;
+
+ Builder() {
+ this(null);
+ }
+
+ Builder(DexItemFactory dexItemFactory) {
+ this.dexItemFactory = dexItemFactory;
+ }
+
+ @Override
+ public boolean isGreaterThanOrEqualTo(Builder builder) {
+ return true;
+ }
+
+ @Override
+ public Builder join(Builder builder) {
+ return this;
+ }
+
+ @Override
+ public Builder join(StartupProfileMethodRule methodRule) {
+ return this;
+ }
+
+ @Override
+ public Builder setMethod(DexMethod method) {
+ this.method = method;
+ return this;
+ }
+
+ @Override
+ public Builder setMethodReference(MethodReference classReference) {
+ assert dexItemFactory != null;
+ return setMethod(MethodReferenceUtils.toDexMethod(classReference, dexItemFactory));
+ }
+
+ @Override
+ public StartupProfileMethodRule build() {
+ return new StartupProfileMethodRule(method);
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupProfileRule.java b/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupProfileRule.java
new file mode 100644
index 0000000..200d364
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/experimental/startup/profile/StartupProfileRule.java
@@ -0,0 +1,33 @@
+// 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.experimental.startup.profile;
+
+import com.android.tools.r8.graph.DexReference;
+import com.android.tools.r8.profile.AbstractProfileRule;
+import com.android.tools.r8.utils.ThrowingConsumer;
+import java.io.IOException;
+import java.util.function.Function;
+
+public abstract class StartupProfileRule
+ implements AbstractProfileRule, Comparable<StartupProfileRule> {
+
+ public abstract <E1 extends Exception, E2 extends Exception> void accept(
+ ThrowingConsumer<StartupProfileClassRule, E1> classConsumer,
+ ThrowingConsumer<StartupProfileMethodRule, E2> methodConsumer)
+ throws E1, E2;
+
+ public abstract <T> T apply(
+ Function<StartupProfileClassRule, T> classFunction,
+ Function<StartupProfileMethodRule, T> methodFunction);
+
+ @Override
+ public final int compareTo(StartupProfileRule rule) {
+ return getReference().compareTo(rule.getReference());
+ }
+
+ public abstract DexReference getReference();
+
+ public abstract void write(Appendable appendable) throws IOException;
+}
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/rewriting/StartupProfileAdditions.java b/src/main/java/com/android/tools/r8/experimental/startup/rewriting/StartupProfileAdditions.java
new file mode 100644
index 0000000..1f12cb3
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/experimental/startup/rewriting/StartupProfileAdditions.java
@@ -0,0 +1,62 @@
+// 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.experimental.startup.rewriting;
+
+import com.android.tools.r8.experimental.startup.StartupProfile;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileClassRule;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileMethodRule;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileRule;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.profile.AbstractProfileRule;
+import com.android.tools.r8.profile.art.rewriting.ProfileAdditions;
+import java.util.Comparator;
+
+// TODO(b/271822426): Use to include synthetics in startup profile.
+public class StartupProfileAdditions
+ extends ProfileAdditions<
+ StartupProfileAdditions,
+ StartupProfileClassRule,
+ StartupProfileClassRule.Builder,
+ StartupProfileMethodRule,
+ StartupProfileMethodRule.Builder,
+ StartupProfileRule,
+ StartupProfile,
+ StartupProfile.Builder> {
+
+ StartupProfileAdditions(StartupProfile profile) {
+ super(profile);
+ }
+
+ @Override
+ public StartupProfileAdditions create() {
+ return new StartupProfileAdditions(profile);
+ }
+
+ @Override
+ public StartupProfileClassRule.Builder createClassRuleBuilder(DexType type) {
+ return StartupProfileClassRule.builder().setClassReference(type);
+ }
+
+ @Override
+ public StartupProfileMethodRule.Builder createMethodRuleBuilder(DexMethod method) {
+ return StartupProfileMethodRule.builder().setMethod(method);
+ }
+
+ @Override
+ public StartupProfile.Builder createProfileBuilder() {
+ return StartupProfile.builder();
+ }
+
+ @Override
+ public Comparator<AbstractProfileRule> getRuleComparator() {
+ return Comparator.comparing(AbstractProfileRule::asStartupProfileRule);
+ }
+
+ @Override
+ public StartupProfileAdditions self() {
+ return this;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java b/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
index 88d2a35..db1c46f 100644
--- a/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
+++ b/src/main/java/com/android/tools/r8/features/ClassToFeatureSplitMap.java
@@ -175,7 +175,7 @@
feature = classToFeatureSplitMap.getOrDefault(type, FeatureSplit.BASE);
}
if (feature.isBase()) {
- return !startupProfile.contains(type)
+ return !startupProfile.containsClassRule(type)
|| options.getStartupOptions().isStartupBoundaryOptimizationsEnabled()
? FeatureSplit.BASE
: FeatureSplit.BASE_STARTUP;
diff --git a/src/main/java/com/android/tools/r8/features/FeatureSplitBoundaryOptimizationUtils.java b/src/main/java/com/android/tools/r8/features/FeatureSplitBoundaryOptimizationUtils.java
index bf3fc09..8badf5b 100644
--- a/src/main/java/com/android/tools/r8/features/FeatureSplitBoundaryOptimizationUtils.java
+++ b/src/main/java/com/android/tools/r8/features/FeatureSplitBoundaryOptimizationUtils.java
@@ -77,8 +77,8 @@
} else if (callerIsStartupMethod.isFalse()) {
// If the caller is not a startup method, then only allow inlining if the caller is not a
// startup class or the callee is a startup class.
- if (startupProfile.contains(caller.getHolderType())
- && !startupProfile.contains(callee.getHolderType())) {
+ if (startupProfile.containsClassRule(caller.getHolderType())
+ && !startupProfile.containsClassRule(callee.getHolderType())) {
return false;
}
}
@@ -91,7 +91,7 @@
// accurate result in this case.
return OptionalBool.unknown();
}
- return OptionalBool.of(startupProfile.contains(method.getReference()));
+ return OptionalBool.of(startupProfile.containsMethodRule(method.getReference()));
}
public static boolean isSafeForVerticalClassMerging(
@@ -114,8 +114,8 @@
// If the source class is a startup class then require that the target class is also a startup
// class.
StartupProfile startupProfile = appView.getStartupOrder();
- if (startupProfile.contains(sourceClass.getType())
- && !startupProfile.contains(targetClass.getType())) {
+ if (startupProfile.containsClassRule(sourceClass.getType())
+ && !startupProfile.containsClassRule(targetClass.getType())) {
return false;
}
return true;
diff --git a/src/main/java/com/android/tools/r8/profile/AbstractProfile.java b/src/main/java/com/android/tools/r8/profile/AbstractProfile.java
index 8265aa2..87b5656 100644
--- a/src/main/java/com/android/tools/r8/profile/AbstractProfile.java
+++ b/src/main/java/com/android/tools/r8/profile/AbstractProfile.java
@@ -30,7 +30,7 @@
Profile extends AbstractProfile<ClassRule, MethodRule>,
ProfileBuilder extends Builder<ClassRule, MethodRule, Profile, ProfileBuilder>> {
- ProfileBuilder addRule(AbstractProfileRule profileRule);
+ ProfileBuilder addRule(AbstractProfileRule rule);
ProfileBuilder addClassRule(ClassRule classRule);
diff --git a/src/main/java/com/android/tools/r8/profile/AbstractProfileRule.java b/src/main/java/com/android/tools/r8/profile/AbstractProfileRule.java
index c9f0d4c..ad28bfd 100644
--- a/src/main/java/com/android/tools/r8/profile/AbstractProfileRule.java
+++ b/src/main/java/com/android/tools/r8/profile/AbstractProfileRule.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.profile;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileRule;
import com.android.tools.r8.profile.art.ArtProfileRule;
public interface AbstractProfileRule {
@@ -12,4 +13,9 @@
default ArtProfileRule asArtProfileRule() {
return (ArtProfileRule) this;
}
+
+ @SuppressWarnings("unchecked")
+ default StartupProfileRule asStartupProfileRule() {
+ return (StartupProfileRule) this;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/profile/art/ArtProfile.java b/src/main/java/com/android/tools/r8/profile/art/ArtProfile.java
index a1761ec..7ab727d 100644
--- a/src/main/java/com/android/tools/r8/profile/art/ArtProfile.java
+++ b/src/main/java/com/android/tools/r8/profile/art/ArtProfile.java
@@ -292,12 +292,7 @@
@Override
public Builder addRule(AbstractProfileRule rule) {
- if (rule instanceof ArtProfileClassRule) {
- return addClassRule((ArtProfileClassRule) rule);
- } else {
- assert rule instanceof ArtProfileMethodRule;
- return addMethodRule((ArtProfileMethodRule) rule);
- }
+ return addRule(rule.asArtProfileRule());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/profile/art/rewriting/ProfileAdditions.java b/src/main/java/com/android/tools/r8/profile/art/rewriting/ProfileAdditions.java
index 195963e..d4bd1bc 100644
--- a/src/main/java/com/android/tools/r8/profile/art/rewriting/ProfileAdditions.java
+++ b/src/main/java/com/android/tools/r8/profile/art/rewriting/ProfileAdditions.java
@@ -77,7 +77,7 @@
void removeMovedMethodRule(DexMethod oldMethod, ProgramMethod newMethod);
}
- Profile profile;
+ protected Profile profile;
final Map<DexType, ClassRuleBuilder> classRuleAdditions = new ConcurrentHashMap<>();
final Map<DexMethod, MethodRuleBuilder> methodRuleAdditions = new ConcurrentHashMap<>();
@@ -86,7 +86,7 @@
private final NestedMethodRuleAdditionsGraph nestedMethodRuleAdditionsGraph =
new NestedMethodRuleAdditionsGraph();
- ProfileAdditions(Profile profile) {
+ protected ProfileAdditions(Profile profile) {
this.profile = profile;
}
diff --git a/src/main/java/com/android/tools/r8/startup/diagnostic/MissingStartupProfileItemsDiagnostic.java b/src/main/java/com/android/tools/r8/startup/diagnostic/MissingStartupProfileItemsDiagnostic.java
index 272684d..0c33a74 100644
--- a/src/main/java/com/android/tools/r8/startup/diagnostic/MissingStartupProfileItemsDiagnostic.java
+++ b/src/main/java/com/android/tools/r8/startup/diagnostic/MissingStartupProfileItemsDiagnostic.java
@@ -6,8 +6,8 @@
import com.android.tools.r8.Diagnostic;
import com.android.tools.r8.Keep;
-import com.android.tools.r8.experimental.startup.profile.StartupClass;
-import com.android.tools.r8.experimental.startup.profile.StartupMethod;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileClassRule;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileMethodRule;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
@@ -85,7 +85,7 @@
return !missingStartupItems.isEmpty();
}
- public boolean registerStartupClass(StartupClass startupClass) {
+ public boolean registerStartupClass(StartupProfileClassRule startupClass) {
if (definitions != null && !definitions.hasDefinitionFor(startupClass.getReference())) {
addMissingStartupItem(startupClass.getReference());
return true;
@@ -93,7 +93,7 @@
return false;
}
- public boolean registerStartupMethod(StartupMethod startupMethod) {
+ public boolean registerStartupMethod(StartupProfileMethodRule startupMethod) {
if (definitions != null && !definitions.hasDefinitionFor(startupMethod.getReference())) {
addMissingStartupItem(startupMethod.getReference());
return true;
diff --git a/src/test/java/com/android/tools/r8/D8CommandTest.java b/src/test/java/com/android/tools/r8/D8CommandTest.java
index 901629a..f22ce21 100644
--- a/src/test/java/com/android/tools/r8/D8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/D8CommandTest.java
@@ -22,7 +22,7 @@
import com.android.tools.r8.dex.Marker;
import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.experimental.startup.StartupProfile;
-import com.android.tools.r8.experimental.startup.profile.StartupItem;
+import com.android.tools.r8.experimental.startup.profile.StartupProfileRule;
import com.android.tools.r8.origin.EmbeddedOrigin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.references.Reference;
@@ -812,9 +812,9 @@
// Verify we found the same rule.
StartupProfile startupProfile = startupProfileBuilder.build();
- Collection<StartupItem> startupItems = startupProfile.getItems();
+ Collection<StartupProfileRule> startupItems = startupProfile.getRules();
assertEquals(1, startupItems.size());
- StartupItem startupItem = startupItems.iterator().next();
+ StartupProfileRule startupItem = startupItems.iterator().next();
startupItem.accept(
startupClass -> fail(),
startupMethod -> assertEquals(profileRule, startupMethod.getReference().toSmaliString()));