Optimize lines and compute mapping after jumbo string rewriting.

Bug: 207765416
Change-Id: I710cec91af3757d626bece79dc9f94d1cf9f374a
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 58753de..c7240f8 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -28,10 +28,8 @@
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
 import com.android.tools.r8.jar.CfApplicationWriter;
 import com.android.tools.r8.kotlin.KotlinMetadataRewriter;
-import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.naming.PrefixRewritingNamingLens;
-import com.android.tools.r8.naming.ProguardMapSupplier;
 import com.android.tools.r8.naming.RecordRewritingNamingLens;
 import com.android.tools.r8.naming.signature.GenericSignatureRewriter;
 import com.android.tools.r8.origin.CommandLineOrigin;
@@ -44,7 +42,6 @@
 import com.android.tools.r8.utils.ExceptionUtils;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.InternalOptions.DesugarState;
-import com.android.tools.r8.utils.LineNumberOptimizer;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.ThreadUtils;
@@ -269,11 +266,9 @@
       namingLens = RecordRewritingNamingLens.createRecordRewritingNamingLens(appView, namingLens);
 
       if (options.isGeneratingClassFiles()) {
-        ProguardMapSupplier proguardMapSupplier =
-            finalizeApplication(inputApp, appView, executor, namingLens);
-        new CfApplicationWriter(
-                appView, marker, GraphLens.getIdentityLens(), namingLens, proguardMapSupplier)
-            .write(options.getClassFileConsumer());
+        finalizeApplication(inputApp, appView, executor, namingLens);
+        new CfApplicationWriter(appView, marker, GraphLens.getIdentityLens(), namingLens)
+            .write(options.getClassFileConsumer(), inputApp);
       } else {
         if (!hasDexResources || !hasClassResources || !appView.rewritePrefix.isRewriting()) {
           // All inputs are either dex or cf, or there is nothing to rewrite.
@@ -314,17 +309,15 @@
                       executor, appView.appInfo().app(), appView.appInfo().getMainDexInfo());
           appView.setAppInfo(appView.appInfo().rebuildWithMainDexInfo(mainDexInfo));
         }
-        ProguardMapSupplier proguardMapSupplier =
-            finalizeApplication(inputApp, appView, executor, namingLens);
+        finalizeApplication(inputApp, appView, executor, namingLens);
 
         new ApplicationWriter(
                 appView,
                 marker == null ? null : ImmutableList.copyOf(markers),
                 appView.graphLens(),
                 InitClassLens.getThrowingInstance(),
-                namingLens,
-                proguardMapSupplier)
-            .write(executor);
+                namingLens)
+            .write(executor, inputApp);
       }
       options.printWarnings();
     } catch (ExecutionException e) {
@@ -338,19 +331,13 @@
     }
   }
 
-  private static ProguardMapSupplier finalizeApplication(
+  private static void finalizeApplication(
       AndroidApp inputApp,
       AppView<AppInfo> appView,
       ExecutorService executorService,
       NamingLens namingLens)
       throws ExecutionException {
     SyntheticFinalization.finalize(appView, executorService);
-    if (appView.options().proguardMapConsumer == null) {
-      return null;
-    }
-    ClassNameMapper classNameMapper =
-        LineNumberOptimizer.run(appView, appView.appInfo().app(), inputApp, namingLens);
-    return ProguardMapSupplier.create(classNameMapper, appView.options());
   }
 
   private static DexApplication rewriteNonDexInputs(
@@ -395,7 +382,6 @@
             GraphLens.getIdentityLens(),
             InitClassLens.getThrowingInstance(),
             desugaringLens,
-            null,
             convertedCfFiles)
         .write(executor);
     AndroidApp.Builder builder = AndroidApp.builder(inputApp);
diff --git a/src/main/java/com/android/tools/r8/DexFileMergerHelper.java b/src/main/java/com/android/tools/r8/DexFileMergerHelper.java
index f51d700..d8e8e69 100644
--- a/src/main/java/com/android/tools/r8/DexFileMergerHelper.java
+++ b/src/main/java/com/android/tools/r8/DexFileMergerHelper.java
@@ -107,8 +107,7 @@
                 markers,
                 GraphLens.getIdentityLens(),
                 InitClassLens.getThrowingInstance(),
-                NamingLens.getIdentityLens(),
-                null);
+                NamingLens.getIdentityLens());
         writer.write(executor);
         options.printWarnings();
       } catch (ExecutionException e) {
diff --git a/src/main/java/com/android/tools/r8/DexSplitterHelper.java b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
index 875635f..fdcdaf2 100644
--- a/src/main/java/com/android/tools/r8/DexSplitterHelper.java
+++ b/src/main/java/com/android/tools/r8/DexSplitterHelper.java
@@ -115,7 +115,6 @@
                   GraphLens.getIdentityLens(),
                   InitClassLens.getThrowingInstance(),
                   NamingLens.getIdentityLens(),
-                  null,
                   consumer)
               .write(executor);
           options.printWarnings();
