Complete rewriting of art profiles

Bug: b/265729283
Change-Id: Ie604a5f7673ab8d8f2f966ccbf06a8490f2fe0ce
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index e9b73d4..55438d2 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -436,7 +436,7 @@
     return finalDexApp.build();
   }
 
-  static class ConvertedCfFiles implements DexIndexedConsumer, ProgramResourceProvider {
+  public static class ConvertedCfFiles implements DexIndexedConsumer, ProgramResourceProvider {
 
     private final List<ProgramResource> resources = new ArrayList<>();
 
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexList.java b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
index 7d1c9bd..3c17174 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexList.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
@@ -15,6 +15,7 @@
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.SubtypingInfo;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
 import com.android.tools.r8.shaking.Enqueuer;
 import com.android.tools.r8.shaking.EnqueuerFactory;
 import com.android.tools.r8.shaking.MainDexInfo;
@@ -65,8 +66,12 @@
 
     SubtypingInfo subtypingInfo = SubtypingInfo.create(appView);
 
+    ArtProfileCollectionAdditions artProfileCollectionAdditions =
+        ArtProfileCollectionAdditions.nop();
     MainDexRootSet mainDexRootSet =
-        MainDexRootSet.builder(appView, subtypingInfo, options.mainDexKeepRules).build(executor);
+        MainDexRootSet.builder(
+                appView, artProfileCollectionAdditions, subtypingInfo, options.mainDexKeepRules)
+            .build(executor);
     appView.setMainDexRootSet(mainDexRootSet);
 
     GraphConsumer graphConsumer = options.mainDexKeptGraphConsumer;
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index c227e1c..fc7bb85 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -73,6 +73,7 @@
 import com.android.tools.r8.optimize.proto.ProtoNormalizer;
 import com.android.tools.r8.origin.CommandLineOrigin;
 import com.android.tools.r8.profile.art.ArtProfileCompletenessChecker;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
 import com.android.tools.r8.repackaging.Repackaging;
 import com.android.tools.r8.repackaging.RepackagingLens;
 import com.android.tools.r8.shaking.AbstractMethodRemover;
@@ -330,11 +331,14 @@
                     options.itemFactory, options.getMinApiLevel()));
           }
         }
+        ArtProfileCollectionAdditions artProfileCollectionAdditions =
+            ArtProfileCollectionAdditions.create(appView);
         AssumeInfoCollection.Builder assumeInfoCollectionBuilder = AssumeInfoCollection.builder();
         SubtypingInfo subtypingInfo = SubtypingInfo.create(appView);
         appView.setRootSet(
             RootSet.builder(
                     appView,
+                    artProfileCollectionAdditions,
                     subtypingInfo,
                     Iterables.concat(
                         options.getProguardConfiguration().getRules(), synthesizedProguardRules))
@@ -348,7 +352,11 @@
           assert appView.graphLens().isIdentityLens();
           // Find classes which may have code executed before secondary dex files installation.
           MainDexRootSet mainDexRootSet =
-              MainDexRootSet.builder(appView, subtypingInfo, options.mainDexKeepRules)
+              MainDexRootSet.builder(
+                      appView,
+                      artProfileCollectionAdditions,
+                      subtypingInfo,
+                      options.mainDexKeepRules)
                   .build(executorService);
           appView.setMainDexRootSet(mainDexRootSet);
           appView.appInfo().unsetObsolete();
@@ -363,6 +371,7 @@
                 annotationRemoverBuilder,
                 executorService,
                 appView,
+                artProfileCollectionAdditions,
                 subtypingInfo,
                 classMergingEnqueuerExtensionBuilder);
         timing.end();
@@ -958,12 +967,14 @@
       AnnotationRemover.Builder annotationRemoverBuilder,
       ExecutorService executorService,
       AppView<AppInfoWithClassHierarchy> appView,
+      ArtProfileCollectionAdditions artProfileCollectionAdditions,
       SubtypingInfo subtypingInfo,
       RuntimeTypeCheckInfo.Builder classMergingEnqueuerExtensionBuilder)
       throws ExecutionException {
     timing.begin("Set up enqueuer");
     Enqueuer enqueuer =
-        EnqueuerFactory.createForInitialTreeShaking(appView, executorService, subtypingInfo);
+        EnqueuerFactory.createForInitialTreeShaking(
+            appView, artProfileCollectionAdditions, executorService, subtypingInfo);
     enqueuer.setAnnotationRemoverBuilder(annotationRemoverBuilder);
     if (appView.options().enableInitializedClassesInInstanceMethodsAnalysis) {
       enqueuer.registerAnalysis(new InitializedClassesInInstanceMethodsAnalysis(appView));
@@ -983,6 +994,7 @@
     timing.begin("Trace application");
     EnqueuerResult enqueuerResult =
         enqueuer.traceApplication(appView.rootSet(), executorService, timing);
+    assert artProfileCollectionAdditions.verifyIsCommitted();
     timing.end();
     timing.begin("Finalize enqueuer result");
     AppView<AppInfoWithLiveness> appViewWithLiveness =
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index 4300df0..99cb304 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -7,6 +7,7 @@
 
 import com.android.tools.r8.ByteBufferProvider;
 import com.android.tools.r8.ByteDataView;
+import com.android.tools.r8.D8.ConvertedCfFiles;
 import com.android.tools.r8.DataDirectoryResource;
 import com.android.tools.r8.DataEntryResource;
 import com.android.tools.r8.DataResourceConsumer;
@@ -432,7 +433,9 @@
       // Fail if there are pending errors, e.g., the program consumers may have reported errors.
       options.reporter.failIfPendingErrors();
       // Supply info to all additional resource consumers.
-      supplyAdditionalConsumers(appView);
+      if (!(programConsumer instanceof ConvertedCfFiles)) {
+        supplyAdditionalConsumers(appView);
+      }
     } finally {
       timing.end();
     }
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index fb288a7..9560129 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -916,6 +916,15 @@
             appView
                 .withLiveness()
                 .setAppInfo(appView.appInfoWithLiveness().rewrittenWithLens(application, lens));
+          } else {
+            assert appView.hasClassHierarchy();
+            AppView<AppInfoWithClassHierarchy> appViewWithClassHierarchy =
+                appView.withClassHierarchy();
+            AppInfoWithClassHierarchy appInfo = appViewWithClassHierarchy.appInfo();
+            MainDexInfo rewrittenMainDexInfo =
+                appInfo.getMainDexInfo().rewrittenWithLens(appView.getSyntheticItems(), lens);
+            appViewWithClassHierarchy.setAppInfo(
+                appInfo.rebuildWithMainDexInfo(rewrittenMainDexInfo));
           }
           appView.setAppServices(appView.appServices().rewrittenWithLens(lens));
           appView.setArtProfileCollection(
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index 22d3978..01fa0e0 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -265,6 +265,10 @@
     forEachStaticField(field -> consumer.accept(new ProgramField(this, field)));
   }
 
+  public void forEachProgramStaticMethod(Consumer<? super ProgramMethod> consumer) {
+    forEachProgramDirectMethodMatching(DexEncodedMethod::isStatic, consumer);
+  }
+
   public void forEachProgramMember(Consumer<? super ProgramMember<?, ?>> consumer) {
     forEachProgramField(consumer);
     forEachProgramMethod(consumer);
@@ -310,7 +314,7 @@
   }
 
   public void forEachProgramDirectMethodMatching(
-      Predicate<DexEncodedMethod> predicate, Consumer<ProgramMethod> consumer) {
+      Predicate<DexEncodedMethod> predicate, Consumer<? super ProgramMethod> consumer) {
     methodCollection.forEachDirectMethodMatching(
         predicate, method -> consumer.accept(new ProgramMethod(this, method)));
   }
diff --git a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
index 8c949fe..ef0d7ff 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
@@ -1213,6 +1213,10 @@
       super(typesCausingError);
     }
 
+    public static NoSuchMethodResult getEmptyNoSuchMethodResult() {
+      return INSTANCE;
+    }
+
     @Override
     public boolean isNoSuchMethodErrorResult(DexClass context, AppInfoWithClassHierarchy appInfo) {
       return true;
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
index b84809e..b8782e2 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -154,7 +154,12 @@
     appView.setHorizontallyMergedClasses(mergedClasses, mode);
 
     HorizontalClassMergerGraphLens horizontalClassMergerGraphLens =
-        createLens(mergedClasses, lensBuilder, mode, syntheticArgumentClass);
+        createLens(
+            mergedClasses,
+            lensBuilder,
+            mode,
+            artProfileCollectionAdditions,
+            syntheticArgumentClass);
     artProfileCollectionAdditions =
         artProfileCollectionAdditions.rewriteMethodReferences(
             horizontalClassMergerGraphLens::getNextMethodToInvoke);
@@ -185,7 +190,7 @@
                       .appInfo()
                       .getMainDexInfo()
                       .rewrittenWithLens(syntheticItems, horizontalClassMergerGraphLens)));
-      appView.setGraphLens(horizontalClassMergerGraphLens);
+      appView.rewriteWithD8Lens(horizontalClassMergerGraphLens);
     }
     codeProvider.setGraphLens(horizontalClassMergerGraphLens);
 
@@ -391,8 +396,15 @@
       HorizontallyMergedClasses mergedClasses,
       HorizontalClassMergerGraphLens.Builder lensBuilder,
       Mode mode,
+      ArtProfileCollectionAdditions artProfileCollectionAdditions,
       SyntheticArgumentClass syntheticArgumentClass) {
-    return new TreeFixer(appView, mergedClasses, lensBuilder, mode, syntheticArgumentClass)
+    return new TreeFixer(
+            appView,
+            mergedClasses,
+            lensBuilder,
+            mode,
+            artProfileCollectionAdditions,
+            syntheticArgumentClass)
         .fixupTypeReferences();
   }
 
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
index 51b4939..53f08a6 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
@@ -99,7 +99,7 @@
 
     private final MutableBidirectionalManyToOneRepresentativeMap<DexField, DexField>
         newFieldSignatures = BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
-    private final MutableBidirectionalManyToOneMap<DexMethod, DexMethod> methodMap =
+    final MutableBidirectionalManyToOneMap<DexMethod, DexMethod> methodMap =
         BidirectionalManyToOneHashMap.newIdentityHashMap();
     private final MutableBidirectionalManyToOneRepresentativeMap<DexMethod, DexMethod>
         newMethodSignatures = BidirectionalManyToOneRepresentativeHashMap.newIdentityHashMap();
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
index 31753bf..a4b8ae0 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/TreeFixer.java
@@ -21,8 +21,10 @@
 import com.android.tools.r8.graph.TreeFixerBase;
 import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger.Mode;
 import com.android.tools.r8.ir.conversion.ExtraUnusedNullParameter;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
 import com.android.tools.r8.shaking.AnnotationFixer;
 import com.android.tools.r8.utils.ArrayUtils;
