Revert "Hygienic outlining."

This reverts commit c49173eb1ec1ad15a302222c9f11ecedeb0e8efe.

Reason for revert: red bots

Change-Id: Ia1b343dc6169c2e0c133aad813fdd082cd8aedfe
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index c488caf..56f9a92 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -19,6 +19,7 @@
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.synthesis.SyntheticNaming;
 import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.structural.CompareToVisitor;
 import com.android.tools.r8.utils.structural.HashingVisitor;
 import com.android.tools.r8.utils.structural.StructuralMapping;
@@ -43,7 +44,6 @@
           "$r8$twr$utility",
           "$-DC",
           "$$ServiceLoaderMethods",
-          "com.android.tools.r8.GeneratedOutlineSupport",
           "-$$Lambda$");
 
   public final DexString descriptor;
@@ -338,6 +338,7 @@
     // Any entry that is removed from here must be added to OLD_SYNTHESIZED_NAMES to ensure that
     // newer releases can be used to merge previous builds.
     return name.contains(LAMBDA_GROUP_CLASS_NAME_PREFIX) // Could collide.
+        || name.contains(OutlineOptions.CLASS_NAME) // Global singleton.
         || name.contains(NestBasedAccessDesugaring.NEST_CONSTRUCTOR_NAME); // Global singleton.
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index db1f69b..152d618 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -20,6 +20,7 @@
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexTypeList;
 import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.ProgramMethod;
@@ -100,6 +101,7 @@
 import com.android.tools.r8.utils.ExceptionUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.InternalOptions.DesugarState;
+import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.Timing;
@@ -836,8 +838,9 @@
               outliner.identifyOutlineSites(code);
             },
             executorService);
-        List<ProgramMethod> outlineMethods = outliner.buildOutlineMethods();
-        optimizeSynthesizedMethods(outlineMethods, executorService);
+        DexProgramClass outlineClass = outliner.buildOutlinerClass(computeOutlineClassType());
+        appView.appInfo().addSynthesizedClass(outlineClass, true);
+        optimizeSynthesizedClass(outlineClass, executorService);
         forEachSelectedOutliningMethod(
             methodsSelectedForOutlining,
             code -> {
@@ -849,7 +852,8 @@
             executorService);
         feedback.updateVisibleOptimizationInfo();
         assert outliner.checkAllOutlineSitesFoundAgain();
-        outlineMethods.forEach(m -> m.getDefinition().markNotProcessed());
+        builder.addSynthesizedClass(outlineClass);
+        clearDexMethodCompilationState(outlineClass);
       }
       timing.end();
     }
@@ -1033,11 +1037,27 @@
     }
   }
 