diff --git a/src/main/java/com/android/tools/r8/GenerateLintFiles.java b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
index 68b9354..cde20fa 100644
--- a/src/main/java/com/android/tools/r8/GenerateLintFiles.java
+++ b/src/main/java/com/android/tools/r8/GenerateLintFiles.java
@@ -352,8 +352,7 @@
             appView,
             options.getMarker(Tool.L8),
             GraphLens.getIdentityLens(),
-            NamingLens.getIdentityLens(),
-            null);
+            NamingLens.getIdentityLens());
     ClassFileConsumer consumer =
         new ClassFileConsumer.ArchiveConsumer(
             lintFile(compilationApiLevel, minApiLevel, FileUtils.JAR_EXTENSION));
diff --git a/src/main/java/com/android/tools/r8/L8.java b/src/main/java/com/android/tools/r8/L8.java
index b0eec1a..318a055 100644
--- a/src/main/java/com/android/tools/r8/L8.java
+++ b/src/main/java/com/android/tools/r8/L8.java
@@ -141,8 +141,7 @@
       NamingLens namingLens = PrefixRewritingNamingLens.createPrefixRewritingNamingLens(appView);
       new GenericSignatureRewriter(appView, namingLens).run(appView.appInfo().classes(), executor);
 
-      new CfApplicationWriter(
-              appView, options.getMarker(Tool.L8), appView.graphLens(), namingLens, null)
+      new CfApplicationWriter(appView, options.getMarker(Tool.L8), appView.graphLens(), namingLens)
           .write(options.getClassFileConsumer());
       options.printWarnings();
     } catch (ExecutionException e) {
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 722ae3e..cf83f78 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -62,12 +62,10 @@
 import com.android.tools.r8.jar.CfApplicationWriter;
 import com.android.tools.r8.kotlin.KotlinMetadataRewriter;
 import com.android.tools.r8.kotlin.KotlinMetadataUtils;
-import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.naming.Minifier;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.naming.PrefixRewritingNamingLens;
 import com.android.tools.r8.naming.ProguardMapMinifier;
-import com.android.tools.r8.naming.ProguardMapSupplier;
 import com.android.tools.r8.naming.RecordRewritingNamingLens;
 import com.android.tools.r8.naming.signature.GenericSignatureRewriter;
 import com.android.tools.r8.optimize.ClassAndMemberPublicizer;
@@ -109,7 +107,6 @@
 import com.android.tools.r8.utils.CollectionUtils;
 import com.android.tools.r8.utils.ExceptionUtils;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.LineNumberOptimizer;
 import com.android.tools.r8.utils.SelfRetraceTest;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.StringUtils;
@@ -217,7 +214,7 @@
       InitClassLens initClassLens,
       NamingLens namingLens,
       InternalOptions options,
-      ProguardMapSupplier proguardMapSupplier)
+      AndroidApp inputApp)
       throws ExecutionException {
     InspectorImpl.runInspections(options.outputInspections, appView.appInfo().classes());
     try {
@@ -228,8 +225,8 @@
       Set<Marker> markers = new HashSet<>(options.itemFactory.extractMarkers());
       markers.remove(marker);
       if (options.isGeneratingClassFiles()) {
-        new CfApplicationWriter(appView, marker, graphLens, namingLens, proguardMapSupplier)
-            .write(options.getClassFileConsumer());
+        new CfApplicationWriter(appView, marker, graphLens, namingLens)
+            .write(options.getClassFileConsumer(), inputApp);
       } else {
         new ApplicationWriter(
                 appView,
@@ -237,9 +234,8 @@
                 ImmutableList.<Marker>builder().add(marker).addAll(markers).build(),
                 graphLens,
                 initClassLens,
-                namingLens,
-                proguardMapSupplier)
-            .write(executorService);
+                namingLens)
+            .write(executorService, inputApp);
       }
     } catch (IOException e) {
       throw new RuntimeException("Cannot write application", e);
@@ -786,14 +782,6 @@
 
       assert verifyMovedMethodsHaveOriginalMethodPosition(appView, getDirectApp(appView));
 
-      timing.begin("Line number remapping");
-      // When line number optimization is turned off the identity mapping for line numbers is
-      // used. We still run the line number optimizer to collect line numbers and inline frame
-      // information for the mapping file.
-      ClassNameMapper classNameMapper =
-          LineNumberOptimizer.run(appView, getDirectApp(appView), inputApp, namingLens);
-      timing.end();
-
       // If a method filter is present don't produce output since the application is likely partial.
       if (options.hasMethodsFilter()) {
         System.out.println("Finished compilation with method filter: ");
@@ -853,7 +841,7 @@
           appView.initClassLens(),
           namingLens,
           options,
-          ProguardMapSupplier.create(classNameMapper, options));
+          inputApp);
 
       assert appView.getDontWarnConfiguration().validate(options);
 