+import com.android.tools.r8.utils.Box;
 import com.android.tools.r8.utils.OptionalBool;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
@@ -47,6 +49,7 @@
   private final Mode mode;
   private final HorizontalClassMergerGraphLens.Builder lensBuilder;
   private final DexItemFactory dexItemFactory;
+  private final ArtProfileCollectionAdditions artProfileCollectionAdditions;
   private final SyntheticArgumentClass syntheticArgumentClass;
 
   private final Map<DexProgramClass, DexType> originalSuperTypes = new IdentityHashMap<>();
@@ -58,12 +61,14 @@
       HorizontallyMergedClasses mergedClasses,
       HorizontalClassMergerGraphLens.Builder lensBuilder,
       Mode mode,
+      ArtProfileCollectionAdditions artProfileCollectionAdditions,
       SyntheticArgumentClass syntheticArgumentClass) {
     super(appView);
     this.appView = appView;
     this.mergedClasses = mergedClasses;
     this.mode = mode;
     this.lensBuilder = lensBuilder;
+    this.artProfileCollectionAdditions = artProfileCollectionAdditions;
     this.syntheticArgumentClass = syntheticArgumentClass;
     this.dexItemFactory = appView.dexItemFactory();
   }
@@ -289,15 +294,36 @@
 
       if (method.isInstanceInitializer()) {
         // If the method is an instance initializer, then add extra nulls.
+        Box<Set<DexType>> usedSyntheticArgumentClasses = new Box<>();
         newMethodReference =
             dexItemFactory.createInstanceInitializerWithFreshProto(
                 newMethodReference,
                 syntheticArgumentClass.getArgumentClasses(),
-                tryMethod -> !newMethods.contains(tryMethod.getSignature()));
+                tryMethod -> !newMethods.contains(tryMethod.getSignature()),
+                usedSyntheticArgumentClasses::set);
         lensBuilder.addExtraParameters(
             originalMethodReference,
             ExtraUnusedNullParameter.computeExtraUnusedNullParameters(
                 originalMethodReference, newMethodReference));
+
+        // Amend the art profile collection.
+        if (usedSyntheticArgumentClasses.isSet()) {
+          Set<DexMethod> previousMethodReferences =
+              lensBuilder.methodMap.getKeys(originalMethodReference);
+          if (previousMethodReferences.isEmpty()) {
+            artProfileCollectionAdditions.applyIfContextIsInProfile(
+                originalMethodReference,
+                additionsBuilder ->
+                    usedSyntheticArgumentClasses.get().forEach(additionsBuilder::addRule));
+          } else {
+            for (DexMethod previousMethodReference : previousMethodReferences) {
+              artProfileCollectionAdditions.applyIfContextIsInProfile(
+                  previousMethodReference,
+                  additionsBuilder ->
+                      usedSyntheticArgumentClasses.get().forEach(additionsBuilder::addRule));
+            }
+          }
+        }
       } else {
         newMethodReference =
             dexItemFactory.createFreshMethodNameWithoutHolder(
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java
index 0092f10..9d03bb5 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java
@@ -309,6 +309,7 @@
       throws ExecutionException {
     CfPostProcessingDesugaringEventConsumer eventConsumer =
         CfPostProcessingDesugaringEventConsumer.createForD8(
+            appView,
             methodProcessor.getArtProfileCollectionAdditions(),
             methodProcessor,
             instructionDesugaring);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfClassSynthesizerDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/CfClassSynthesizerDesugaringEventConsumer.java
index 4e7a473..49a7dd8 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfClassSynthesizerDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfClassSynthesizerDesugaringEventConsumer.java
@@ -101,7 +101,7 @@
     }
 
     @Override
-    public void acceptCollectionConversion(ProgramMethod arrayConversion) {
+    public void acceptCollectionConversion(ProgramMethod arrayConversion, ProgramMethod context) {
       synthesizedClasses.add(arrayConversion.getHolder());
     }
   }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
index 09cc827..7290623 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaringEventConsumer.java
@@ -163,12 +163,12 @@
     }
 
     @Override
-    public void acceptCollectionConversion(ProgramMethod arrayConversion) {
+    public void acceptCollectionConversion(ProgramMethod arrayConversion, ProgramMethod context) {
       methodProcessor.scheduleMethodForProcessing(arrayConversion, outermostEventConsumer);
     }
 
     @Override
-    public void acceptCovariantRetargetMethod(ProgramMethod method) {
+    public void acceptCovariantRetargetMethod(ProgramMethod method, ProgramMethod context) {
       methodProcessor.scheduleMethodForProcessing(method, outermostEventConsumer);
     }
 
@@ -354,7 +354,7 @@
     }
 
     @Override
-    public void acceptAPIConversion(ProgramMethod method) {
+    public void acceptAPIConversionOutline(ProgramMethod method, ProgramMethod context) {
       methodProcessor.scheduleDesugaredMethodForProcessing(method);
     }
 
@@ -522,7 +522,7 @@
     }
 
     @Override
-    public void acceptCollectionConversion(ProgramMethod arrayConversion) {
+    public void acceptCollectionConversion(ProgramMethod arrayConversion, ProgramMethod context) {
       // Intentionally empty. The method will be hit by tracing if required.
     }
 
@@ -548,7 +548,7 @@
     }
 
     @Override
-    public void acceptCovariantRetargetMethod(ProgramMethod method) {
+    public void acceptCovariantRetargetMethod(ProgramMethod method, ProgramMethod context) {
       // Intentionally empty. The method will be hit by tracing if required.
     }
 
@@ -614,7 +614,7 @@
     }
 
     @Override
-    public void acceptAPIConversion(ProgramMethod method) {
+    public void acceptAPIConversionOutline(ProgramMethod method, ProgramMethod context) {
       // Intentionally empty. The method will be hit by tracing if required.
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringEventConsumer.java
index 33ff0b4..7a38cf1 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfPostProcessingDesugaringEventConsumer.java
@@ -3,15 +3,18 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.desugar;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexClassAndMethod;
 import com.android.tools.r8.graph.DexClasspathClass;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodResolutionResult.FailedResolutionResult;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.conversion.D8MethodProcessor;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.apiconversion.DesugaredLibraryWrapperSynthesizerEventConsumer.DesugaredLibraryAPICallbackSynthesizorEventConsumer;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.retargeter.DesugaredLibraryRetargeterSynthesizerEventConsumer.DesugaredLibraryRetargeterPostProcessingEventConsumer;
 import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper;
 import com.android.tools.r8.ir.desugar.itf.InterfaceProcessingDesugaringEventConsumer;
@@ -35,16 +38,18 @@
         DesugaredLibraryAPICallbackSynthesizorEventConsumer {
 
   public static CfPostProcessingDesugaringEventConsumer createForD8(
+      AppView<?> appView,
       ArtProfileCollectionAdditions artProfileCollectionAdditions,
       D8MethodProcessor methodProcessor,
       CfInstructionDesugaringCollection instructionDesugaring) {
     CfPostProcessingDesugaringEventConsumer eventConsumer =
         new D8CfPostProcessingDesugaringEventConsumer(methodProcessor, instructionDesugaring);
     return ArtProfileRewritingCfPostProcessingDesugaringEventConsumer.attach(
-        artProfileCollectionAdditions, eventConsumer);
+        appView, artProfileCollectionAdditions, eventConsumer);
   }
 
   public static CfPostProcessingDesugaringEventConsumer createForR8(
+      AppView<?> appView,
       SyntheticAdditions additions,
       ArtProfileCollectionAdditions artProfileCollectionAdditions,
       CfInstructionDesugaringCollection desugaring,
@@ -52,7 +57,7 @@
     CfPostProcessingDesugaringEventConsumer eventConsumer =
         new R8PostProcessingDesugaringEventConsumer(additions, desugaring, missingClassConsumer);
     return ArtProfileRewritingCfPostProcessingDesugaringEventConsumer.attach(
-        artProfileCollectionAdditions, eventConsumer);
+        appView, artProfileCollectionAdditions, eventConsumer);
   }
 
   public abstract Set<DexMethod> getNewlyLiveMethods();
@@ -93,7 +98,7 @@
     }
 
     @Override
-    public void acceptCovariantRetargetMethod(ProgramMethod method) {
+    public void acceptCovariantRetargetMethod(ProgramMethod method, ProgramMethod context) {
       addMethodToReprocess(method);
     }
 
@@ -109,7 +114,8 @@
     }
 
     @Override
-    public void acceptDesugaredLibraryRetargeterForwardingMethod(ProgramMethod method) {
+    public void acceptDesugaredLibraryRetargeterForwardingMethod(
+        ProgramMethod method, EmulatedDispatchMethodDescriptor descriptor) {
       addMethodToReprocess(method);
     }
 
@@ -120,12 +126,13 @@
     }
 
     @Override
-    public void acceptThrowingMethod(ProgramMethod method, DexType errorType) {
+    public void acceptThrowingMethod(
+        ProgramMethod method, DexType errorType, FailedResolutionResult resolutionResult) {
       addMethodToReprocess(method);
     }
 
     @Override
-    public void acceptCollectionConversion(ProgramMethod method) {
+    public void acceptCollectionConversion(ProgramMethod method, ProgramMethod context) {
       addMethodToReprocess(method);
     }
 
@@ -216,12 +223,13 @@
     }
 
     @Override
-    public void acceptCovariantRetargetMethod(ProgramMethod method) {
+    public void acceptCovariantRetargetMethod(ProgramMethod method, ProgramMethod context) {
       additions.addLiveMethod(method);
     }
 
     @Override
-    public void acceptDesugaredLibraryRetargeterForwardingMethod(ProgramMethod method) {
+    public void acceptDesugaredLibraryRetargeterForwardingMethod(
+        ProgramMethod method, EmulatedDispatchMethodDescriptor descriptor) {
       additions.addLiveMethod(method);
     }
 
@@ -232,12 +240,13 @@
     }
 
     @Override
-    public void acceptThrowingMethod(ProgramMethod method, DexType errorType) {
+    public void acceptThrowingMethod(
+        ProgramMethod method, DexType errorType, FailedResolutionResult resolutionResult) {
       additions.addLiveMethod(method);
     }
 
     @Override
-    public void acceptCollectionConversion(ProgramMethod method) {
+    public void acceptCollectionConversion(ProgramMethod method, ProgramMethod context) {
       additions.addLiveMethod(method);
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryConversionCfProvider.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryConversionCfProvider.java
index c4ce708..9a75734 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryConversionCfProvider.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryConversionCfProvider.java
@@ -260,7 +260,7 @@
                                         parameterConversions,
                                         invoke.getOpcode())
                                     .generateCfCode()));
-    eventConsumer.acceptAPIConversion(outline);
+    eventConsumer.acceptAPIConversionOutline(outline, context);
     return outline;
   }
 
@@ -362,7 +362,8 @@
                             methodSignature ->
                                 computeParameterConversionCfCode(
                                     methodSignature.holder, invokedMethod, parameterConversions)));
-    eventConsumer.acceptAPIConversion(parameterConversion);
+    eventConsumer.acceptAPIConversionOutline(
+        parameterConversion, methodProcessingContext.getMethodContext());
     cfInstructions.add(
         new CfInvoke(Opcodes.INVOKESTATIC, parameterConversion.getReference(), false));
     int arrayLocal = freshLocalProvider.getFreshLocal(ValueType.OBJECT.requiredRegisters());
@@ -461,6 +462,7 @@
                 destIsVivified,
                 apiConversionCollection,
                 eventConsumer,
+                context,
                 contextSupplier),
         context);
   }