-  public void optimizeSynthesizedMethods(
-      List<ProgramMethod> programMethods, ExecutorService executorService)
+  // Find an unused name for the outlining class. When multiple runs produces additional
+  // outlining the default outlining class might already be present.
+  private DexType computeOutlineClassType() {
+    DexType result;
+    int count = 0;
+    String prefix = appView.options().synthesizedClassPrefix.replace('/', '.');
+    do {
+      String name =
+          prefix + OutlineOptions.CLASS_NAME + (count == 0 ? "" : Integer.toString(count));
+      count++;
+      result = appView.dexItemFactory().createType(DescriptorUtils.javaTypeToDescriptor(name));
+
+    } while (appView.appInfo().definitionForWithoutExistenceAssert(result) != null);
+    return result;
+  }
+
+  public void optimizeSynthesizedClass(
+      DexProgramClass clazz, ExecutorService executorService)
       throws ExecutionException {
     // Process the generated class, but don't apply any outlining.
-    SortedProgramMethodSet methods = SortedProgramMethodSet.create(programMethods::forEach);
+    SortedProgramMethodSet methods = SortedProgramMethodSet.create(clazz::forEachProgramMethod);
     processMethodsConcurrently(methods, executorService);
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index 09fd687..994e2ba 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -165,9 +165,11 @@
   public void processSynthesizedClasses(IRConverter converter, ExecutorService executor)
       throws ExecutionException {
     while (!synthesizedMethods.isEmpty()) {
-      ArrayList<ProgramMethod> methods = new ArrayList<>(synthesizedMethods);
+      List<ProgramMethod> methods = new ArrayList<>(synthesizedMethods);
       synthesizedMethods.clear();
-      converter.optimizeSynthesizedMethods(methods, executor);
+      for (ProgramMethod method : methods) {
+        converter.optimizeSynthesizedClass(method.getHolder(), executor);
+      }
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index dbad5bd..11b4ddf 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -10,16 +10,26 @@
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.ClassAccessFlags;
 import com.android.tools.r8.graph.ClasspathMethod;
 import com.android.tools.r8.graph.Code;
 import com.android.tools.r8.graph.DebugLocalInfo;
+import com.android.tools.r8.graph.DexAnnotationSet;
+import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexProgramClass.ChecksumSupplier;
 import com.android.tools.r8.graph.DexProto;
+import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.DexTypeList;
+import com.android.tools.r8.graph.GenericSignature.ClassSignature;
+import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
 import com.android.tools.r8.graph.GraphLens;
 import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.analysis.type.ArrayTypeElement;
@@ -55,8 +65,8 @@
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.origin.SynthesizedOrigin;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.ListUtils;
@@ -66,6 +76,7 @@
 import com.android.tools.r8.utils.collections.ProgramMethodMultiset;
 import com.android.tools.r8.utils.collections.ProgramMethodSet;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
@@ -91,9 +102,9 @@
  *       {@link OutlineOptions#threshold}). Each selected method is then converted back to IR and
  *       passed to {@link Outliner#identifyOutlineSites(IRCode)}, which then stores concrete
  *       outlining candidates in {@link Outliner#outlineSites}.
- *   <li>Third, {@link Outliner#buildOutlineMethods()} is called to construct the <em>outline
- *       support classes</em> containing a static helper method for each outline candidate that
- *       occurs frequently enough. Each selected method is then converted to IR, passed to {@link
+ *   <li>Third, {@link Outliner#buildOutlinerClass(DexType)} is called to construct the <em>outline
+ *       support class</em> containing a static helper method for each outline candidate that occurs
+ *       frequently enough. Each selected method is then converted to IR, passed to {@link
  *       Outliner#applyOutliningCandidate(IRCode)} to perform the outlining, and converted back to
  *       the output format (DEX or CF).
  * </ul>
@@ -105,7 +116,7 @@
       new ArrayList<>();
   /** Result of second step (see {@link Outliner#selectMethodsForOutlining()}. */
   private final Map<Outline, List<ProgramMethod>> outlineSites = new HashMap<>();
-  /** Result of third step (see {@link Outliner#buildOutlineMethods()}. */
+  /** Result of third step (see {@link Outliner#buildOutlinerClass(DexType)}. */
   private final Map<Outline, DexMethod> generatedOutlines = new HashMap<>();
 
   static final int MAX_IN_SIZE = 5;  // Avoid using ranged calls for outlined code.
@@ -570,6 +581,11 @@
       return proto;
     }
 
+    // Build the DexMethod for this outline.
+    DexMethod buildMethod(DexType clazz, DexString name) {
+      return appView.dexItemFactory().createMethod(clazz, buildProto(), name);
+    }
+
     @Override
     public boolean equals(Object other) {
       if (!(other instanceof Outline)) {
@@ -1339,40 +1355,67 @@
     return methodsSelectedForOutlining;
   }
 
-  public List<ProgramMethod> buildOutlineMethods() {
-    List<ProgramMethod> outlineMethods = new ArrayList<>();
-    // By now the candidates are the actual selected outlines. Iterate the outlines in a
-    // consistent order, to provide deterministic naming of the internal-synthetics.
-    // The choice of 'representative' will ensure deterministic naming of the external names.
+  public DexProgramClass buildOutlinerClass(DexType type) {
+    // Build the outlined methods.
+    // By now the candidates are the actual selected outlines. Name the generated methods in a
+    // consistent order, to provide deterministic output.
     List<Outline> outlines = selectOutlines();
     outlines.sort(Comparator.naturalOrder());
+    DexEncodedMethod[] direct = new DexEncodedMethod[outlines.size()];
+    int count = 0;
     for (Outline outline : outlines) {
+      MethodAccessFlags methodAccess =
+          MethodAccessFlags.fromSharedAccessFlags(
+              Constants.ACC_PUBLIC | Constants.ACC_STATIC, false);
+      DexString methodName =
+          appView.dexItemFactory().createString(OutlineOptions.METHOD_PREFIX + count);
+      DexMethod method = outline.buildMethod(type, methodName);
       List<ProgramMethod> sites = outlineSites.get(outline);
       assert !sites.isEmpty();
-      ProgramMethod representative = findDeterministicRepresentative(sites);
-      ProgramMethod outlineMethod =
-          appView
-              .getSyntheticItems()
-              .createMethod(
-                  SyntheticKind.OUTLINE,
-                  representative,
-                  appView.dexItemFactory(),
-                  builder -> {
-                    builder
-                        .setAccessFlags(
-                            MethodAccessFlags.fromSharedAccessFlags(
-                                Constants.ACC_PUBLIC | Constants.ACC_STATIC, false))
-                        .setProto(outline.buildProto())
-                        .setCode(m -> new OutlineCode(outline));
-                    if (appView.options().isGeneratingClassFiles()) {
-                      builder.setClassFileVersion(
-                          representative.getDefinition().getClassFileVersion());
-                    }
-                  });
-      generatedOutlines.put(outline, outlineMethod.getReference());
-      outlineMethods.add(outlineMethod);
+      direct[count] =
+          new DexEncodedMethod(
+              method,
+              methodAccess,
+              MethodTypeSignature.noSignature(),
+              DexAnnotationSet.empty(),
+              ParameterAnnotationsList.empty(),
+              new OutlineCode(outline),
+              true);
+      if (appView.options().isGeneratingClassFiles()) {
+        direct[count].upgradeClassFileVersion(sites.get(0).getDefinition().getClassFileVersion());
+      }
+      generatedOutlines.put(outline, method);
+      count++;
     }
-    return outlineMethods;
+    // No need to sort the direct methods as they are generated in sorted order.
+
+    // Build the outliner class.
+    DexTypeList interfaces = DexTypeList.empty();
+    DexString sourceFile = appView.dexItemFactory().createString("outline");
+    ClassAccessFlags accessFlags = ClassAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC);
+    assert !appView.options().encodeChecksums;
+    // The outliner is R8 only and checksum is not a supported part of R8 compilation.
+    ChecksumSupplier checksumSupplier = DexProgramClass::invalidChecksumRequest;
+    return new DexProgramClass(
+        type,
+        null,
+        new SynthesizedOrigin("outlining", getClass()),
+        accessFlags,
+        appView.dexItemFactory().objectType,
+        interfaces,
+        sourceFile,
+        null,
+        Collections.emptyList(),
+        null,
+        Collections.emptyList(),
+        ClassSignature.noSignature(),
+        DexAnnotationSet.empty(),
+        DexEncodedField.EMPTY_ARRAY, // Static fields.
+        DexEncodedField.EMPTY_ARRAY, // Instance fields.
+        direct,
+        DexEncodedMethod.EMPTY_ARRAY, // Virtual methods.
+        appView.dexItemFactory().getSkipNameValidationForTesting(),
+        checksumSupplier);
   }
 
   private List<Outline> selectOutlines() {
@@ -1387,18 +1430,6 @@
     return result;
   }
 
-  private static ProgramMethod findDeterministicRepresentative(List<ProgramMethod> members) {
-    // Pick a deterministic member as representative.
-    ProgramMethod smallest = members.get(0);
-    for (int i = 1; i < members.size(); i++) {
-      ProgramMethod next = members.get(i);
-      if (next.getReference().compareTo(smallest.getReference()) < 0) {
-        smallest = next;
-      }
-    }
-    return smallest;
-  }
-
   public void applyOutliningCandidate(IRCode code) {
     assert !code.method().getCode().isOutlineCode();
     ListIterator<BasicBlock> blocksIterator = code.listIterator();
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 a9d8d57..f7ac800 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -109,6 +109,7 @@
 import com.android.tools.r8.utils.Action;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.InternalOptions.DesugarState;
+import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.IteratorUtils;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.MethodSignatureEquivalence;
@@ -1723,6 +1724,8 @@
             || !options.testing.checkForNotExpandingMainDexTracingResult
             || previousMainDexTracingResult.isRoot(clazz)
             || clazz.toSourceString().contains(ENUM_UNBOXING_UTILITY_CLASS_SUFFIX)
+            // TODO(b/177847090): Consider not outlining anything in main dex.
+            || clazz.toSourceString().contains(OutlineOptions.CLASS_NAME)
         : "Class " + clazz.toSourceString() + " was not a main dex root in the first round";
 
     // Mark types in inner-class attributes referenced.
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
index fc5b278..b33e260 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
@@ -32,8 +32,7 @@
     THROW_ICCE("ThrowICCE", true),
     THROW_NSME("ThrowNSME", true),
     TWR_CLOSE_RESOURCE("TwrCloseResource", true),
-    SERVICE_LOADER("ServiceLoad", true),
-    OUTLINE("Outline", true);
+    SERVICE_LOADER("ServiceLoad", true);
 
     public final String descriptor;
     public final boolean isSingleSyntheticMethod;
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 a9f55ee..a8bec4a 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -1067,6 +1067,10 @@
   }
 
   public static class OutlineOptions {
+
+    public static final String CLASS_NAME = "com.android.tools.r8.GeneratedOutlineSupport";
+    public static final String METHOD_PREFIX = "outline";
+
     public boolean enabled = true;
     public int minSize = 3;
     public int maxSize = 99;
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/NoOutliningForClassFileBuildsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/NoOutliningForClassFileBuildsTest.java
index 2a837bc..4af2593 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/NoOutliningForClassFileBuildsTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/NoOutliningForClassFileBuildsTest.java
@@ -9,7 +9,7 @@
 
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -72,9 +72,8 @@
     assertThat(classSubject.uniqueMethodWithName("foo"), isPresent());
     assertThat(classSubject.uniqueMethodWithName("bar"), isPresent());
     boolean hasOutlineClass =
-        inspector
-            .clazz(SyntheticItemsTestUtils.syntheticOutlineClass(TestClass.class, 0))
-            .isPresent();
+        inspector.allClasses().stream()
+            .anyMatch(c -> c.getFinalName().equals(OutlineOptions.CLASS_NAME));
     assertEquals(forceOutline || parameters.isDexRuntime(), hasOutlineClass);
   }
 
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlinesWithNonNullTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlinesWithNonNullTest.java
index 6b7bc4a..59602da 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlinesWithNonNullTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/OutlinesWithNonNullTest.java
@@ -12,7 +12,7 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -93,10 +93,9 @@
   }
 
   private void validateOutlining(CodeInspector inspector, Class<?> main) {
-    ClassSubject outlineClass =
-        inspector.clazz(SyntheticItemsTestUtils.syntheticOutlineClass(main, 0));
-    MethodSubject outlineMethod =
-        outlineClass.uniqueMethodWithName(SyntheticItemsTestUtils.syntheticMethodName());
+    ClassSubject outlineClass = inspector.clazz(OutlineOptions.CLASS_NAME);
+    assertThat(outlineClass, isPresent());
+    MethodSubject outlineMethod = outlineClass.uniqueMethodWithName("outline0");
     assertThat(outlineMethod, isPresent());
 
     ClassSubject argClass = inspector.clazz(TestArg.class);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithClassArrayTypeArguments.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithClassArrayTypeArguments.java
index 440b036..099afa8 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithClassArrayTypeArguments.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithClassArrayTypeArguments.java
@@ -11,7 +11,7 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -37,12 +37,11 @@
   }
 
   private void validateOutlining(CodeInspector inspector) {
-    ClassSubject outlineClass =
-        inspector.clazz(SyntheticItemsTestUtils.syntheticOutlineClass(TestClass.class, 0));
+    ClassSubject outlineClass = inspector.clazz(OutlineOptions.CLASS_NAME);
     MethodSubject outline0Method =
         outlineClass.method(
             "void",
-            SyntheticItemsTestUtils.syntheticMethodName(),
+            "outline0",
             ImmutableList.of(
                 TestClass.class.getTypeName() + "[]", TestClass.class.getTypeName() + "[]"));
     assertThat(outline0Method, isPresent());
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithInterfaceArrayTypeArguments.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithInterfaceArrayTypeArguments.java
index 062516c..fb4417f9 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithInterfaceArrayTypeArguments.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithInterfaceArrayTypeArguments.java
@@ -11,8 +11,8 @@
 import com.android.tools.r8.NeverInline;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
 import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -44,15 +44,12 @@
   private void validateOutlining(CodeInspector inspector) {
     // No outlining when arrays of interfaces are involved, see b/132420510 - unless the testing
     // option is set.
-    ClassSubject outlineClass =
-        inspector.clazz(SyntheticItemsTestUtils.syntheticOutlineClass(TestClass.class, 0));
+    ClassSubject outlineClass = inspector.clazz(OutlineOptions.CLASS_NAME);
     if (allowOutlinerInterfaceArrayArguments && parameters.isCfRuntime()) {
       assertThat(outlineClass, isPresent());
       MethodSubject outline0Method =
           outlineClass.method(
-              "void",
-              SyntheticItemsTestUtils.syntheticMethodName(),
-              ImmutableList.of("java.lang.Object[]", "java.lang.Object[]"));
+              "void", "outline0", ImmutableList.of("java.lang.Object[]", "java.lang.Object[]"));
       assertThat(outline0Method, isPresent());
       ClassSubject classSubject = inspector.clazz(TestClass.class);
       assertThat(
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithPrimitiveArrayTypeArguments.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithPrimitiveArrayTypeArguments.java
index 36d9ad5..7a69926 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithPrimitiveArrayTypeArguments.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/arraytypes/OutlinesWithPrimitiveArrayTypeArguments.java
@@ -11,7 +11,7 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -37,13 +37,9 @@
   }
 
   private void validateOutlining(CodeInspector inspector) {
-    ClassSubject outlineClass =
-        inspector.clazz(SyntheticItemsTestUtils.syntheticOutlineClass(TestClass.class, 0));
+    ClassSubject outlineClass = inspector.clazz(OutlineOptions.CLASS_NAME);
     MethodSubject outline0Method =
-        outlineClass.method(
-            "void",
-            SyntheticItemsTestUtils.syntheticMethodName(),
-            ImmutableList.of("int[]", "int[]"));
+        outlineClass.method("void", "outline0", ImmutableList.of("int[]", "int[]"));
     assertThat(outline0Method, isPresent());
     ClassSubject classSubject = inspector.clazz(TestClass.class);
     assertThat(
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/b112247415/B112247415.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/b112247415/B112247415.java
index b4dd6b7..9fcc6b7 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/b112247415/B112247415.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/b112247415/B112247415.java
@@ -10,7 +10,6 @@
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
@@ -99,14 +98,11 @@
         .inspector();
 
     for (FoundClassSubject clazz : inspector.allClasses()) {
-      if (!SyntheticItemsTestUtils.isExternalOutlineClass(clazz.getFinalReference())) {
-        clazz.forAllMethods(
-            method -> {
-              if (method.hasCode()) {
-                verifyAbsenceOfStringBuilderAppend(method.streamInstructions());
-              }
-            });
-      }
+      clazz.forAllMethods(method -> {
+        if (method.hasCode() && !method.getFinalName().startsWith("outline")) {
+          verifyAbsenceOfStringBuilderAppend(method.streamInstructions());
+        }
+      });
     }
   }
 
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/b133215941/B133215941.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/b133215941/B133215941.java
index 031fd9d..66c42e8 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/b133215941/B133215941.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/b133215941/B133215941.java
@@ -15,7 +15,7 @@
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.ir.optimize.outliner.b133215941.B133215941.TestClass.ClassWithStaticMethod;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -41,12 +41,11 @@
   }
 
   private void validateOutlining(CodeInspector inspector) {
-    ClassSubject outlineClass =
-        inspector.clazz(SyntheticItemsTestUtils.syntheticOutlineClass(TestClass.class, 0));
+    ClassSubject outlineClass = inspector.clazz(OutlineOptions.CLASS_NAME);
     MethodSubject outline0Method =
         outlineClass.method(
             "void",
-            SyntheticItemsTestUtils.syntheticMethodName(),
+            "outline0",
             ImmutableList.of(TestClass.class.getTypeName(), TestClass.class.getTypeName()));
     assertThat(outline0Method, isPresent());
     ClassSubject classSubject = inspector.clazz(TestClass.class);
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/b149971007/B149971007.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/b149971007/B149971007.java
index dd6dace..438aa81 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/b149971007/B149971007.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/b149971007/B149971007.java
@@ -4,7 +4,6 @@
 
 package com.android.tools.r8.ir.optimize.outliner.b149971007;
 
-import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static junit.framework.TestCase.assertEquals;
 import static junit.framework.TestCase.assertFalse;
@@ -16,7 +15,7 @@
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.dexsplitter.SplitterTestBase;
 import com.android.tools.r8.naming.ClassNameMapper;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
@@ -25,8 +24,6 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -67,17 +64,10 @@
   }
 
   private void checkOutlineFromFeature(CodeInspector inspector) {
-    // There are two expected outlines, each is currently in its own class.
-    List<FoundMethodSubject> allMethods = new ArrayList<>();
-    for (int i = 0; i < 2; i++) {
-      ClassSubject clazz =
-          inspector.clazz(SyntheticItemsTestUtils.syntheticOutlineClass(FeatureClass.class, i));
-      assertThat(clazz, isPresent());
-      assertEquals(1, clazz.allMethods().size());
-      allMethods.addAll(clazz.allMethods());
-    }
-    // One of the methods is StringBuilder the other references the feature.
-    assertTrue(allMethods.stream().anyMatch(this::referenceFeatureClass));
+    ClassSubject clazz = inspector.clazz(OutlineOptions.CLASS_NAME);
+    assertThat(clazz, isPresent());
+    assertEquals(2, clazz.allMethods().size());
+    assertTrue(clazz.allMethods().stream().anyMatch(this::referenceFeatureClass));
   }
 
   @Test
@@ -95,44 +85,24 @@
     // Check that parts of method1, ..., method4 in FeatureClass was outlined.
     ClassSubject featureClass = compileResult.inspector().clazz(FeatureClass.class);
     assertThat(featureClass, isPresent());
-
-    // Find the final names of the two outline classes.
-    String outlineClassName0 =
+    String outlineClassName =
         ClassNameMapper.mapperFromString(compileResult.getProguardMap())
             .getObfuscatedToOriginalMapping()
             .inverse
-            .get(
-                SyntheticItemsTestUtils.syntheticOutlineClass(FeatureClass.class, 0).getTypeName());
-    String outlineClassName1 =
-        ClassNameMapper.mapperFromString(compileResult.getProguardMap())
-            .getObfuscatedToOriginalMapping()
-            .inverse
-            .get(
-                SyntheticItemsTestUtils.syntheticOutlineClass(FeatureClass.class, 1).getTypeName());
-
-    // Verify they are called from the feature methods.
-    // Note: should the choice of synthetic grouping change these expectations will too.
-    assertTrue(invokesOutline(featureClass.uniqueMethodWithName("method1"), outlineClassName0));
-    assertTrue(invokesOutline(featureClass.uniqueMethodWithName("method2"), outlineClassName0));
-    assertTrue(invokesOutline(featureClass.uniqueMethodWithName("method3"), outlineClassName1));
-    assertTrue(invokesOutline(featureClass.uniqueMethodWithName("method4"), outlineClassName1));
+            .get(OutlineOptions.CLASS_NAME);
+    assertTrue(invokesOutline(featureClass.uniqueMethodWithName("method1"), outlineClassName));
+    assertTrue(invokesOutline(featureClass.uniqueMethodWithName("method2"), outlineClassName));
+    assertTrue(invokesOutline(featureClass.uniqueMethodWithName("method3"), outlineClassName));
+    assertTrue(invokesOutline(featureClass.uniqueMethodWithName("method4"), outlineClassName));
 
     compileResult.run(parameters.getRuntime(), TestClass.class).assertSuccessWithOutput("123456");
   }
 
   private void checkNoOutlineFromFeature(CodeInspector inspector) {
-    // The features do not give rise to an outline.
-    ClassSubject featureOutlineClass =
-        inspector.clazz(
-            SyntheticItemsTestUtils.syntheticOutlineClass(FeatureClass.class, 0).getTypeName());
-    assertThat(featureOutlineClass, isAbsent());
-    // The main TestClass entry does.
-    ClassSubject mainOutlineClazz =
-        inspector.clazz(
-            SyntheticItemsTestUtils.syntheticOutlineClass(TestClass.class, 0).getTypeName());
-    assertThat(mainOutlineClazz, isPresent());
-    assertEquals(1, mainOutlineClazz.allMethods().size());
-    assertTrue(mainOutlineClazz.allMethods().stream().noneMatch(this::referenceFeatureClass));
+    ClassSubject clazz = inspector.clazz(OutlineOptions.CLASS_NAME);
+    assertThat(clazz, isPresent());
+    assertEquals(1, clazz.allMethods().size());
+    assertTrue(clazz.allMethods().stream().noneMatch(this::referenceFeatureClass));
   }
 
   @Test
@@ -154,16 +124,12 @@
     // Check that parts of method1, ..., method4 in FeatureClass was not outlined.
     CodeInspector featureInspector = new CodeInspector(featureCode);
     ClassSubject featureClass = featureInspector.clazz(FeatureClass.class);
-
-    // Note, this code does not really check a valid property now as the name of the outline is not
-    // known.
     assertThat(featureClass, isPresent());
     String outlineClassName =
         ClassNameMapper.mapperFromString(compileResult.getProguardMap())
             .getObfuscatedToOriginalMapping()
             .inverse
-            .get(SyntheticItemsTestUtils.syntheticOutlineClass(TestClass.class, 0).getTypeName());
-
+            .get(OutlineOptions.CLASS_NAME);
     assertFalse(invokesOutline(featureClass.uniqueMethodWithName("method1"), outlineClassName));
     assertFalse(invokesOutline(featureClass.uniqueMethodWithName("method2"), outlineClassName));
     assertFalse(invokesOutline(featureClass.uniqueMethodWithName("method3"), outlineClassName));
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/classtypes/B134462736.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/classtypes/B134462736.java
index 39c95f1..eab6811 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/classtypes/B134462736.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/classtypes/B134462736.java
@@ -11,7 +11,7 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -37,12 +37,11 @@
   }
 
   private void validateOutlining(CodeInspector inspector) {
-    ClassSubject outlineClass =
-        inspector.clazz(SyntheticItemsTestUtils.syntheticOutlineClass(TestClass.class, 0));
+    ClassSubject outlineClass = inspector.clazz(OutlineOptions.CLASS_NAME);
     MethodSubject outline0Method =
         outlineClass.method(
             "void",
-            SyntheticItemsTestUtils.syntheticMethodName(),
+            "outline0",
             ImmutableList.of(
                 StringBuilder.class.getTypeName(),
                 String.class.getTypeName(),
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/outliner/primitivetypes/PrimitiveTypesTest.java b/src/test/java/com/android/tools/r8/ir/optimize/outliner/primitivetypes/PrimitiveTypesTest.java
index 4b81714..db3ef77 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/outliner/primitivetypes/PrimitiveTypesTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/outliner/primitivetypes/PrimitiveTypesTest.java
@@ -12,7 +12,7 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
+import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -38,13 +38,10 @@
   }
 
   private void validateOutlining(CodeInspector inspector, Class<?> testClass, String argumentType) {
-    ClassSubject outlineClass =
-        inspector.clazz(SyntheticItemsTestUtils.syntheticOutlineClass(testClass, 0));
+    ClassSubject outlineClass = inspector.clazz(OutlineOptions.CLASS_NAME);
     MethodSubject outline0Method =
         outlineClass.method(
-            "java.lang.String",
-            SyntheticItemsTestUtils.syntheticMethodName(),
-            ImmutableList.of(argumentType, argumentType));
+            "java.lang.String", "outline0", ImmutableList.of(argumentType, argumentType));
     assertThat(outline0Method, isPresent());
     ClassSubject classSubject = inspector.clazz(testClass);
     assertThat(
diff --git a/src/test/java/com/android/tools/r8/smali/OutlineTest.java b/src/test/java/com/android/tools/r8/smali/OutlineTest.java
index efe3826..04ac085 100644
--- a/src/test/java/com/android/tools/r8/smali/OutlineTest.java
+++ b/src/test/java/com/android/tools/r8/smali/OutlineTest.java
@@ -30,18 +30,14 @@
 import com.android.tools.r8.graph.DexCode;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.references.ClassReference;
-import com.android.tools.r8.references.Reference;
 import com.android.tools.r8.smali.SmaliBuilder.MethodSignature;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
 import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
 import com.google.common.collect.ImmutableList;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -54,10 +50,6 @@
 
 public class OutlineTest extends SmaliTestBase {
 
-  private static ClassReference OUTLINE_CLASS =
-      SyntheticItemsTestUtils.syntheticOutlineClass(
-          Reference.classFromTypeName(DEFAULT_CLASS_NAME), 0);
-
   private static final String stringBuilderAppendSignature =
       "Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;";
   private static final String stringBuilderAppendDoubleSignature =
@@ -93,13 +85,12 @@
   }
 
   private String firstOutlineMethodName() {
-    return OUTLINE_CLASS.getTypeName() + '.' + SyntheticItemsTestUtils.syntheticMethodName();
+    return OutlineOptions.CLASS_NAME + '.' + OutlineOptions.METHOD_PREFIX + "0";
   }
 
-  private static boolean isOutlineMethodName(DexMethod method) {
-    return SyntheticItemsTestUtils.isExternalOutlineClass(
-            Reference.classFromDescriptor(method.holder.toDescriptorString()))
-        && method.name.toString().equals(SyntheticItemsTestUtils.syntheticMethodName());
+  private boolean isOutlineMethodName(String qualifiedName) {
+    String qualifiedPrefix = OutlineOptions.CLASS_NAME + '.' + OutlineOptions.METHOD_PREFIX;
+    return qualifiedName.indexOf(qualifiedPrefix) == 0;
   }
 
   @Test
@@ -151,6 +142,7 @@
 
       AndroidApp originalApplication = buildApplication(builder);
       AndroidApp processedApplication = processApplication(originalApplication, options);
+      assertEquals(2, getNumberOfProgramClasses(processedApplication));
 
       // Return the processed method for inspection.
       DexEncodedMethod method = getMethod(processedApplication, signature);
@@ -159,7 +151,7 @@
       assertTrue(code.instructions[0] instanceof ConstString);
       assertTrue(code.instructions[1] instanceof InvokeStatic);
       InvokeStatic invoke = (InvokeStatic) code.instructions[1];
-      assertTrue(isOutlineMethodName(invoke.getMethod()));
+      assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
 
       // Run code and check result.
       String result = runArt(processedApplication);
@@ -219,6 +211,7 @@
 
       AndroidApp originalApplication = buildApplication(builder);
       AndroidApp processedApplication = processApplication(originalApplication, options);
+      assertEquals(2, getNumberOfProgramClasses(processedApplication));
 
       // Return the processed method for inspection.
       DexEncodedMethod method = getMethod(processedApplication, signature);
@@ -232,7 +225,7 @@
       }
       assertTrue(code.instructions[firstOutlineInvoke] instanceof InvokeStatic);
       InvokeStatic invoke = (InvokeStatic) code.instructions[firstOutlineInvoke];
-      assertTrue(isOutlineMethodName(invoke.getMethod()));
+      assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
 
       // Run code and check result.
       String result = runArt(processedApplication);
@@ -280,6 +273,7 @@
     Consumer<InternalOptions> options = configureOutlineOptions(outline -> outline.threshold = 1);
     AndroidApp originalApplication = buildApplication(builder);
     AndroidApp processedApplication = processApplication(originalApplication, options);
+    assertEquals(2, getNumberOfProgramClasses(processedApplication));
 
     // Return the processed method for inspection.
     DexEncodedMethod method = getMethod(processedApplication, signature);
@@ -288,7 +282,7 @@
     assertTrue(code.instructions[0] instanceof ConstString);
     assertTrue(code.instructions[1] instanceof InvokeStatic);
     InvokeStatic invoke = (InvokeStatic) code.instructions[1];
-    assertTrue(isOutlineMethodName(invoke.getMethod()));
+    assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
 
     // Run code and check result.
     String result = runArt(processedApplication);
@@ -342,6 +336,7 @@
     Consumer<InternalOptions> options = configureOutlineOptions(outline -> outline.threshold = 1);
     AndroidApp originalApplication = buildApplication(builder);
     AndroidApp processedApplication = processApplication(originalApplication, options);
+    assertEquals(2, getNumberOfProgramClasses(processedApplication));
 
     // Return the processed method for inspection.
     DexEncodedMethod method = getMethod(processedApplication, signature);
@@ -351,7 +346,7 @@
     assertTrue(code.instructions[1] instanceof ConstString);
     assertTrue(code.instructions[2] instanceof InvokeStatic);
     InvokeStatic invoke = (InvokeStatic) code.instructions[2];
-    assertTrue(isOutlineMethodName(invoke.getMethod()));
+    assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
 
     // Run code and check result.
     String result = runArt(processedApplication);
@@ -407,6 +402,7 @@
 
       AndroidApp originalApplication = buildApplicationWithAndroidJar(builder);
       AndroidApp processedApplication = processApplication(originalApplication, options);
+      assertEquals(2, getNumberOfProgramClasses(processedApplication));
 
       // Return the processed method for inspection.
       DexEncodedMethod method = getMethod(processedApplication, signature);
@@ -416,13 +412,13 @@
       if (i < 3) {
         assertTrue(code.instructions[1] instanceof InvokeStatic);
         InvokeStatic invoke = (InvokeStatic) code.instructions[1];
-        assertTrue(isOutlineMethodName(invoke.getMethod()));
+        assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
       } else {
         assertTrue(code.instructions[1] instanceof InvokeVirtual);
         assertTrue(code.instructions[2] instanceof InvokeVirtual);
         assertTrue(code.instructions[3] instanceof InvokeStatic);
         InvokeStatic invoke = (InvokeStatic) code.instructions[3];
-        assertTrue(isOutlineMethodName(invoke.getMethod()));
+        assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
       }
 
       // Run code and check result.
@@ -484,6 +480,7 @@
 
       AndroidApp originalApplication = buildApplicationWithAndroidJar(builder);
       AndroidApp processedApplication = processApplication(originalApplication, options);
+      assertEquals(2, getNumberOfProgramClasses(processedApplication));
 
       // Return the processed method for inspection.
       DexEncodedMethod method = getMethod(processedApplication, signature);
@@ -493,13 +490,13 @@
       if (i < 3) {
         assertTrue(code.instructions[1] instanceof InvokeStatic);
         InvokeStatic invoke = (InvokeStatic) code.instructions[1];
-        assertTrue(isOutlineMethodName(invoke.getMethod()));
+        assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
       } else {
         assertTrue(code.instructions[1] instanceof InvokeVirtual);
         assertTrue(code.instructions[2] instanceof InvokeVirtual);
         assertTrue(code.instructions[3] instanceof InvokeStatic);
         InvokeStatic invoke = (InvokeStatic) code.instructions[3];
-        assertTrue(isOutlineMethodName(invoke.getMethod()));
+        assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
       }
 
       // Run code and check result.
@@ -556,6 +553,7 @@
 
       AndroidApp originalApplication = buildApplicationWithAndroidJar(builder);
       AndroidApp processedApplication = processApplication(originalApplication, options);
+      assertEquals(2, getNumberOfProgramClasses(processedApplication));
 
       // Return the processed main method for inspection.
       DexEncodedMethod mainMethod = getMethod(processedApplication, mainSignature);
@@ -571,14 +569,14 @@
       }
       if (i == 2) {
         InvokeStatic invoke = (InvokeStatic) mainCode.instructions[4];
-        assertTrue(isOutlineMethodName(invoke.getMethod()));
+        assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
       } else if (i == 3) {
         InvokeStatic invoke = (InvokeStatic) mainCode.instructions[1];
-        assertTrue(isOutlineMethodName(invoke.getMethod()));
+        assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
       } else {
         assert i == 4 || i == 5;
         InvokeStatic invoke = (InvokeStatic) mainCode.instructions[2];
-        assertTrue(isOutlineMethodName(invoke.getMethod()));
+        assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
       }
 
       // Run code and check result.
@@ -655,19 +653,19 @@
 
     AndroidApp originalApplication = buildApplicationWithAndroidJar(builder);
     AndroidApp processedApplication = processApplication(originalApplication, options);
-    assertEquals(3, getNumberOfProgramClasses(processedApplication));
+    assertEquals(2, getNumberOfProgramClasses(processedApplication));
 
     DexCode code1 = getMethod(processedApplication, signature1).getCode().asDexCode();
     assertEquals(4, code1.instructions.length);
     assertTrue(code1.instructions[1] instanceof InvokeStatic);
     InvokeStatic invoke1 = (InvokeStatic) code1.instructions[1];
-    assertTrue(isOutlineMethodName(invoke1.getMethod()));
+    assertTrue(isOutlineMethodName(invoke1.getMethod().qualifiedName()));
 
     DexCode code2 = getMethod(processedApplication, signature2).getCode().asDexCode();
     assertEquals(5, code2.instructions.length);
     assertTrue(code2.instructions[2] instanceof InvokeStatic);
     InvokeStatic invoke2 = (InvokeStatic) code2.instructions[2];
-    assertTrue(isOutlineMethodName(invoke1.getMethod()));
+    assertTrue(isOutlineMethodName(invoke1.getMethod().qualifiedName()));
 
     // Run code and check result.
     String result = runArt(processedApplication);
@@ -723,6 +721,7 @@
 
       AndroidApp originalApplication = buildApplicationWithAndroidJar(builder);
       AndroidApp processedApplication = processApplication(originalApplication, options);
+      assertEquals(2, getNumberOfProgramClasses(processedApplication));
 
       DexCode code = getMethod(processedApplication, signature).getCode().asDexCode();
       int outlineInstructionIndex;
@@ -740,10 +739,10 @@
       Instruction instruction = code.instructions[outlineInstructionIndex];
       if (instruction instanceof InvokeStatic) {
         InvokeStatic invoke = (InvokeStatic) instruction;
-        assertTrue(isOutlineMethodName(invoke.getMethod()));
+        assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
       } else {
         InvokeStaticRange invoke = (InvokeStaticRange) instruction;
-        assertTrue(isOutlineMethodName(invoke.getMethod()));
+        assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
       }
 
       // Run code and check result.
@@ -792,7 +791,7 @@
     InvokeStatic invoke;
     assertTrue(code.instructions[0] instanceof InvokeStatic);
     invoke = (InvokeStatic) code.instructions[0];
-    assertTrue(isOutlineMethodName(invoke.getMethod()));
+    assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
 
     // Run code and check result.
     String result = runArt(processedApplication);
@@ -860,15 +859,16 @@
 
     AndroidApp originalApplication = buildApplicationWithAndroidJar(builder);
     AndroidApp processedApplication = processApplication(originalApplication, options);
-    assertEquals(4, getNumberOfProgramClasses(processedApplication));
+    assertEquals(2, getNumberOfProgramClasses(processedApplication));
 
     // Check that three outlining methods was created.
     CodeInspector inspector = new CodeInspector(processedApplication);
-    List<DexEncodedMethod> outlineMethods = getOutlineMethods(inspector);
-    assertEquals(3, outlineMethods.size());
+    ClassSubject clazz = inspector.clazz(OutlineOptions.CLASS_NAME);
+    assertTrue(clazz.isPresent());
+    assertEquals(3, clazz.getDexProgramClass().getMethodCollection().numberOfDirectMethods());
     // Collect the return types of the outlines for the body of method1 and method2.
     List<DexType> r = new ArrayList<>();
-    for (DexEncodedMethod directMethod : outlineMethods) {
+    for (DexEncodedMethod directMethod : clazz.getDexProgramClass().directMethods()) {
       if (directMethod.getCode().asDexCode().instructions[0] instanceof InvokeVirtual) {
         r.add(directMethod.method.proto.returnType);
       }
@@ -885,16 +885,6 @@
     assertEquals("TestTestTestTestTest", result);
   }
 
-  private static List<DexEncodedMethod> getOutlineMethods(CodeInspector inspector) {
-    List<DexEncodedMethod> outlineMethods = new ArrayList<>();
-    for (FoundClassSubject clazz : inspector.allClasses()) {
-      if (SyntheticItemsTestUtils.isExternalOutlineClass(clazz.getFinalReference())) {
-        clazz.forAllMethods(m -> outlineMethods.add(m.getMethod()));
-      }
-    }
-    return outlineMethods;
-  }
-
   @Test
   public void outlineMultipleTimes() throws Exception {
     SmaliBuilder builder = new SmaliBuilder(DEFAULT_CLASS_NAME);
@@ -941,18 +931,15 @@
 
     AndroidApp originalApplication = buildApplicationWithAndroidJar(builder);
     AndroidApp processedApplication = processApplication(originalApplication, options);
-    assertEquals(3, getNumberOfProgramClasses(processedApplication));
+    assertEquals(2, getNumberOfProgramClasses(processedApplication));
 
     final int count = 10;
-    // Process the application several times. Each time will outline the previous outlines.
-    for (int i = 1; i < count; i++) {
+    // Process the application several times. Each time will outline the previous outline.
+    for (int i = 0; i < count; i++) {
       // Build a new application with the Outliner class.
       originalApplication = processedApplication;
-      processedApplication =
-          processApplication(
-              originalApplication,
-              options.andThen(o -> o.testing.allowConflictingSyntheticTypes = true));
-      assertEquals((i + 1) * 3, getNumberOfProgramClasses(processedApplication));
+      processedApplication = processApplication(originalApplication, options);
+      assertEquals(i + 3, getNumberOfProgramClasses(processedApplication));
     }
 
     // Process the application several times. No more outlining as threshold has been raised.
@@ -967,7 +954,7 @@
       // Build a new application with the Outliner class.
       originalApplication = processedApplication;
       processedApplication = processApplication(originalApplication, options);
-      assertEquals(count * 3, getNumberOfProgramClasses(processedApplication));
+      assertEquals(count - 1 + 3, getNumberOfProgramClasses(processedApplication));
     }
 
     // Run the application with several levels of outlining.
@@ -1208,6 +1195,7 @@
 
     AndroidApp originalApplication = buildApplicationWithAndroidJar(builder);
     AndroidApp processedApplication = processApplication(originalApplication, options);
+    assertEquals(2, getNumberOfProgramClasses(processedApplication));
 
     // Return the processed method for inspection.
     DexEncodedMethod method1 = getMethod(processedApplication, signature1);
@@ -1217,7 +1205,7 @@
     assertTrue(code1.instructions[1] instanceof MoveResult);
     assertTrue(code1.instructions[2] instanceof Return);
     InvokeStatic invoke1 = (InvokeStatic) code1.instructions[0];
-    assertTrue(isOutlineMethodName(invoke1.getMethod()));
+    assertTrue(isOutlineMethodName(invoke1.getMethod().qualifiedName()));
 
     DexEncodedMethod method2 = getMethod(processedApplication, signature2);
     DexCode code2 = method2.getCode().asDexCode();
@@ -1299,7 +1287,7 @@
     assertTrue(code.instructions[5] instanceof Const4);
     assertTrue(code.instructions[6] instanceof Return);
     InvokeStatic invoke = (InvokeStatic) code.instructions[1];
-    assertTrue(isOutlineMethodName(invoke.getMethod()));
+    assertTrue(isOutlineMethodName(invoke.getMethod().qualifiedName()));
 
     // Run code and check result.
     String result = runArt(processedApplication);
@@ -1626,13 +1614,15 @@
 
     AndroidApp originalApplication = buildApplicationWithAndroidJar(builder);
     AndroidApp processedApplication = processApplication(originalApplication, options);
+    assertEquals(2, getNumberOfProgramClasses(processedApplication));
 
     // Verify the code.
     runDex2Oat(processedApplication);
   }
 
   private static boolean isOutlineInvoke(Instruction instruction) {
-    return instruction instanceof InvokeStatic && isOutlineMethodName(instruction.getMethod());
+    return instruction instanceof InvokeStatic
+        && instruction.getMethod().holder.toSourceString().equals(OutlineOptions.CLASS_NAME);
   }
 
   private void assertHasOutlineInvoke(DexEncodedMethod method) {
@@ -1709,10 +1699,10 @@
     assertHasOutlineInvoke(getMethod(processedApplication, signature2));
     assertThat(
         new CodeInspector(processedApplication)
-            .clazz(OUTLINE_CLASS)
+            .clazz(OutlineOptions.CLASS_NAME)
             .method(
                 "boolean",
-                SyntheticItemsTestUtils.syntheticMethodName(),
+                "outline0",
                 ImmutableList.of("java.io.PrintStream", "java.util.ArrayList")),
         isPresent());
 
@@ -1784,11 +1774,8 @@
     assertHasOutlineInvoke(getMethod(processedApplication, signature2));
     assertThat(
         new CodeInspector(processedApplication)
-            .clazz(OUTLINE_CLASS)
-            .method(
-                "boolean",
-                SyntheticItemsTestUtils.syntheticMethodName(),
-                ImmutableList.of("java.util.List")),
+            .clazz(OutlineOptions.CLASS_NAME)
+            .method("boolean", "outline0", ImmutableList.of("java.util.List")),
         isPresent());
 
     // Run code and check result.
@@ -1861,11 +1848,8 @@
     assertHasOutlineInvoke(getMethod(processedApplication, signature2));
     assertThat(
         new CodeInspector(processedApplication)
-            .clazz(OUTLINE_CLASS)
-            .method(
-                "boolean",
-                SyntheticItemsTestUtils.syntheticMethodName(),
-                ImmutableList.of("java.util.ArrayList")),
+            .clazz(OutlineOptions.CLASS_NAME)
+            .method("boolean", "outline0", ImmutableList.of("java.util.ArrayList")),
         isPresent());
 
     // Run code and check result.
@@ -1938,11 +1922,8 @@
     assertHasOutlineInvoke(getMethod(processedApplication, signature2));
     assertThat(
         new CodeInspector(processedApplication)
-            .clazz(OUTLINE_CLASS)
-            .method(
-                "boolean",
-                SyntheticItemsTestUtils.syntheticMethodName(),
-                ImmutableList.of("java.util.ArrayList")),
+            .clazz(OutlineOptions.CLASS_NAME)
+            .method("boolean", "outline0", ImmutableList.of("java.util.ArrayList")),
         isPresent());
 
     // Run code and check result.
diff --git a/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java b/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
index 3f9c6af..438d3f9 100644
--- a/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
+++ b/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
@@ -16,10 +16,6 @@
 
 public class SyntheticItemsTestUtils {
 
-  public static String syntheticMethodName() {
-    return SyntheticNaming.INTERNAL_SYNTHETIC_METHOD_PREFIX;
-  }
-
   public static ClassReference syntheticCompanionClass(Class<?> clazz) {
     return Reference.classFromDescriptor(
         InterfaceMethodRewriter.getCompanionClassDescriptor(
@@ -27,11 +23,8 @@
   }
 
   private static ClassReference syntheticClass(Class<?> clazz, SyntheticKind kind, int id) {
-    return syntheticClass(Reference.classFromClass(clazz), kind, id);
-  }
-
-  private static ClassReference syntheticClass(ClassReference clazz, SyntheticKind kind, int id) {
-    return SyntheticNaming.makeSyntheticReferenceForTest(clazz, kind, "" + id);
+    return SyntheticNaming.makeSyntheticReferenceForTest(
+        Reference.classFromClass(clazz), kind, "" + id);
   }
 
   public static MethodReference syntheticBackportMethod(Class<?> clazz, int id, Method method) {
@@ -40,18 +33,10 @@
     MethodReference originalMethod = Reference.methodFromMethod(method);
     return Reference.methodFromDescriptor(
         syntheticHolder.getDescriptor(),
-        syntheticMethodName(),
+        SyntheticNaming.INTERNAL_SYNTHETIC_METHOD_PREFIX,
         originalMethod.getMethodDescriptor());
   }
 
-  public static ClassReference syntheticOutlineClass(Class<?> clazz, int id) {
-    return syntheticClass(clazz, SyntheticKind.OUTLINE, id);
-  }
-
-  public static ClassReference syntheticOutlineClass(ClassReference clazz, int id) {
-    return syntheticClass(clazz, SyntheticKind.OUTLINE, id);
-  }
-
   public static ClassReference syntheticLambdaClass(Class<?> clazz, int id) {
     return syntheticClass(clazz, SyntheticNaming.SyntheticKind.LAMBDA, id);
   }
@@ -82,10 +67,6 @@
     return SyntheticNaming.isSynthetic(reference, Phase.EXTERNAL, SyntheticKind.TWR_CLOSE_RESOURCE);
   }
 
-  public static boolean isExternalOutlineClass(ClassReference reference) {
-    return SyntheticNaming.isSynthetic(reference, Phase.EXTERNAL, SyntheticKind.OUTLINE);
-  }
-
   public static Matcher<String> containsInternalSyntheticReference() {
     return containsString(SyntheticNaming.getPhaseSeparator(Phase.INTERNAL));
   }