diff --git a/src/main/java/com/android/tools/r8/bisect/Bisect.java b/src/main/java/com/android/tools/r8/bisect/Bisect.java
index 7406a28..262300f 100644
--- a/src/main/java/com/android/tools/r8/bisect/Bisect.java
+++ b/src/main/java/com/android/tools/r8/bisect/Bisect.java
@@ -194,8 +194,7 @@
             null,
             GraphLens.getIdentityLens(),
             InitClassLens.getThrowingInstance(),
-            NamingLens.getIdentityLens(),
-            null);
+            NamingLens.getIdentityLens());
     writer.write(executor);
     options.signalFinishedToConsumers();
     compatSink.build().writeToDirectory(output, OutputMode.DexIndexed);
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 3acd908..f99eee5 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.dex;
 
+import static com.android.tools.r8.utils.LineNumberOptimizer.runAndWriteMap;
+
 import com.android.tools.r8.ByteBufferProvider;
 import com.android.tools.r8.ByteDataView;
 import com.android.tools.r8.DataDirectoryResource;
@@ -41,15 +43,16 @@
 import com.android.tools.r8.graph.ObjectToOffsetMapping;
 import com.android.tools.r8.graph.ParameterAnnotationsList;
 import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.naming.ProguardMapSupplier;
 import com.android.tools.r8.naming.ProguardMapSupplier.ProguardMapId;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.shaking.MainDexInfo;
+import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.ArrayUtils;
 import com.android.tools.r8.utils.Box;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.ExceptionUtils;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.OriginalSourceFiles;
 import com.android.tools.r8.utils.PredicateUtils;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.StringUtils;
@@ -63,8 +66,10 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
@@ -84,7 +89,6 @@
   public List<DexString> markerStrings;
 
   public DexIndexedConsumer programConsumer;
-  public final ProguardMapSupplier proguardMapSupplier;
 
   private static class SortAnnotations extends MixedSectionCollection {
 
@@ -154,15 +158,13 @@
       List<Marker> markers,
       GraphLens graphLens,
       InitClassLens initClassLens,
-      NamingLens namingLens,
-      ProguardMapSupplier proguardMapSupplier) {
+      NamingLens namingLens) {
     this(
         appView,
         markers,
         graphLens,
         initClassLens,
         namingLens,
-        proguardMapSupplier,
         null);
   }
 
@@ -172,7 +174,6 @@
       GraphLens graphLens,
       InitClassLens initClassLens,
       NamingLens namingLens,