@@ -479,6 +481,7 @@
                 destIsVivified,
                 apiConversionCollection,
                 eventConsumer,
+                context,
                 contextSupplier),
         context);
   }
@@ -507,7 +510,12 @@
         wrapperSynthesizer,
         (argType, apiGenericTypesConversion) ->
             wrapperSynthesizer.ensureConversionMethod(
-                argType, destIsVivified, apiGenericTypesConversion, eventConsumer, contextSupplier),
+                argType,
+                destIsVivified,
+                apiGenericTypesConversion,
+                eventConsumer,
+                context,
+                contextSupplier),
         context);
   }
 
@@ -522,7 +530,12 @@
         wrapperSynthesizer,
         (argType, apiGenericTypesConversion) ->
             wrapperSynthesizer.getExistingProgramConversionMethod(
-                argType, destIsVivified, apiGenericTypesConversion, eventConsumer, contextSupplier),
+                argType,
+                destIsVivified,
+                apiGenericTypesConversion,
+                eventConsumer,
+                context,
+                contextSupplier),
         context);
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
index 40f9d67..cc5d7d6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
@@ -197,6 +197,7 @@
       boolean destIsVivified,
       DexMethod apiGenericTypesConversion,
       DesugaredLibraryClasspathWrapperSynthesizeEventConsumer eventConsumer,
+      ProgramMethod context,
       Supplier<UniqueContext> contextSupplier) {
     if (apiGenericTypesConversion != null) {
       assert !type.isArrayType();
@@ -205,7 +206,8 @@
     DexType srcType = destIsVivified ? type : vivifiedTypeFor(type);
     DexType destType = destIsVivified ? vivifiedTypeFor(type) : type;
     if (type.isArrayType()) {
-      return ensureArrayConversionMethod(type, srcType, destType, eventConsumer, contextSupplier);
+      return ensureArrayConversionMethod(
+          type, srcType, destType, eventConsumer, context, contextSupplier);
     }
     DexMethod customConversion = getCustomConversion(type, srcType, destType);
     if (customConversion != null) {
@@ -231,6 +233,7 @@
       DexType srcType,
       DexType destType,
       DesugaredLibraryClasspathWrapperSynthesizeEventConsumer eventConsumer,
+      ProgramMethod context,
       Supplier<UniqueContext> contextSupplier) {
     DexMethod conversion =
         ensureConversionMethod(
@@ -238,9 +241,10 @@
             srcType == type,
             null,
             eventConsumer,
+            context,
             contextSupplier);
     return ensureArrayConversionMethod(
-        srcType, destType, eventConsumer, contextSupplier, conversion);
+        srcType, destType, eventConsumer, context, contextSupplier, conversion);
   }
 
   private DexMethod ensureArrayConversionMethodFromExistingBaseConversion(
@@ -248,6 +252,7 @@
       DexType srcType,
       DexType destType,
       DesugaredLibraryL8ProgramWrapperSynthesizerEventConsumer eventConsumer,
+      ProgramMethod context,
       Supplier<UniqueContext> contextSupplier) {
     DexMethod conversion =
         getExistingProgramConversionMethod(
@@ -255,15 +260,17 @@
             srcType == type,
             null,
             eventConsumer,
+            context,
             contextSupplier);
     return ensureArrayConversionMethod(
-        srcType, destType, eventConsumer, contextSupplier, conversion);
+        srcType, destType, eventConsumer, context, contextSupplier, conversion);
   }
 
   private DexMethod ensureArrayConversionMethod(
       DexType srcType,
       DexType destType,
       DesugaredLibraryWrapperSynthesizerEventConsumer eventConsumer,
+      ProgramMethod context,
       Supplier<UniqueContext> contextSupplier,
       DexMethod conversion) {
     ProgramMethod arrayConversion =
@@ -286,7 +293,7 @@
                                         destType,
                                         conversion)
                                     .generateCfCode()));
-    eventConsumer.acceptCollectionConversion(arrayConversion);
+    eventConsumer.acceptCollectionConversion(arrayConversion, context);
     return arrayConversion.getReference();
   }
 
@@ -295,6 +302,7 @@
       boolean destIsVivified,
       DexMethod apiGenericTypesConversion,
       DesugaredLibraryL8ProgramWrapperSynthesizerEventConsumer eventConsumer,
+      ProgramMethod context,
       Supplier<UniqueContext> contextSupplier) {
     if (apiGenericTypesConversion != null) {
       assert !type.isArrayType();
@@ -304,7 +312,7 @@
     DexType destType = destIsVivified ? vivifiedTypeFor(type) : type;
     if (type.isArrayType()) {
       return ensureArrayConversionMethodFromExistingBaseConversion(
-          type, srcType, destType, eventConsumer, contextSupplier);
+          type, srcType, destType, eventConsumer, context, contextSupplier);
     }
     DexMethod customConversion = getCustomConversion(type, srcType, destType);
     if (customConversion != null) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizerEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizerEventConsumer.java
index 161247c..9a57f6b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizerEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizerEventConsumer.java
@@ -10,7 +10,7 @@
 
 public interface DesugaredLibraryWrapperSynthesizerEventConsumer {
 
-  void acceptCollectionConversion(ProgramMethod arrayConversion);
+  void acceptCollectionConversion(ProgramMethod arrayConversion, ProgramMethod context);
 
   interface DesugaredLibraryL8ProgramWrapperSynthesizerEventConsumer
       extends DesugaredLibraryWrapperSynthesizerEventConsumer {
@@ -33,7 +33,7 @@
   interface DesugaredLibraryAPIConverterEventConsumer
       extends DesugaredLibraryClasspathWrapperSynthesizeEventConsumer {
 
-    void acceptAPIConversion(ProgramMethod method);
+    void acceptAPIConversionOutline(ProgramMethod method, ProgramMethod context);
   }
 
   interface DesugaredLibraryAPICallbackSynthesizorEventConsumer
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/SupportedClasses.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/SupportedClasses.java
index 3c1cfd6..32f1bf9 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/SupportedClasses.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/lint/SupportedClasses.java
@@ -11,6 +11,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSortedMap;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.IdentityHashMap;
@@ -83,26 +84,26 @@
 
       private final DexClass clazz;
       private ClassAnnotation classAnnotation;
-      private final List<DexEncodedMethod> supportedMethods = new ArrayList<>();
+      private final Map<DexMethod, DexEncodedMethod> supportedMethods = new IdentityHashMap<>();
       private final Map<DexMethod, MethodAnnotation> methodAnnotations = new HashMap<>();
 
       private Builder(DexClass clazz) {
         this.clazz = clazz;
       }
 
-      void forEachMethods(BiConsumer<DexClass, List<DexEncodedMethod>> biConsumer) {
-        biConsumer.accept(clazz, supportedMethods);
+      void forEachMethods(BiConsumer<DexClass, Collection<DexEncodedMethod>> biConsumer) {
+        biConsumer.accept(clazz, supportedMethods.values());
       }
 
       void forEachMethod(BiConsumer<DexClass, DexEncodedMethod> biConsumer) {
-        for (DexEncodedMethod dexEncodedMethod : supportedMethods) {
+        for (DexEncodedMethod dexEncodedMethod : supportedMethods.values()) {
           biConsumer.accept(clazz, dexEncodedMethod);
         }
       }
 
       void addSupportedMethod(DexEncodedMethod method) {
         assert method.getHolderType() == clazz.type;
-        supportedMethods.add(method);
+        supportedMethods.put(method.getReference(), method);
       }
 
       void annotateClass(ClassAnnotation annotation) {
@@ -123,9 +124,13 @@
       }
 
       SupportedClass build() {
-        supportedMethods.sort(Comparator.comparing(DexEncodedMethod::getReference));
+        List<DexEncodedMethod> supportedMethodsSorted = new ArrayList<>(supportedMethods.values());
+        supportedMethodsSorted.sort(Comparator.comparing(DexEncodedMethod::getReference));
         return new SupportedClass(
-            clazz, classAnnotation, ImmutableList.copyOf(supportedMethods), methodAnnotations);
+            clazz,
+            classAnnotation,
+            ImmutableList.copyOf(supportedMethodsSorted),
+            methodAnnotations);
       }
     }
   }
@@ -138,7 +143,7 @@
 
     Map<DexType, SupportedClass.Builder> supportedClassBuilders = new IdentityHashMap<>();
 
-    void forEachClassAndMethods(BiConsumer<DexClass, List<DexEncodedMethod>> biConsumer) {
+    void forEachClassAndMethods(BiConsumer<DexClass, Collection<DexEncodedMethod>> biConsumer) {
       supportedClassBuilders
           .values()
           .forEach(classBuilder -> classBuilder.forEachMethods(biConsumer));
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterPostProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterPostProcessor.java
index cc5abfd..dcf5c0a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterPostProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterPostProcessor.java
@@ -138,7 +138,7 @@
         DexEncodedMethod newMethod = createForwardingMethod(itfMethod, descriptor, clazz);
         clazz.addVirtualMethod(newMethod);
         eventConsumer.acceptDesugaredLibraryRetargeterForwardingMethod(
-            new ProgramMethod(clazz, newMethod));
+            new ProgramMethod(clazz, newMethod), descriptor);
       }
     }
   }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSynthesizerEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSynthesizerEventConsumer.java
