Move profile transformer to AbstractProfile

Change-Id: If37e187f0bc2e0eee662b07e49200b6b9d9e0099
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 ff8c494..43776fd 100644
--- a/src/main/java/com/android/tools/r8/profile/AbstractProfile.java
+++ b/src/main/java/com/android/tools/r8/profile/AbstractProfile.java
@@ -6,10 +6,15 @@
 
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.profile.AbstractProfile.Builder;
 import com.android.tools.r8.utils.ThrowingConsumer;
+import java.util.function.BiConsumer;
 
 public interface AbstractProfile<
-    ClassRule extends AbstractProfileClassRule, MethodRule extends AbstractProfileMethodRule> {
+    ClassRule extends AbstractProfileClassRule,
+    MethodRule extends AbstractProfileMethodRule,
+    Profile extends AbstractProfile<ClassRule, MethodRule, Profile, ProfileBuilder>,
+    ProfileBuilder extends Builder<ClassRule, MethodRule, Profile, ProfileBuilder>> {
 
   boolean containsClassRule(DexType type);
 
@@ -24,10 +29,22 @@
 
   MethodRule getMethodRule(DexMethod method);
 
+  ProfileBuilder toEmptyBuilderWithCapacity();
+
+  default Profile transform(
+      BiConsumer<ClassRule, ProfileBuilder> classRuleTransformer,
+      BiConsumer<MethodRule, ProfileBuilder> methodRuleTransformer) {
+    ProfileBuilder builder = toEmptyBuilderWithCapacity();
+    forEachRule(
+        classRule -> classRuleTransformer.accept(classRule, builder),
+        methodRule -> methodRuleTransformer.accept(methodRule, builder));
+    return builder.build();
+  }
+
   interface Builder<
       ClassRule extends AbstractProfileClassRule,
       MethodRule extends AbstractProfileMethodRule,
-      Profile extends AbstractProfile<ClassRule, MethodRule>,
+      Profile extends AbstractProfile<ClassRule, MethodRule, Profile, ProfileBuilder>,
       ProfileBuilder extends Builder<ClassRule, MethodRule, Profile, ProfileBuilder>> {
 
     ProfileBuilder addRule(AbstractProfileRule rule);
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 165845a..9ff43b1 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
@@ -28,10 +28,11 @@
 import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.Map;
-import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 
-public class ArtProfile implements AbstractProfile<ArtProfileClassRule, ArtProfileMethodRule> {
+public class ArtProfile
+    implements AbstractProfile<
+        ArtProfileClassRule, ArtProfileMethodRule, ArtProfile, ArtProfile.Builder> {
 
   private final Map<DexReference, ArtProfileRule> rules;
 
@@ -53,6 +54,11 @@
   }
 
   @Override
+  public Builder toEmptyBuilderWithCapacity() {
+    return builderWithCapacity(rules.size());
+  }
+
+  @Override
   public boolean containsClassRule(DexType type) {
     return rules.containsKey(type);
   }
@@ -195,22 +201,6 @@
     return this;
   }
 
-  private ArtProfile transform(
-      BiConsumer<ArtProfileClassRule, Builder> classTransformation,
-      BiConsumer<ArtProfileMethodRule, Builder> methodTransformation) {
-    Builder builder = builderWithCapacity(rules.size());
-    forEachRule(
-        // Supply a factory method for creating a builder. If the current rule should be included in
-        // the rewritten profile, the caller should call the provided builder factory method to
-        // create a class rule builder. If two rules are mapped to the same reference, the same rule
-        // builder is reused so that the two rules are merged into a single rule (with their flags
-        // merged).
-        classRule -> classTransformation.accept(classRule, builder),
-        // As above.
-        methodRule -> methodTransformation.accept(methodRule, builder));
-    return builder.build();
-  }
-
   public void supplyConsumer(ArtProfileConsumer consumer, Reporter reporter) {
     if (consumer != null) {
       TextOutputStream textOutputStream = consumer.getHumanReadableArtProfileConsumer();
diff --git a/src/main/java/com/android/tools/r8/profile/rewriting/ProfileAdditions.java b/src/main/java/com/android/tools/r8/profile/rewriting/ProfileAdditions.java
index 877df9a..0269114 100644
--- a/src/main/java/com/android/tools/r8/profile/rewriting/ProfileAdditions.java
+++ b/src/main/java/com/android/tools/r8/profile/rewriting/ProfileAdditions.java
@@ -47,7 +47,7 @@
     MethodRule extends AbstractProfileMethodRule,
     MethodRuleBuilder extends AbstractProfileMethodRule.Builder<MethodRule, MethodRuleBuilder>,
     ProfileRule extends AbstractProfileRule,
-    Profile extends AbstractProfile<ClassRule, MethodRule>,
+    Profile extends AbstractProfile<ClassRule, MethodRule, Profile, ProfileBuilder>,
     ProfileBuilder extends
         AbstractProfile.Builder<ClassRule, MethodRule, Profile, ProfileBuilder>> {
 
diff --git a/src/main/java/com/android/tools/r8/profile/startup/profile/EmptyStartupProfile.java b/src/main/java/com/android/tools/r8/profile/startup/profile/EmptyStartupProfile.java
index a051dc9..666338a 100644
--- a/src/main/java/com/android/tools/r8/profile/startup/profile/EmptyStartupProfile.java
+++ b/src/main/java/com/android/tools/r8/profile/startup/profile/EmptyStartupProfile.java
@@ -66,6 +66,11 @@
   }
 
   @Override
+  public Builder toEmptyBuilderWithCapacity() {
+    return builder();
+  }
+
+  @Override
   public EmptyStartupProfile toStartupProfileForWriting(AppView<?> appView) {
     return this;
   }
diff --git a/src/main/java/com/android/tools/r8/profile/startup/profile/NonEmptyStartupProfile.java b/src/main/java/com/android/tools/r8/profile/startup/profile/NonEmptyStartupProfile.java
index 5ccba97..eea1f3d 100644
--- a/src/main/java/com/android/tools/r8/profile/startup/profile/NonEmptyStartupProfile.java
+++ b/src/main/java/com/android/tools/r8/profile/startup/profile/NonEmptyStartupProfile.java
@@ -21,7 +21,6 @@
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
-import java.util.function.BiConsumer;
 
 public class NonEmptyStartupProfile extends StartupProfile {
 
@@ -105,6 +104,11 @@
     return startupRules.size();
   }
 
+  @Override
+  public Builder toEmptyBuilderWithCapacity() {
+    return builderWithCapacity(size());
+  }
+
   /**
    * This is called to process the startup profile before computing the startup layouts.
    *
@@ -194,14 +198,4 @@
     timing.end();
     return result;
   }
-
-  private StartupProfile transform(
-      BiConsumer<StartupProfileClassRule, Builder> classRuleTransformer,
-      BiConsumer<StartupProfileMethodRule, Builder> methodRuleTransformer) {
-    Builder builder = builderWithCapacity(startupRules.size());
-    forEachRule(
-        classRule -> classRuleTransformer.accept(classRule, builder),
-        methodRule -> methodRuleTransformer.accept(methodRule, builder));
-    return builder.build();
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/profile/startup/profile/StartupProfile.java b/src/main/java/com/android/tools/r8/profile/startup/profile/StartupProfile.java
index 8ee1fd5..b10578c 100644
--- a/src/main/java/com/android/tools/r8/profile/startup/profile/StartupProfile.java
+++ b/src/main/java/com/android/tools/r8/profile/startup/profile/StartupProfile.java
@@ -36,7 +36,8 @@
 import java.util.function.Function;
 
 public abstract class StartupProfile
-    implements AbstractProfile<StartupProfileClassRule, StartupProfileMethodRule> {
+    implements AbstractProfile<
+        StartupProfileClassRule, StartupProfileMethodRule, StartupProfile, StartupProfile.Builder> {
 
   protected StartupProfile() {}