-      ProguardMapSupplier proguardMapSupplier,
       DexIndexedConsumer consumer) {
     this.appView = appView;
     this.options = appView.options();
@@ -181,7 +182,6 @@
     this.graphLens = graphLens;
     this.initClassLens = initClassLens;
     this.namingLens = namingLens;
-    this.proguardMapSupplier = proguardMapSupplier;
     this.programConsumer = consumer;
     this.isTypeMissing =
         PredicateUtils.isNull(appView.appInfo()::definitionForWithoutExistenceAssert);
@@ -228,17 +228,26 @@
   }
 
   private boolean willComputeProguardMap() {
-    return proguardMapSupplier != null && options.proguardMapConsumer != null;
+    return options.proguardMapConsumer != null;
   }
 
+  /** Writer that never needs the input app to deal with mapping info for kotlin. */
   public void write(ExecutorService executorService) throws IOException, ExecutionException {
+    assert !willComputeProguardMap();
+    write(executorService, null);
+  }
+
+  public void write(ExecutorService executorService, AndroidApp inputApp)
+      throws IOException, ExecutionException {
     Timing timing = appView.appInfo().app().timing;
+
     timing.begin("DexApplication.write");
 
     Box<ProguardMapId> delayedProguardMapId = new Box<>();
     List<LazyDexString> lazyDexStrings = new ArrayList<>();
     computeMarkerStrings(delayedProguardMapId, lazyDexStrings);
-    computeSourceFileString(delayedProguardMapId, lazyDexStrings);
+    OriginalSourceFiles originalSourceFiles =
+        computeSourceFileString(delayedProguardMapId, lazyDexStrings);
 
     try {
       timing.begin("Insert Attribute Annotations");
@@ -295,11 +304,9 @@
       }
 
       // Now code offsets are fixed, compute the mapping file content.
-      // TODO(b/207765416): Move the line number optimizer to this point so PC info can be used.
       if (willComputeProguardMap()) {
-        timing.begin("Write proguard map");
-        delayedProguardMapId.set(proguardMapSupplier.writeProguardMap());
-        timing.end();
+        delayedProguardMapId.set(
+            runAndWriteMap(inputApp, appView, namingLens, timing, originalSourceFiles));
       }
 
       // With the mapping id/hash known, it is safe to compute the remaining dex strings.
@@ -366,17 +373,25 @@
     }
   }
 