index 63dcba2..6e491ff 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSynthesizerEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSynthesizerEventConsumer.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.graph.DexClasspathClass;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
 
 public interface DesugaredLibraryRetargeterSynthesizerEventConsumer {
 
@@ -18,13 +19,14 @@
   interface DesugaredLibraryRetargeterInstructionEventConsumer {
     void acceptDesugaredLibraryRetargeterDispatchClasspathClass(DexClasspathClass clazz);
 
-    void acceptCovariantRetargetMethod(ProgramMethod method);
+    void acceptCovariantRetargetMethod(ProgramMethod method, ProgramMethod context);
   }
 
   interface DesugaredLibraryRetargeterPostProcessingEventConsumer
       extends DesugaredLibraryRetargeterInstructionEventConsumer {
     void acceptInterfaceInjection(DexProgramClass clazz, DexClass newInterface);
 
-    void acceptDesugaredLibraryRetargeterForwardingMethod(ProgramMethod method);
+    void acceptDesugaredLibraryRetargeterForwardingMethod(
+        ProgramMethod method, EmulatedDispatchMethodDescriptor descriptor);
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSyntheticHelper.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSyntheticHelper.java
index ae5814a..52fa933 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSyntheticHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSyntheticHelper.java
@@ -57,7 +57,7 @@
                                     .setNonStaticSource(target)
                                     .setCastResult()
                                     .build()));
-    eventConsumer.acceptCovariantRetargetMethod(method);
+    eventConsumer.acceptCovariantRetargetMethod(method, methodProcessingContext.getMethodContext());
     return method.getReference();
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
index 32e2c37..6a74cf3 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
@@ -30,6 +30,8 @@
 import com.android.tools.r8.graph.LookupMethodTarget;
 import com.android.tools.r8.graph.MethodAccessFlags;
 import com.android.tools.r8.graph.MethodResolutionResult;
+import com.android.tools.r8.graph.MethodResolutionResult.FailedResolutionResult;
+import com.android.tools.r8.graph.MethodResolutionResult.NoSuchMethodResult;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
 import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.InterfaceMethodDesugaringMode;
@@ -126,16 +128,23 @@
   private static class SyntheticThrowingMethodInfo extends SyntheticMethodInfo {
 
     private final DexType errorType;
+    private final FailedResolutionResult resolutionResult;
 
-    SyntheticThrowingMethodInfo(ProgramMethod method, DexType errorType) {
+    SyntheticThrowingMethodInfo(
+        ProgramMethod method, DexType errorType, FailedResolutionResult resolutionResult) {
       super(method);
       this.errorType = errorType;
+      this.resolutionResult = resolutionResult;
     }
 
     DexType getErrorType() {
       return errorType;
     }
 
+    FailedResolutionResult getResolutionResult() {
+      return resolutionResult;
+    }
+
     @Override
     SyntheticThrowingMethodInfo asThrowingMethodInfo() {
       return this;
@@ -511,8 +520,11 @@
               eventConsumer.acceptInterfaceMethodDesugaringForwardingMethod(
                   info.getMethod(), info.asForwardingMethodInfo().getBaseMethod());
             } else {
+              SyntheticThrowingMethodInfo throwingMethodInfo = info.asThrowingMethodInfo();
               eventConsumer.acceptThrowingMethod(
-                  info.getMethod(), info.asThrowingMethodInfo().getErrorType());
+                  info.getMethod(),
+                  throwingMethodInfo.getErrorType(),
+                  throwingMethodInfo.getResolutionResult());
             }
           }
         },
@@ -842,15 +854,15 @@
       }
       if (resolutionResult.isFailedResolution()) {
         if (resolutionResult.isIncompatibleClassChangeErrorResult()) {
-          addICCEThrowingMethod(method, clazz);
+          addICCEThrowingMethod(method, clazz, resolutionResult.asFailedResolution());
           return;
         }
         if (resolutionResult.isNoSuchMethodErrorResult(clazz, appInfo)) {
-          addNoSuchMethodErrorThrowingMethod(method, clazz);
+          addNoSuchMethodErrorThrowingMethod(method, clazz, resolutionResult.asFailedResolution());
           return;
         }
         assert resolutionResult.isIllegalAccessErrorResult(clazz, appInfo);
-        addIllegalAccessErrorThrowingMethod(method, clazz);
+        addIllegalAccessErrorThrowingMethod(method, clazz, resolutionResult.asFailedResolution());
         return;
       }
     }
@@ -878,7 +890,8 @@
                   + "). Please report this issue in the D8/R8 bug tracker at"
                   + " https://issuetracker.google.com/issues/237507594.");
       // To be able to resume compilation we add a NoSuchMethodErrorThrowingMethod.
-      addNoSuchMethodErrorThrowingMethod(method, clazz);
+      addNoSuchMethodErrorThrowingMethod(
+          method, clazz, NoSuchMethodResult.getEmptyNoSuchMethodResult());
       return;
     }
     DexClassAndMethod virtualDispatchTarget = lookupMethodTarget.getTarget();
@@ -919,27 +932,37 @@
     assert existingMethodInfo == null;
   }
 
-  private void addSyntheticThrowingMethod(ProgramMethod method, DexType errorType) {
+  private void addSyntheticThrowingMethod(
+      ProgramMethod method, DexType errorType, FailedResolutionResult resolutionResult) {
     SyntheticMethodInfo existingMethodInfo =
         newSyntheticMethods
             .computeIfAbsent(method.getHolder(), key -> new ConcurrentHashMap<>())
-            .put(method.getReference(), new SyntheticThrowingMethodInfo(method, errorType));
+            .put(
+                method.getReference(),
+                new SyntheticThrowingMethodInfo(method, errorType, resolutionResult));
     assert existingMethodInfo == null;
   }
 
-  private void addICCEThrowingMethod(DexMethod method, DexClass clazz) {
-    addThrowingMethod(method, clazz, dexItemFactory.icceType);
+  private void addICCEThrowingMethod(
+      DexMethod method, DexClass clazz, FailedResolutionResult resolutionResult) {
+    addThrowingMethod(method, clazz, dexItemFactory.icceType, resolutionResult);
   }
 
-  private void addIllegalAccessErrorThrowingMethod(DexMethod method, DexClass clazz) {
-    addThrowingMethod(method, clazz, dexItemFactory.illegalAccessErrorType);
+  private void addIllegalAccessErrorThrowingMethod(
+      DexMethod method, DexClass clazz, FailedResolutionResult resolutionResult) {
+    addThrowingMethod(method, clazz, dexItemFactory.illegalAccessErrorType, resolutionResult);
   }
 
-  private void addNoSuchMethodErrorThrowingMethod(DexMethod method, DexClass clazz) {
-    addThrowingMethod(method, clazz, dexItemFactory.noSuchMethodErrorType);
+  private void addNoSuchMethodErrorThrowingMethod(
+      DexMethod method, DexClass clazz, FailedResolutionResult resolutionResult) {
+    addThrowingMethod(method, clazz, dexItemFactory.noSuchMethodErrorType, resolutionResult);
   }
 
-  private void addThrowingMethod(DexMethod method, DexClass clazz, DexType errorType) {
+  private void addThrowingMethod(
+      DexMethod method,
+      DexClass clazz,
+      DexType errorType,
+      FailedResolutionResult resolutionResult) {
     if (!clazz.isProgramClass()) {
       return;
     }
@@ -953,7 +976,8 @@
                 createExceptionThrowingCfCode(newMethod, accessFlags, errorType, dexItemFactory))
             .disableAndroidApiLevelCheck()
             .build();
-    addSyntheticThrowingMethod(newEncodedMethod.asProgramMethod(clazz.asProgramClass()), errorType);
+    addSyntheticThrowingMethod(
+        newEncodedMethod.asProgramMethod(clazz.asProgramClass()), errorType, resolutionResult);
   }
 
   private static CfCode createExceptionThrowingCfCode(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessingDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessingDesugaringEventConsumer.java
index dde1382..a918d81 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessingDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessingDesugaringEventConsumer.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.graph.DexClasspathClass;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodResolutionResult.FailedResolutionResult;
 import com.android.tools.r8.graph.ProgramMethod;
 
 public interface InterfaceProcessingDesugaringEventConsumer {
@@ -18,7 +19,8 @@
   void acceptEmulatedInterfaceMarkerInterface(
       DexProgramClass clazz, DexClasspathClass newInterface);
 
-  void acceptThrowingMethod(ProgramMethod method, DexType errorType);
+  void acceptThrowingMethod(
+      ProgramMethod method, DexType errorType, FailedResolutionResult resolutionResult);
 
   void warnMissingInterface(
       DexProgramClass context, DexType missing, InterfaceDesugaringSyntheticHelper helper);
diff --git a/src/main/java/com/android/tools/r8/profile/art/ArtProfileOptions.java b/src/main/java/com/android/tools/r8/profile/art/ArtProfileOptions.java
index 534f5d9..0e2a3f4 100644
--- a/src/main/java/com/android/tools/r8/profile/art/ArtProfileOptions.java
+++ b/src/main/java/com/android/tools/r8/profile/art/ArtProfileOptions.java
@@ -28,7 +28,10 @@
   }
 
   public boolean isCompletenessCheckForTestingEnabled() {
-    return enableCompletenessCheckForTesting && !options.isDesugaredLibraryCompilation();
+    return enableCompletenessCheckForTesting
+        && !options.isDesugaredLibraryCompilation()
+        && !options.getStartupOptions().isStartupCompletenessCheckForTestingEnabled()
+        && !options.getStartupInstrumentationOptions().isStartupInstrumentationEnabled();
   }
 
   public boolean isIncludingApiReferenceStubs() {
@@ -38,11 +41,29 @@
     return enableCompletenessCheckForTesting;
   }
 
+  public boolean isIncludingBackportedClasses() {
+    // Similar to isIncludingVarHandleClasses().
+    return enableCompletenessCheckForTesting;
+  }
+
   public boolean isIncludingConstantDynamicClass() {
     // Similar to isIncludingVarHandleClasses().
     return enableCompletenessCheckForTesting;
   }
 
+  public boolean isIncludingDesugaredLibraryRetargeterForwardingMethodsUnconditionally() {
+    // TODO(b/265729283): If we get as input the profile for the desugared library, maybe we can
+    //  tell if the method targeted by the forwarding method is in the profile, e.g.:
+    //  java.time.Instant java.util.DesugarDate.toInstant(java.util.Date).
+    return enableCompletenessCheckForTesting;
+  }
+
+  public boolean isIncludingThrowingMethods() {
+    // The throw methods we insert should generally be dead a runtime, so no need for them to be
+    // optimized.
+    return enableCompletenessCheckForTesting;
+  }
+
   public boolean isIncludingVarHandleClasses() {
     // We only include var handle classes in the residual ART profiles for completeness testing,
     // since the classes synthesized by var handle desugaring are fairly large and may not be that
diff --git a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileAdditions.java b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileAdditions.java
index b1e72d9..f4400c7 100644
--- a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileAdditions.java
+++ b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileAdditions.java
@@ -4,7 +4,6 @@
 
 package com.android.tools.r8.profile.art.rewriting;
 
-import static com.android.tools.r8.utils.ConsumerUtils.emptyConsumer;
 import static com.android.tools.r8.utils.MapUtils.ignoreKey;
 
 import com.android.tools.r8.graph.DexClass;
@@ -123,7 +122,10 @@
 
             @Override
             public ArtProfileAdditionsBuilder addMethodRule(DexMethod method) {
-              ArtProfileAdditions.this.addMethodRuleFromContext(method, emptyConsumer());
+              ArtProfileMethodRule.Builder contextRuleBuilder = methodRuleAdditions.get(context);
+              ArtProfileAdditions.this.addMethodRuleFromContext(
+                  method,
+                  methodRuleInfoBuilder -> methodRuleInfoBuilder.joinFlags(contextRuleBuilder));
               nestedMethodRuleAdditionsGraph.recordMethodRuleInfoFlagsLargerThan(method, context);
               return this;
             }
@@ -199,7 +201,20 @@
     artProfile.forEachRule(
         artProfileBuilder::addRule,
         methodRule -> {
-          if (!methodRuleRemovals.contains(methodRule.getMethod())) {
+          if (methodRuleRemovals.contains(methodRule.getMethod())) {
+            return;
+          }
+          ArtProfileMethodRule.Builder methodRuleBuilder =
+              methodRuleAdditions.remove(methodRule.getReference());
+          if (methodRuleBuilder != null) {
+            ArtProfileMethodRule newMethodRule =
+                methodRuleBuilder
+                    .acceptMethodRuleInfoBuilder(
+                        methodRuleInfoBuilder ->
+                            methodRuleInfoBuilder.joinFlags(methodRule.getMethodRuleInfo()))
+                    .build();
+            artProfileBuilder.addRule(newMethodRule);
+          } else {
             artProfileBuilder.addRule(methodRule);
           }
         });
diff --git a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileCollectionAdditions.java b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileCollectionAdditions.java
index 49d99c4..5198d05 100644
--- a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileCollectionAdditions.java
+++ b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileCollectionAdditions.java
@@ -55,4 +55,6 @@
 
   public abstract ArtProfileCollectionAdditions setArtProfileCollection(
       ArtProfileCollection artProfileCollection);
+
+  public abstract boolean verifyIsCommitted();
 }
diff --git a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingCfClassSynthesizerDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingCfClassSynthesizerDesugaringEventConsumer.java
index fc09831..ebc4799 100644
--- a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingCfClassSynthesizerDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingCfClassSynthesizerDesugaringEventConsumer.java
@@ -50,8 +50,9 @@
   }
 
   @Override
-  public void acceptCollectionConversion(ProgramMethod arrayConversion) {
-    parent.acceptCollectionConversion(arrayConversion);
+  public void acceptCollectionConversion(ProgramMethod arrayConversion, ProgramMethod context) {
+    additionsCollection.addMethodAndHolderIfContextIsInProfile(arrayConversion, context);
+    parent.acceptCollectionConversion(arrayConversion, context);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingCfInstructionDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingCfInstructionDesugaringEventConsumer.java
index 0f40e39..3ac8a23 100644
--- a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingCfInstructionDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingCfInstructionDesugaringEventConsumer.java
@@ -55,12 +55,21 @@
   }
 
   @Override
-  public void acceptAPIConversion(ProgramMethod method) {
-    parent.acceptAPIConversion(method);
+  public void acceptAPIConversionOutline(ProgramMethod method, ProgramMethod context) {
+    additionsCollection.addMethodAndHolderIfContextIsInProfile(method, context);
+    parent.acceptAPIConversionOutline(method, context);
   }
 
   @Override
   public void acceptBackportedClass(DexProgramClass backportedClass, ProgramMethod context) {
+    if (appView.options().getArtProfileOptions().isIncludingBackportedClasses()) {
+      additionsCollection.applyIfContextIsInProfile(
+          context,
+          additionsBuilder -> {
+            additionsBuilder.addRule(backportedClass);
+            backportedClass.forEachProgramMethod(additionsBuilder::addRule);
+          });
+    }
     parent.acceptBackportedClass(backportedClass, context);
   }
 
@@ -76,8 +85,9 @@
   }
 
   @Override
-  public void acceptCollectionConversion(ProgramMethod arrayConversion) {
-    parent.acceptCollectionConversion(arrayConversion);
+  public void acceptCollectionConversion(ProgramMethod arrayConversion, ProgramMethod context) {
+    additionsCollection.addMethodAndHolderIfContextIsInProfile(arrayConversion, context);
+    parent.acceptCollectionConversion(arrayConversion, context);
   }
 
   @Override
@@ -113,13 +123,19 @@
   }
 
   @Override
-  public void acceptCovariantRetargetMethod(ProgramMethod method) {
-    parent.acceptCovariantRetargetMethod(method);
+  public void acceptCovariantRetargetMethod(ProgramMethod method, ProgramMethod context) {
+    additionsCollection.addMethodAndHolderIfContextIsInProfile(method, context);
+    parent.acceptCovariantRetargetMethod(method, context);
   }
 
   @Override
   public void acceptDefaultAsCompanionMethod(ProgramMethod method, ProgramMethod companionMethod) {
-    additionsCollection.addMethodAndHolderIfContextIsInProfile(companionMethod, method);
+    additionsCollection.applyIfContextIsInProfile(
+        method,
+        additionsBuilder -> {
+          additionsBuilder.addRule(companionMethod).addRule(companionMethod.getHolder());
+          companionMethod.getHolder().acceptProgramClassInitializer(additionsBuilder::addRule);
+        });
     parent.acceptDefaultAsCompanionMethod(method, companionMethod);
   }
 
@@ -148,6 +164,7 @@
   @Override
   public void acceptInvokeStaticInterfaceOutliningMethod(
       ProgramMethod method, ProgramMethod context) {
+    additionsCollection.addMethodAndHolderIfContextIsInProfile(method, context);
     parent.acceptInvokeStaticInterfaceOutliningMethod(method, context);
   }
 
@@ -169,6 +186,9 @@
             additionsBuilder.addRule(lambdaProgramClass.getProgramClassInitializer());
           }
           lambdaProgramClass.forEachProgramInstanceInitializer(additionsBuilder::addRule);
+          if (appView.options().testing.alwaysGenerateLambdaFactoryMethods) {
+            lambdaProgramClass.forEachProgramStaticMethod(additionsBuilder::addRule);
+          }
         });
   }
 
@@ -216,7 +236,7 @@
               .appInfoWithClassHierarchy()
               .resolveMethod(target.getImplementationMethod(), target.isInterface())
               .getResolutionPair();
-      if (resolutionResult == null || resolutionResult.isProgramMethod()) {
+      if (resolutionResult != null && resolutionResult.isProgramMethod()) {
         // Direct call to other method in the app. Only add virtual methods if the callee is in the
         // profile.
         return false;
@@ -272,11 +292,13 @@
   public void acceptPrivateAsCompanionMethod(ProgramMethod method, ProgramMethod companionMethod) {
     additionsCollection.applyIfContextIsInProfile(
         method,
-        additionsBuilder ->
-            additionsBuilder
-                .addRule(companionMethod)
-                .addRule(companionMethod.getHolder())
-                .removeMovedMethodRule(method, companionMethod));
+        additionsBuilder -> {
+          additionsBuilder
+              .addRule(companionMethod)
+              .addRule(companionMethod.getHolder())
+              .removeMovedMethodRule(method, companionMethod);
+          companionMethod.getHolder().acceptProgramClassInitializer(additionsBuilder::addRule);
+        });
     parent.acceptPrivateAsCompanionMethod(method, companionMethod);
   }
 
@@ -319,11 +341,13 @@
   public void acceptStaticAsCompanionMethod(ProgramMethod method, ProgramMethod companionMethod) {
     additionsCollection.applyIfContextIsInProfile(
         method,
-        additionsBuilder ->
-            additionsBuilder
-                .addRule(companionMethod)
-                .addRule(companionMethod.getHolder())
-                .removeMovedMethodRule(method, companionMethod));
+        additionsBuilder -> {
+          additionsBuilder
+              .addRule(companionMethod)
+              .addRule(companionMethod.getHolder())
+              .removeMovedMethodRule(method, companionMethod);
+          companionMethod.getHolder().acceptProgramClassInitializer(additionsBuilder::addRule);
+        });
     parent.acceptStaticAsCompanionMethod(method, companionMethod);
   }
 
diff --git a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingCfPostProcessingDesugaringEventConsumer.java b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingCfPostProcessingDesugaringEventConsumer.java
index a317c8d..568efcc 100644
--- a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingCfPostProcessingDesugaringEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingCfPostProcessingDesugaringEventConsumer.java
@@ -6,15 +6,20 @@
 
 import static com.android.tools.r8.utils.ConsumerUtils.emptyConsumer;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexClassAndMethod;
 import com.android.tools.r8.graph.DexClasspathClass;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodResolutionResult.FailedResolutionResult;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.desugar.CfPostProcessingDesugaringEventConsumer;
+import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
 import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper;
+import com.android.tools.r8.profile.art.ArtProfileOptions;
+import com.android.tools.r8.utils.BooleanBox;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 
@@ -22,23 +27,29 @@
     extends CfPostProcessingDesugaringEventConsumer {
 
   private final ConcreteArtProfileCollectionAdditions additionsCollection;
+  private final ArtProfileOptions options;
   private final CfPostProcessingDesugaringEventConsumer parent;
 
   private ArtProfileRewritingCfPostProcessingDesugaringEventConsumer(
       ConcreteArtProfileCollectionAdditions additionsCollection,
+      ArtProfileOptions options,
       CfPostProcessingDesugaringEventConsumer parent) {
     this.additionsCollection = additionsCollection;
+    this.options = options;
     this.parent = parent;
   }
 
   public static CfPostProcessingDesugaringEventConsumer attach(
+      AppView<?> appView,
       ArtProfileCollectionAdditions artProfileCollectionAdditions,
       CfPostProcessingDesugaringEventConsumer eventConsumer) {
     if (artProfileCollectionAdditions.isNop()) {
       return eventConsumer;
     }
     return new ArtProfileRewritingCfPostProcessingDesugaringEventConsumer(
-        artProfileCollectionAdditions.asConcrete(), eventConsumer);
+        artProfileCollectionAdditions.asConcrete(),
+        appView.options().getArtProfileOptions(),
+        eventConsumer);
   }
 
   @Override
@@ -49,13 +60,15 @@
   }
 
   @Override
-  public void acceptCollectionConversion(ProgramMethod arrayConversion) {
-    parent.acceptCollectionConversion(arrayConversion);
+  public void acceptCollectionConversion(ProgramMethod arrayConversion, ProgramMethod context) {
+    additionsCollection.addMethodAndHolderIfContextIsInProfile(arrayConversion, context);
+    parent.acceptCollectionConversion(arrayConversion, context);
   }
 
   @Override
-  public void acceptCovariantRetargetMethod(ProgramMethod method) {
-    parent.acceptCovariantRetargetMethod(method);
+  public void acceptCovariantRetargetMethod(ProgramMethod method, ProgramMethod context) {
+    additionsCollection.addMethodAndHolderIfContextIsInProfile(context, method);
+    parent.acceptCovariantRetargetMethod(method, context);
   }
 
   @Override
@@ -64,8 +77,12 @@
   }
 
   @Override
-  public void acceptDesugaredLibraryRetargeterForwardingMethod(ProgramMethod method) {
-    parent.acceptDesugaredLibraryRetargeterForwardingMethod(method);
+  public void acceptDesugaredLibraryRetargeterForwardingMethod(
+      ProgramMethod method, EmulatedDispatchMethodDescriptor descriptor) {
+    if (options.isIncludingDesugaredLibraryRetargeterForwardingMethodsUnconditionally()) {
+      additionsCollection.apply(additions -> additions.addMethodRule(method, emptyConsumer()));
+    }
+    parent.acceptDesugaredLibraryRetargeterForwardingMethod(method, descriptor);
   }
 
   @Override
@@ -97,8 +114,24 @@
   }
 
   @Override
-  public void acceptThrowingMethod(ProgramMethod method, DexType errorType) {
-    parent.acceptThrowingMethod(method, errorType);
+  public void acceptThrowingMethod(
+      ProgramMethod method, DexType errorType, FailedResolutionResult resolutionResult) {
+    if (options.isIncludingThrowingMethods()) {
+      BooleanBox seenMethodCausingError = new BooleanBox();
+      resolutionResult.forEachFailureDependency(
+          emptyConsumer(),
+          methodCausingError -> {
+            additionsCollection.applyIfContextIsInProfile(
+                methodCausingError.getReference(),
+                additionsBuilder -> additionsBuilder.addRule(method));
+            seenMethodCausingError.set();
+          });
+      if (seenMethodCausingError.isFalse()) {
+        additionsCollection.applyIfContextIsInProfile(
+            method.getHolder(), additions -> additions.addMethodRule(method, emptyConsumer()));
+      }
+    }
+    parent.acceptThrowingMethod(method, errorType, resolutionResult);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingMethodProcessorEventConsumer.java b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingMethodProcessorEventConsumer.java
index 8363e62..dea3841 100644
--- a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingMethodProcessorEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingMethodProcessorEventConsumer.java
@@ -51,7 +51,7 @@
   @Override
   public void acceptEnumUnboxerCheckNotZeroContext(ProgramMethod method, ProgramMethod context) {
     additionsCollection.applyIfContextIsInProfile(
-        context, additionsBuilder -> additionsBuilder.addRule(method));
+        context, additionsBuilder -> additionsBuilder.addRule(method).addRule(method.getHolder()));
     parent.acceptEnumUnboxerCheckNotZeroContext(method, context);
   }
 
diff --git a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingRootSetBuilderEventConsumer.java b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingRootSetBuilderEventConsumer.java
index 9a61ea9..005c33c 100644
--- a/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingRootSetBuilderEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/profile/art/rewriting/ArtProfileRewritingRootSetBuilderEventConsumer.java
@@ -4,11 +4,8 @@
 
 package com.android.tools.r8.profile.art.rewriting;
 
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
-import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.shaking.RootSetBuilderEventConsumer;
-import com.android.tools.r8.shaking.RootSetUtils.RootSet;
 
 public class ArtProfileRewritingRootSetBuilderEventConsumer implements RootSetBuilderEventConsumer {
 
@@ -23,10 +20,8 @@
   }
 
   public static RootSetBuilderEventConsumer attach(
-      AppView<? extends AppInfoWithClassHierarchy> appView,
+      ArtProfileCollectionAdditions additionsCollection,
       RootSetBuilderEventConsumer eventConsumer) {
-    ArtProfileCollectionAdditions additionsCollection =
-        ArtProfileCollectionAdditions.create(appView);
     if (additionsCollection.isNop()) {
       return eventConsumer;
     }
@@ -68,9 +63,4 @@
                 .removeMovedMethodRule(method, companionMethod));
     parent.acceptStaticAsCompanionMethod(method, companionMethod);
   }
-
-  @Override
-  public void finished(AppView<? extends AppInfoWithClassHierarchy> appView, RootSet rootSet) {
-    additionsCollection.commit(appView);
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/profile/art/rewriting/ConcreteArtProfileCollectionAdditions.java b/src/main/java/com/android/tools/r8/profile/art/rewriting/ConcreteArtProfileCollectionAdditions.java
index 4cfd694..1d1a897 100644
--- a/src/main/java/com/android/tools/r8/profile/art/rewriting/ConcreteArtProfileCollectionAdditions.java
+++ b/src/main/java/com/android/tools/r8/profile/art/rewriting/ConcreteArtProfileCollectionAdditions.java
@@ -155,4 +155,10 @@
     }
     return this;
   }
+
+  @Override
+  public boolean verifyIsCommitted() {
+    assert committed;
+    return true;
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/profile/art/rewriting/NopArtProfileCollectionAdditions.java b/src/main/java/com/android/tools/r8/profile/art/rewriting/NopArtProfileCollectionAdditions.java
index fe61aaa..8bfd4a6 100644
--- a/src/main/java/com/android/tools/r8/profile/art/rewriting/NopArtProfileCollectionAdditions.java
+++ b/src/main/java/com/android/tools/r8/profile/art/rewriting/NopArtProfileCollectionAdditions.java
@@ -57,4 +57,10 @@
     // Intentionally empty.
     return this;
   }
+
+  @Override
+  public boolean verifyIsCommitted() {
+    // Nothing to commit.
+    return true;
+  }
 }
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 13e0528..15781741 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -473,6 +473,7 @@
 
   Enqueuer(
       AppView<? extends AppInfoWithClassHierarchy> appView,
+      ArtProfileCollectionAdditions artProfileCollectionAdditions,
       ExecutorService executorService,
       SubtypingInfo subtypingInfo,
       GraphConsumer keptGraphConsumer,
@@ -481,7 +482,7 @@
     InternalOptions options = appView.options();
     this.appInfo = appView.appInfo();
     this.appView = appView.withClassHierarchy();
-    this.artProfileCollectionAdditions = ArtProfileCollectionAdditions.create(appView);
+    this.artProfileCollectionAdditions = artProfileCollectionAdditions;
     this.deferredTracing = EnqueuerDeferredTracing.create(appView, this, mode);
     this.executorService = executorService;
     this.subtypingInfo = subtypingInfo;
@@ -531,6 +532,10 @@
     return appView.appInfo();
   }
 
+  public ArtProfileCollectionAdditions getArtProfileCollectionAdditions() {
+    return artProfileCollectionAdditions;
+  }
+
   public Mode getMode() {
     return mode;
   }
@@ -4475,7 +4480,7 @@
             }
           }
           ConsequentRootSetBuilder consequentSetBuilder =