-  private void computeSourceFileString(
+  private OriginalSourceFiles computeSourceFileString(
       Box<ProguardMapId> delayedProguardMapId, List<LazyDexString> lazyDexStrings) {
     if (options.sourceFileProvider == null) {
-      return;
+      return OriginalSourceFiles.fromClasses();
     }
     if (!willComputeProguardMap()) {
       rewriteSourceFile(null);
-      return;
+      return OriginalSourceFiles.unreachable();
     }
     // Clear all source files so as not to collect the original files.
-    appView.appInfo().classes().forEach(clazz -> clazz.setSourceFile(null));
+    List<DexProgramClass> classes = appView.appInfo().classes();
+    Map<DexType, DexString> originalSourceFiles = new HashMap<>(classes.size());
+    for (DexProgramClass clazz : classes) {
+      DexString originalSourceFile = clazz.getSourceFile();
+      if (originalSourceFile != null) {
+        originalSourceFiles.put(clazz.getType(), originalSourceFile);
+        clazz.setSourceFile(null);
+      }
+    }
     // Add a lazy dex string computation to defer construction of the actual string.
     lazyDexStrings.add(
         new LazyDexString() {
@@ -385,6 +400,8 @@
             return rewriteSourceFile(delayedProguardMapId.get());
           }
         });
+
+    return OriginalSourceFiles.fromMap(originalSourceFiles);
   }
 
   public static SourceFileEnvironment createSourceFileEnvironment(ProguardMapId proguardMapId) {
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index b10c36a..bdda2fe 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.jar;
 
 import static com.android.tools.r8.utils.InternalOptions.ASM_VERSION;
+import static com.android.tools.r8.utils.LineNumberOptimizer.runAndWriteMap;
 
 import com.android.tools.r8.ByteDataView;
 import com.android.tools.r8.ClassFileConsumer;
@@ -40,14 +41,15 @@
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
 import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.naming.ProguardMapSupplier;
 import com.android.tools.r8.naming.ProguardMapSupplier.ProguardMapId;
 import com.android.tools.r8.references.Reference;
 import com.android.tools.r8.synthesis.SyntheticNaming;
+import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.AsmUtils;
 import com.android.tools.r8.utils.ComparatorUtils;
 import com.android.tools.r8.utils.ExceptionUtils;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.OriginalSourceFiles;
 import com.android.tools.r8.utils.PredicateUtils;
 import com.android.tools.r8.utils.structural.Ordered;
 import com.google.common.collect.ImmutableMap;
@@ -90,16 +92,10 @@
   private final Marker marker;
   private final Predicate<DexType> isTypeMissing;
 
-  public final ProguardMapSupplier proguardMapSupplier;
-
   private static final CfVersion MIN_VERSION_FOR_COMPILER_GENERATED_CODE = CfVersion.V1_6;
 
   public CfApplicationWriter(
-      AppView<?> appView,
-      Marker marker,
-      GraphLens graphLens,
-      NamingLens namingLens,
-      ProguardMapSupplier proguardMapSupplier) {
+      AppView<?> appView, Marker marker, GraphLens graphLens, NamingLens namingLens) {
     this.application = appView.appInfo().app();
     this.appView = appView;
     this.graphLens = graphLens;
@@ -107,15 +103,19 @@
     this.options = appView.options();
     assert marker != null;
     this.marker = marker;
-    this.proguardMapSupplier = proguardMapSupplier;
     this.isTypeMissing =
         PredicateUtils.isNull(appView.appInfo()::definitionForWithoutExistenceAssert);
   }
 
   public void write(ClassFileConsumer consumer) {
+    assert options.proguardMapConsumer == null;
+    write(consumer, null);
+  }
+
+  public void write(ClassFileConsumer consumer, AndroidApp inputApp) {
     application.timing.begin("CfApplicationWriter.write");
     try {
-      writeApplication(consumer);
+      writeApplication(inputApp, consumer);
     } finally {
       application.timing.end();
     }
@@ -132,12 +132,12 @@
     return true;
   }
 
-  private void writeApplication(ClassFileConsumer consumer) {
-    ProguardMapId proguardMapId =
-        (proguardMapSupplier != null && options.proguardMapConsumer != null)
-            ? proguardMapSupplier.writeProguardMap()
-            : null;
-    if (proguardMapId != null) {
+  private void writeApplication(AndroidApp inputApp, ClassFileConsumer consumer) {
+    ProguardMapId proguardMapId = null;
+    if (options.proguardMapConsumer != null) {
+      proguardMapId =
+          runAndWriteMap(
+              inputApp, appView, namingLens, application.timing, OriginalSourceFiles.fromClasses());
       marker.setPgMapId(proguardMapId.getId());
     }
     Optional<String> markerString =
diff --git a/src/main/java/com/android/tools/r8/relocator/Relocator.java b/src/main/java/com/android/tools/r8/relocator/Relocator.java
index bf2bfe8..d0836d7 100644
--- a/src/main/java/com/android/tools/r8/relocator/Relocator.java
+++ b/src/main/java/com/android/tools/r8/relocator/Relocator.java
@@ -89,11 +89,7 @@
       new GenericSignatureRewriter(appView, namingLens).run(appInfo.classes(), executor);
 
       new CfApplicationWriter(
-              appView,
-              new Marker(Tool.Relocator),
-              GraphLens.getIdentityLens(),
-              namingLens,
-              null)
+              appView, new Marker(Tool.Relocator), GraphLens.getIdentityLens(), namingLens)
           .write(command.getConsumer());
       options.printWarnings();
     } catch (ExecutionException e) {
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index 2e9c933..8505e9f 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -54,6 +54,8 @@
 import com.android.tools.r8.naming.MemberNaming.FieldSignature;
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.naming.ProguardMapSupplier;
+import com.android.tools.r8.naming.ProguardMapSupplier.ProguardMapId;
 import com.android.tools.r8.naming.Range;
 import com.android.tools.r8.naming.mappinginformation.CompilerSynthesizedMappingInformation;
 import com.android.tools.r8.naming.mappinginformation.FileNameInformation;
@@ -323,8 +325,32 @@
     }
   }
 
+  public static ProguardMapId runAndWriteMap(
+      AndroidApp inputApp,
+      AppView<?> appView,
+      NamingLens namingLens,
+      Timing timing,
+      OriginalSourceFiles originalSourceFiles) {
+    assert appView.options().proguardMapConsumer != null;
+    // When line number optimization is turned off the identity mapping for line numbers is
+    // used. We still run the line number optimizer to collect line numbers and inline frame
+    // information for the mapping file.
+    timing.begin("Line number remapping");
+    ClassNameMapper mapper =
+        run(appView, appView.appInfo().app(), inputApp, namingLens, originalSourceFiles);
+    timing.end();
+    timing.begin("Write proguard map");
+    ProguardMapId mapId = ProguardMapSupplier.create(mapper, appView.options()).writeProguardMap();
+    timing.end();
+    return mapId;
+  }
+
   public static ClassNameMapper run(
-      AppView<?> appView, DexApplication application, AndroidApp inputApp, NamingLens namingLens) {
+      AppView<?> appView,
+      DexApplication application,
+      AndroidApp inputApp,
+      NamingLens namingLens,
+      OriginalSourceFiles originalSourceFiles) {
     // For finding methods in kotlin files based on SourceDebugExtensions, we use a line method map.
     // We create it here to ensure it is only reading class files once.
     CfLineToMethodMapper cfLineToMethodMapper = new CfLineToMethodMapper(inputApp);
@@ -353,8 +379,9 @@
                       com.android.tools.r8.position.Position.UNKNOWN));
 
       // Check if source file should be added to the map