-              ConsequentRootSet.builder(appView, subtypingInfo, this);
+              ConsequentRootSet.builder(appView, this, subtypingInfo);
           IfRuleEvaluator ifRuleEvaluator =
               new IfRuleEvaluator(
                   appView,
@@ -4569,6 +4574,7 @@
 
     CfPostProcessingDesugaringEventConsumer eventConsumer =
         CfPostProcessingDesugaringEventConsumer.createForR8(
+            appView,
             syntheticAdditions,
             artProfileCollectionAdditions,
             desugaring,
@@ -4635,7 +4641,7 @@
   }
 
   private ConsequentRootSet computeDelayedInterfaceMethodSyntheticBridges() {
-    RootSetBuilder builder = RootSet.builder(appView, subtypingInfo);
+    RootSetBuilder builder = RootSet.builder(appView, this, subtypingInfo);
     for (DelayedRootSetActionItem delayedRootSetActionItem : rootSet.delayedRootSetActionItems) {
       if (delayedRootSetActionItem.isInterfaceMethodSyntheticBridgeAction()) {
         handleInterfaceMethodSyntheticBridgeAction(
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerFactory.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerFactory.java
index cfce371..e1d0124 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerFactory.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerFactory.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.SubtypingInfo;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
 import com.android.tools.r8.shaking.Enqueuer.Mode;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
@@ -17,9 +18,16 @@
 
   public static Enqueuer createForInitialTreeShaking(
       AppView<? extends AppInfoWithClassHierarchy> appView,
+      ArtProfileCollectionAdditions artProfileCollectionAdditions,
       ExecutorService executorService,
       SubtypingInfo subtypingInfo) {
-    return new Enqueuer(appView, executorService, subtypingInfo, null, Mode.INITIAL_TREE_SHAKING);
+    return new Enqueuer(
+        appView,
+        artProfileCollectionAdditions,
+        executorService,
+        subtypingInfo,
+        null,
+        Mode.INITIAL_TREE_SHAKING);
   }
 
   public static Enqueuer createForFinalTreeShaking(
@@ -28,9 +36,16 @@
       SubtypingInfo subtypingInfo,
       GraphConsumer keptGraphConsumer,
       Set<DexType> initialPrunedTypes) {
+    ArtProfileCollectionAdditions artProfileCollectionAdditions =
+        ArtProfileCollectionAdditions.create(appView);
     Enqueuer enqueuer =
         new Enqueuer(
-            appView, executorService, subtypingInfo, keptGraphConsumer, Mode.FINAL_TREE_SHAKING);
+            appView,
+            artProfileCollectionAdditions,
+            executorService,
+            subtypingInfo,
+            keptGraphConsumer,
+            Mode.FINAL_TREE_SHAKING);
     appView.withProtoShrinker(
         shrinker -> enqueuer.setInitialDeadProtoTypes(shrinker.getDeadProtoTypes()));
     enqueuer.setInitialPrunedTypes(initialPrunedTypes);
@@ -41,8 +56,15 @@
       AppView<? extends AppInfoWithClassHierarchy> appView,
       ExecutorService executorService,
       SubtypingInfo subtypingInfo) {
+    ArtProfileCollectionAdditions artProfileCollectionAdditions =
+        ArtProfileCollectionAdditions.create(appView);
     return new Enqueuer(
-        appView, executorService, subtypingInfo, null, Mode.INITIAL_MAIN_DEX_TRACING);
+        appView,
+        artProfileCollectionAdditions,
+        executorService,
+        subtypingInfo,
+        null,
+        Mode.INITIAL_MAIN_DEX_TRACING);
   }
 
   public static Enqueuer createForFinalMainDexTracing(
@@ -50,8 +72,15 @@
       ExecutorService executorService,
       SubtypingInfo subtypingInfo,
       GraphConsumer keptGraphConsumer) {
+    ArtProfileCollectionAdditions artProfileCollectionAdditions =
+        ArtProfileCollectionAdditions.create(appView);
     return new Enqueuer(
-        appView, executorService, subtypingInfo, keptGraphConsumer, Mode.FINAL_MAIN_DEX_TRACING);
+        appView,
+        artProfileCollectionAdditions,
+        executorService,
+        subtypingInfo,
+        keptGraphConsumer,
+        Mode.FINAL_MAIN_DEX_TRACING);
   }
 
   public static Enqueuer createForGenerateMainDexList(
@@ -59,8 +88,15 @@
       ExecutorService executorService,
       SubtypingInfo subtypingInfo,
       GraphConsumer keptGraphConsumer) {
+    ArtProfileCollectionAdditions artProfileCollectionAdditions =
+        ArtProfileCollectionAdditions.create(appView);
     return new Enqueuer(
-        appView, executorService, subtypingInfo, keptGraphConsumer, Mode.GENERATE_MAIN_DEX_LIST);
+        appView,
+        artProfileCollectionAdditions,
+        executorService,
+        subtypingInfo,
+        keptGraphConsumer,
+        Mode.GENERATE_MAIN_DEX_LIST);
   }
 
   public static Enqueuer createForWhyAreYouKeeping(
@@ -68,7 +104,14 @@
       ExecutorService executorService,
       SubtypingInfo subtypingInfo,
       GraphConsumer keptGraphConsumer) {
+    ArtProfileCollectionAdditions artProfileCollectionAdditions =
+        ArtProfileCollectionAdditions.create(appView);
     return new Enqueuer(
-        appView, executorService, subtypingInfo, keptGraphConsumer, Mode.WHY_ARE_YOU_KEEPING);
+        appView,
+        artProfileCollectionAdditions,
+        executorService,
+        subtypingInfo,
+        keptGraphConsumer,
+        Mode.WHY_ARE_YOU_KEEPING);
   }
 }
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilderEventConsumer.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilderEventConsumer.java
index b49a15d..9378b76 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilderEventConsumer.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilderEventConsumer.java
@@ -4,25 +4,23 @@
 
 package com.android.tools.r8.shaking;
 
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
-import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.desugar.itf.InterfaceMethodDesugaringBaseEventConsumer;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
 import com.android.tools.r8.profile.art.rewriting.ArtProfileRewritingRootSetBuilderEventConsumer;