-      if (clazz.sourceFile != null) {
-        String sourceFile = clazz.sourceFile.toString();
+      DexString originalSourceFile = originalSourceFiles.getOriginalSourceFile(clazz);
+      if (originalSourceFile != null) {
+        String sourceFile = originalSourceFile.toString();
         if (!RetraceUtils.hasPredictableSourceFileName(clazz.toSourceString(), sourceFile)) {
           onDemandClassNamingBuilder
               .get()
diff --git a/src/main/java/com/android/tools/r8/utils/OriginalSourceFiles.java b/src/main/java/com/android/tools/r8/utils/OriginalSourceFiles.java
new file mode 100644
index 0000000..7eca4e7
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/OriginalSourceFiles.java
@@ -0,0 +1,52 @@
+// Copyright (c) 2021, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.utils;
+
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.DexType;
+import java.util.Map;
+
+/** Abstraction to allow removal of the source file content prior to collecting DEX items. */
+public abstract class OriginalSourceFiles {
+
+  private static final OriginalSourceFiles UNREACHABLE =
+      new OriginalSourceFiles() {
+        @Override
+        public DexString getOriginalSourceFile(DexProgramClass clazz) {
+          throw new Unreachable();
+        }
+      };
+
+  private static final OriginalSourceFiles FROM_CLASSES =
+      new OriginalSourceFiles() {
+        @Override
+        public DexString getOriginalSourceFile(DexProgramClass clazz) {
+          return clazz.getSourceFile();
+        }
+      };
+
+  /** For compilations where original source files should never be needed. */
+  public static OriginalSourceFiles unreachable() {
+    return UNREACHABLE;
+  }
+
+  /** For compilations where the original source files is still valid on the classes. */
+  public static OriginalSourceFiles fromClasses() {
+    return FROM_CLASSES;
+  }
+
+  /** Saved mapping of original source files prior to mutating the file on classes. */
+  public static OriginalSourceFiles fromMap(Map<DexType, DexString> map) {
+    return new OriginalSourceFiles() {
+      @Override
+      public DexString getOriginalSourceFile(DexProgramClass clazz) {
+        return map.get(clazz.getType());
+      }
+    };
+  }
+
+  public abstract DexString getOriginalSourceFile(DexProgramClass clazz);
+}
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index 9347e50..ece3111 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -885,8 +885,7 @@
             null,
             GraphLens.getIdentityLens(),
             InitClassLens.getThrowingInstance(),
-            NamingLens.getIdentityLens(),
-            null);
+            NamingLens.getIdentityLens());
     ExecutorService executor = ThreadUtils.getExecutorService(options);
     AndroidAppConsumers compatSink = new AndroidAppConsumers(options);
     try {
diff --git a/src/test/java/com/android/tools/r8/retrace/SourceFileTest.java b/src/test/java/com/android/tools/r8/retrace/SourceFileTest.java
index 5bc7a26..6f533c2 100644
--- a/src/test/java/com/android/tools/r8/retrace/SourceFileTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/SourceFileTest.java
@@ -8,7 +8,7 @@
 import static org.junit.Assert.assertEquals;
 
 import com.android.tools.r8.NeverInline;
-import com.android.tools.r8.R8FullTestBuilder;
+import com.android.tools.r8.R8TestCompileResult;
 import com.android.tools.r8.R8TestRunResult;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
@@ -85,7 +85,7 @@
 
   private void runTest(boolean addDummyArg, BiConsumer<StackTrace, CodeInspector> consumer)
       throws Exception {
-    R8FullTestBuilder r8FullTestBuilder =
+    R8TestCompileResult compileResult =
         testForR8(parameters.getBackend())
             .addProgramClasses(Main.class, ClassWithoutCustomFileName.class)
             .addProgramClassFileData(
@@ -94,11 +94,12 @@
             .enableInliningAnnotations()
             .addKeepMainRule(Main.class)
             .setMinApi(parameters.getApiLevel())
-            .addKeepAttributeSourceFile();
+            .addKeepAttributeSourceFile()
+            .compile();
     R8TestRunResult runResult =
         addDummyArg
-            ? r8FullTestBuilder.run(parameters.getRuntime(), Main.class, "foo")
-            : r8FullTestBuilder.run(parameters.getRuntime(), Main.class);
+            ? compileResult.run(parameters.getRuntime(), Main.class, "foo")
+            : compileResult.run(parameters.getRuntime(), Main.class);
     runResult.assertFailureWithErrorThatMatches(containsString("Hello World!"));
     StackTrace originalStackTrace = runResult.getOriginalStackTrace();
     StackTrace retracedStackTrace = originalStackTrace.retrace(runResult.proguardMap());
diff --git a/src/test/java/com/android/tools/r8/retrace/StackTraceWithPcAndJumboStringTestRunner.java b/src/test/java/com/android/tools/r8/retrace/StackTraceWithPcAndJumboStringTestRunner.java
index 652de07..4ba5253 100644
--- a/src/test/java/com/android/tools/r8/retrace/StackTraceWithPcAndJumboStringTestRunner.java
+++ b/src/test/java/com/android/tools/r8/retrace/StackTraceWithPcAndJumboStringTestRunner.java
@@ -4,7 +4,6 @@
 package com.android.tools.r8.retrace;
 
 import static com.android.tools.r8.naming.retrace.StackTrace.isSame;
-import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
 
 import com.android.tools.r8.TestBase;
@@ -58,20 +57,7 @@
             })
         .run(parameters.getRuntime(), getTestClass())
         .assertFailureWithErrorThatThrows(RuntimeException.class)
-        .inspectStackTrace(
-            stacktrace -> {
-              if (isApiLevelWithPcSupport()) {
-                // TODO(b/207765416): Remove this when PC support works with jumbo string rewriting.
-                assertThat(stacktrace, not(isSame(getExpectedStackTrace())));
-              } else {
-                assertThat(stacktrace, isSame(getExpectedStackTrace()));
-              }
-            });
-  }
-
-  private boolean isApiLevelWithPcSupport() {
-    return parameters.isDexRuntime()
-        && parameters.getApiLevel().isGreaterThanOrEqualTo(apiLevelWithPcAsLineNumberSupport());
+        .inspectStackTrace(stacktrace -> assertThat(stacktrace, isSame(getExpectedStackTrace())));
   }
 
   private StackTrace getExpectedStackTrace() {
diff --git a/src/test/java/com/android/tools/r8/utils/Smali.java b/src/test/java/com/android/tools/r8/utils/Smali.java
index 84099dc..bdeecf4 100644
--- a/src/test/java/com/android/tools/r8/utils/Smali.java
+++ b/src/test/java/com/android/tools/r8/utils/Smali.java
@@ -119,8 +119,7 @@
               null,
               GraphLens.getIdentityLens(),
               InitClassLens.getThrowingInstance(),
-              NamingLens.getIdentityLens(),
-              null);
+              NamingLens.getIdentityLens());
       writer.write(executor);
       return consumer.contents;
     } finally {