-import com.android.tools.r8.shaking.RootSetUtils.RootSet;
 
 public interface RootSetBuilderEventConsumer extends InterfaceMethodDesugaringBaseEventConsumer {
 
-  static RootSetBuilderEventConsumer create(AppView<? extends AppInfoWithClassHierarchy> appView) {
-    return ArtProfileRewritingRootSetBuilderEventConsumer.attach(appView, empty());
+  static RootSetBuilderEventConsumer create(
+      ArtProfileCollectionAdditions artProfileCollectionAdditions) {
+    return ArtProfileRewritingRootSetBuilderEventConsumer.attach(
+        artProfileCollectionAdditions, empty());
   }
 
   static EmptyRootSetBuilderEventConsumer empty() {
     return EmptyRootSetBuilderEventConsumer.getInstance();
   }
 
-  default void finished(AppView<? extends AppInfoWithClassHierarchy> appView, RootSet rootSet) {}
-
   class EmptyRootSetBuilderEventConsumer implements RootSetBuilderEventConsumer {
 
     private static final EmptyRootSetBuilderEventConsumer INSTANCE =
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
index bda1564..b5810f2 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -53,6 +53,7 @@
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
 import com.android.tools.r8.ir.optimize.membervaluepropagation.assume.AssumeInfo;
 import com.android.tools.r8.logging.Log;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
 import com.android.tools.r8.repackaging.RepackagingUtils;
 import com.android.tools.r8.shaking.AnnotationMatchResult.AnnotationsIgnoredMatchResult;
 import com.android.tools.r8.shaking.AnnotationMatchResult.ConcreteAnnotationMatchResult;
@@ -156,10 +157,11 @@
 
     private RootSetBuilder(
         AppView<? extends AppInfoWithClassHierarchy> appView,
+        RootSetBuilderEventConsumer eventConsumer,
         SubtypingInfo subtypingInfo,
         Iterable<? extends ProguardConfigurationRule> rules) {
       this.appView = appView;
-      this.eventConsumer = RootSetBuilderEventConsumer.create(appView);
+      this.eventConsumer = eventConsumer;
       this.subtypingInfo = subtypingInfo;
       this.application = appView.appInfo().app().asDirect();
       this.rules = rules;
@@ -171,8 +173,14 @@
     }
 
     private RootSetBuilder(
-        AppView<? extends AppInfoWithClassHierarchy> appView, SubtypingInfo subtypingInfo) {
-      this(appView, subtypingInfo, null);
+        AppView<? extends AppInfoWithClassHierarchy> appView,
+        Enqueuer enqueuer,
+        SubtypingInfo subtypingInfo) {
+      this(
+          appView,
+          RootSetBuilderEventConsumer.create(enqueuer.getArtProfileCollectionAdditions()),
+          subtypingInfo,
+          null);
     }
 
     boolean isMainDexRootSetBuilder() {
@@ -386,30 +394,27 @@
             alwaysInline,
             bypassClinitforInlining);
       }
-      RootSet rootSet =
-          new RootSet(
-              dependentMinimumKeepInfo,
-              ImmutableList.copyOf(reasonAsked.values()),
-              alwaysInline,
-              neverInlineDueToSingleCaller,
-              bypassClinitforInlining,
-              whyAreYouNotInlining,
-              reprocess,
-              neverReprocess,
-              alwaysClassInline,
-              neverClassInline,
-              noUnusedInterfaceRemoval,
-              noVerticalClassMerging,
-              noHorizontalClassMerging,
-              neverPropagateValue,
-              mayHaveSideEffects,
-              dependentKeepClassCompatRule,
-              identifierNameStrings,
-              ifRules,
-              Lists.newArrayList(delayedRootSetActionItems),
-              pendingMethodMoveInverse);
-      eventConsumer.finished(appView, rootSet);
-      return rootSet;
+      return new RootSet(
+          dependentMinimumKeepInfo,
+          ImmutableList.copyOf(reasonAsked.values()),
+          alwaysInline,
+          neverInlineDueToSingleCaller,
+          bypassClinitforInlining,
+          whyAreYouNotInlining,
+          reprocess,
+          neverReprocess,
+          alwaysClassInline,
+          neverClassInline,
+          noUnusedInterfaceRemoval,
+          noVerticalClassMerging,
+          noHorizontalClassMerging,
+          neverPropagateValue,
+          mayHaveSideEffects,
+          dependentKeepClassCompatRule,
+          identifierNameStrings,
+          ifRules,
+          Lists.newArrayList(delayedRootSetActionItems),
+          pendingMethodMoveInverse);
     }
 
     private void propagateAssumeRules(DexClass clazz) {
@@ -2158,15 +2163,22 @@
     }
 
     public static RootSetBuilder builder(
-        AppView<? extends AppInfoWithClassHierarchy> appView, SubtypingInfo subtypingInfo) {
-      return new RootSetBuilder(appView, subtypingInfo);
+        AppView<? extends AppInfoWithClassHierarchy> appView,
+        Enqueuer enqueuer,
+        SubtypingInfo subtypingInfo) {
+      return new RootSetBuilder(appView, enqueuer, subtypingInfo);
     }
 
     public static RootSetBuilder builder(
         AppView<? extends AppInfoWithClassHierarchy> appView,
+        ArtProfileCollectionAdditions artProfileCollectionAdditions,
         SubtypingInfo subtypingInfo,
         Iterable<? extends ProguardConfigurationRule> rules) {
-      return new RootSetBuilder(appView, subtypingInfo, rules);
+      return new RootSetBuilder(
+          appView,
+          RootSetBuilderEventConsumer.create(artProfileCollectionAdditions),
+          subtypingInfo,
+          rules);
     }
   }
 
@@ -2176,9 +2188,13 @@
 
     private ConsequentRootSetBuilder(
         AppView<? extends AppInfoWithClassHierarchy> appView,
-        SubtypingInfo subtypingInfo,
-        Enqueuer enqueuer) {
-      super(appView, subtypingInfo, null);
+        Enqueuer enqueuer,
+        SubtypingInfo subtypingInfo) {
+      super(
+          appView,
+          RootSetBuilderEventConsumer.create(enqueuer.getArtProfileCollectionAdditions()),
+          subtypingInfo,
+          null);
       this.enqueuer = enqueuer;
     }
 
@@ -2214,9 +2230,9 @@
 
     static ConsequentRootSetBuilder builder(
         AppView<? extends AppInfoWithClassHierarchy> appView,
-        SubtypingInfo subtypingInfo,
-        Enqueuer enqueuer) {
-      return new ConsequentRootSetBuilder(appView, subtypingInfo, enqueuer);
+        Enqueuer enqueuer,
+        SubtypingInfo subtypingInfo) {
+      return new ConsequentRootSetBuilder(appView, enqueuer, subtypingInfo);
     }
   }
 
@@ -2224,9 +2240,14 @@
 
     private MainDexRootSetBuilder(
         AppView<? extends AppInfoWithClassHierarchy> appView,
+        ArtProfileCollectionAdditions artProfileCollectionAdditions,
         SubtypingInfo subtypingInfo,
         Iterable<? extends ProguardConfigurationRule> rules) {
-      super(appView, subtypingInfo, rules);
+      super(
+          appView,
+          RootSetBuilderEventConsumer.create(artProfileCollectionAdditions),
+          subtypingInfo,
+          rules);
     }
 
     @Override
@@ -2278,9 +2299,11 @@
 
     public static MainDexRootSetBuilder builder(
         AppView<? extends AppInfoWithClassHierarchy> appView,
+        ArtProfileCollectionAdditions artProfileCollectionAdditions,
         SubtypingInfo subtypingInfo,
         Iterable<? extends ProguardConfigurationRule> rules) {
-      return new MainDexRootSetBuilder(appView, subtypingInfo, rules);
+      return new MainDexRootSetBuilder(
+          appView, artProfileCollectionAdditions, subtypingInfo, rules);
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index 8214303..8cf1e77 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -197,15 +197,7 @@
     appView.setAppInfo(appView.appInfo().rebuildWithClassHierarchy(result.commit));
     appView.setAppInfo(appView.appInfo().rebuildWithMainDexInfo(result.mainDexInfo));
     if (result.lens != null) {
-      appView.setGraphLens(result.lens);
-      appView.setAppInfo(
-          appView
-              .appInfo()
-              .rebuildWithMainDexInfo(
-                  appView
-                      .appInfo()
-                      .getMainDexInfo()
-                      .rewrittenWithLens(appView.getSyntheticItems(), result.lens)));
+      appView.rewriteWithLens(result.lens);
     }
     appView.pruneItems(result.prunedItems, executorService);
   }
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index 74620e9..d4123d3 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -46,6 +46,7 @@
 import com.android.tools.r8.jasmin.JasminBuilder;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.origin.PathOrigin;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
 import com.android.tools.r8.references.ClassReference;
 import com.android.tools.r8.references.FieldReference;
 import com.android.tools.r8.references.MethodReference;
@@ -856,14 +857,20 @@
         computeAppViewWithClassHierarchy(app, keepConfig, optionsConsumer);
     // Run the tree shaker to compute an instance of AppInfoWithLiveness.
     ExecutorService executor = Executors.newSingleThreadExecutor();
+    ArtProfileCollectionAdditions artProfileCollectionAdditions =
+        ArtProfileCollectionAdditions.nop();
     SubtypingInfo subtypingInfo = SubtypingInfo.create(appView);
     RootSet rootSet =
         RootSet.builder(
-                appView, subtypingInfo, appView.options().getProguardConfiguration().getRules())
+                appView,
+                artProfileCollectionAdditions,
+                subtypingInfo,
+                appView.options().getProguardConfiguration().getRules())
             .build(executor);
     appView.setRootSet(rootSet);
     EnqueuerResult enqueuerResult =
-        EnqueuerFactory.createForInitialTreeShaking(appView, executor, subtypingInfo)
+        EnqueuerFactory.createForInitialTreeShaking(
+                appView, artProfileCollectionAdditions, executor, subtypingInfo)
             .traceApplication(rootSet, executor, Timing.empty());
     executor.shutdown();
     // We do not run the tree pruner to ensure that the hierarchy is as designed and not modified
diff --git a/src/test/java/com/android/tools/r8/ir/InlineTest.java b/src/test/java/com/android/tools/r8/ir/InlineTest.java
index be71b20..037bb82 100644
--- a/src/test/java/com/android/tools/r8/ir/InlineTest.java
+++ b/src/test/java/com/android/tools/r8/ir/InlineTest.java
@@ -23,6 +23,7 @@
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.InstructionListIterator;
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.profile.art.rewriting.ArtProfileCollectionAdditions;
 import com.android.tools.r8.shaking.Enqueuer;
 import com.android.tools.r8.shaking.EnqueuerFactory;
 import com.android.tools.r8.shaking.EnqueuerResult;
@@ -73,17 +74,21 @@
       throws ExecutionException {
     AppView<AppInfoWithClassHierarchy> appView = AppView.createForR8(application.asDirect());
     appView.setAppServices(AppServices.builder(appView).build());
+    ArtProfileCollectionAdditions artProfileCollectionAdditions =
+        ArtProfileCollectionAdditions.nop();
     ExecutorService executorService = ThreadUtils.getExecutorService(options);
     SubtypingInfo subtypingInfo = SubtypingInfo.create(appView);
     appView.setRootSet(
         RootSet.builder(
                 appView,
+                artProfileCollectionAdditions,
                 subtypingInfo,
                 ImmutableList.of(ProguardKeepRule.defaultKeepAllRule(unused -> {})))
             .build(executorService));
     Timing timing = Timing.empty();
     Enqueuer enqueuer =
-        EnqueuerFactory.createForInitialTreeShaking(appView, executorService, subtypingInfo);
+        EnqueuerFactory.createForInitialTreeShaking(
+            appView, artProfileCollectionAdditions, executorService, subtypingInfo);
     EnqueuerResult enqueuerResult =
         enqueuer.traceApplication(appView.rootSet(), executorService, timing);
     appView.setAppInfo(enqueuerResult.getAppInfo());
diff --git a/src/test/java/com/android/tools/r8/profile/art/completeness/MovedStaticInterfaceMethodProfileRewritingTest.java b/src/test/java/com/android/tools/r8/profile/art/completeness/MovedStaticInterfaceMethodProfileRewritingTest.java
index 6e7ab5b..009966f 100644
--- a/src/test/java/com/android/tools/r8/profile/art/completeness/MovedStaticInterfaceMethodProfileRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/profile/art/completeness/MovedStaticInterfaceMethodProfileRewritingTest.java
@@ -4,6 +4,8 @@
 
 package com.android.tools.r8.profile.art.completeness;
 
+import static com.android.tools.r8.synthesis.SyntheticItemsTestUtils.syntheticCompanionClass;
+import static com.android.tools.r8.synthesis.SyntheticItemsTestUtils.syntheticStaticInterfaceMethodAsCompanionMethod;
 import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
 import static org.hamcrest.MatcherAssert.assertThat;
 
@@ -14,7 +16,6 @@
 import com.android.tools.r8.profile.art.model.ExternalArtProfile;
 import com.android.tools.r8.profile.art.utils.ArtProfileInspector;
 import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
 import com.android.tools.r8.utils.codeinspector.ClassSubject;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
@@ -48,6 +49,20 @@
   }
 
   @Test
+  public void testD8FromProfileAfterDesugaring() throws Exception {
+    testForD8(parameters.getBackend())
+        .addInnerClasses(getClass())
+        .addArtProfileForRewriting(
+            getArtProfileAfterDesugaring(
+                parameters.canUseDefaultAndStaticInterfaceMethodsWhenDesugaring()))
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspectResidualArtProfile(this::inspectD8)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines("Hello, world!");
+  }
+
+  @Test
   public void testR8() throws Exception {
     parameters.assumeR8TestParameters();
     testForR8(parameters.getBackend())
@@ -62,12 +77,42 @@
         .assertSuccessWithOutputLines("Hello, world!");
   }
 
+  @Test
+  public void testR8FromProfileAfterDesugaring() throws Exception {
+    parameters.assumeR8TestParameters();
+    testForR8(parameters.getBackend())
+        .addInnerClasses(getClass())
+        .addKeepMainRule(Main.class)
+        .addArtProfileForRewriting(
+            getArtProfileAfterDesugaring(
+                parameters.isCfRuntime() || parameters.canUseDefaultAndStaticInterfaceMethods()))
+        .enableInliningAnnotations()
+        .setMinApi(parameters.getApiLevel())
+        .compile()
+        .inspectResidualArtProfile(this::inspectR8)
+        .run(parameters.getRuntime(), Main.class)
+        .assertSuccessWithOutputLines("Hello, world!");
+  }
+
   private ExternalArtProfile getArtProfile() throws Exception {
     return ExternalArtProfile.builder()
         .addMethodRule(Reference.methodFromMethod(I.class.getDeclaredMethod("m")))
         .build();
   }
 
+  private ExternalArtProfile getArtProfileAfterDesugaring(
+      boolean canUseDefaultAndStaticInterfaceMethods) throws Exception {
+    if (canUseDefaultAndStaticInterfaceMethods) {
+      return getArtProfile();
+    } else {
+      return ExternalArtProfile.builder()
+          .addClassRule(syntheticCompanionClass(I.class))
+          .addMethodRule(
+              syntheticStaticInterfaceMethodAsCompanionMethod(I.class.getDeclaredMethod("m")))
+          .build();
+    }
+  }
+
   private void inspectD8(ArtProfileInspector profileInspector, CodeInspector inspector)
       throws Exception {
     inspect(
@@ -100,8 +145,7 @@
           .assertContainsMethodRule(staticInterfaceMethodSubject)
           .assertContainsNoOtherRules();
     } else {
-      ClassSubject companionClassSubject =
-          inspector.clazz(SyntheticItemsTestUtils.syntheticCompanionClass(I.class));
+      ClassSubject companionClassSubject = inspector.clazz(syntheticCompanionClass(I.class));
       assertThat(companionClassSubject, isPresent());
 
       MethodSubject staticInterfaceMethodSubject =
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 478af32..e69bb0f 100644
--- a/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
+++ b/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
@@ -228,6 +228,14 @@
         originalMethod.getMethodDescriptor());
   }
 
+  public static MethodReference syntheticStaticInterfaceMethodAsCompanionMethod(Method method) {
+    MethodReference originalMethod = Reference.methodFromMethod(method);
+    ClassReference companionClassReference =
+        syntheticCompanionClass(originalMethod.getHolderClass());
+    return Reference.methodFromDescriptor(
+        companionClassReference, method.getName(), originalMethod.getMethodDescriptor());
+  }
+
   public static ClassReference syntheticEnumUnboxingLocalUtilityClass(Class<?> clazz) {
     return Reference.classFromTypeName(
         clazz.getTypeName() + naming.ENUM_UNBOXING_LOCAL_UTILITY_CLASS.getDescriptor());