Paralleize jumbo string rewriting

Bug: b/422947619

Change-Id: Ia7ebdc2c556710d2fdd318f04cf62d51bb1a5546
diff --git a/src/main/java/com/android/tools/r8/dex/jumbostrings/ContainerJumboStringRewriter.java b/src/main/java/com/android/tools/r8/dex/jumbostrings/ContainerJumboStringRewriter.java
index 4cf0940..dc287f8 100644
--- a/src/main/java/com/android/tools/r8/dex/jumbostrings/ContainerJumboStringRewriter.java
+++ b/src/main/java/com/android/tools/r8/dex/jumbostrings/ContainerJumboStringRewriter.java
@@ -37,7 +37,7 @@
     }
     // Compute string layout and handle jumbo strings for the last DEX section.
     timing.begin("Process last virtual file");
-    processVirtualFile(lastFile, timing);
+    processVirtualFile(lastFile, timing, executorService);
     timing.end();
     // Handle jumbo strings for the remaining DEX sections using the string ids in the last DEX
     // section.
@@ -46,7 +46,7 @@
         alwaysTrue(),
         (virtualFile, threadTiming) ->
             rewriteJumboStringsAndComputeDebugRepresentationWithExternalStringIds(
-                virtualFile, lastFile.getObjectMapping(), threadTiming),
+                virtualFile, lastFile.getObjectMapping(), threadTiming, executorService),
         appView.options(),
         executorService,
         timing,
@@ -54,13 +54,22 @@
   }
 
   private void rewriteJumboStringsAndComputeDebugRepresentationWithExternalStringIds(
-      VirtualFile virtualFile, ObjectToOffsetMapping mapping, Timing timing) {
-    computeOffsetMappingAndRewriteJumboStringsWithExternalStringIds(virtualFile, timing, mapping);
+      VirtualFile virtualFile,
+      ObjectToOffsetMapping mapping,
+      Timing timing,
+      ExecutorService executorService)
+      throws ExecutionException {
+    computeOffsetMappingAndRewriteJumboStringsWithExternalStringIds(
+        virtualFile, timing, mapping, executorService);
     DebugRepresentation.computeForFile(appView, virtualFile);
   }
 
   private void computeOffsetMappingAndRewriteJumboStringsWithExternalStringIds(
-      VirtualFile virtualFile, Timing timing, ObjectToOffsetMapping mapping) {
+      VirtualFile virtualFile,
+      Timing timing,
+      ObjectToOffsetMapping mapping,
+      ExecutorService executorService)
+      throws ExecutionException {
     if (virtualFile.isEmpty()) {
       return;
     }
@@ -68,7 +77,8 @@
     virtualFile.computeMapping(appView, lazyDexStrings.size(), timing, mapping);
     timing.end();
     timing.begin("Rewrite jumbo strings");
-    rewriteCodeWithJumboStrings(virtualFile.getObjectMapping(), virtualFile.classes());
+    rewriteCodeWithJumboStrings(
+        virtualFile.getObjectMapping(), virtualFile.classes(), executorService);
     timing.end();
   }
 }
diff --git a/src/main/java/com/android/tools/r8/dex/jumbostrings/JumboStringRewriter.java b/src/main/java/com/android/tools/r8/dex/jumbostrings/JumboStringRewriter.java
index 22aef00..a0fd1e8 100644
--- a/src/main/java/com/android/tools/r8/dex/jumbostrings/JumboStringRewriter.java
+++ b/src/main/java/com/android/tools/r8/dex/jumbostrings/JumboStringRewriter.java
@@ -53,19 +53,23 @@
     ThreadUtils.processItemsThatMatches(
         virtualFiles,
         alwaysTrue(),
-        this::processVirtualFile,
+        (virtualFile, ttiming) -> processVirtualFile(virtualFile, ttiming, executorService),
         options,
         executorService,
         timing,
         timing.beginMerger("Pre-write phase", executorService));
   }
 
-  protected final void processVirtualFile(VirtualFile virtualFile, Timing timing) {
-    computeOffsetMappingAndRewriteJumboStrings(virtualFile, timing);
+  protected final void processVirtualFile(
+      VirtualFile virtualFile, Timing timing, ExecutorService executorService)
+      throws ExecutionException {
+    computeOffsetMappingAndRewriteJumboStrings(virtualFile, timing, executorService);
     DebugRepresentation.computeForFile(appView, virtualFile);
   }
 
-  private void computeOffsetMappingAndRewriteJumboStrings(VirtualFile virtualFile, Timing timing) {
+  private void computeOffsetMappingAndRewriteJumboStrings(
+      VirtualFile virtualFile, Timing timing, ExecutorService executorService)
+      throws ExecutionException {
     if (virtualFile.isEmpty()) {
       return;
     }
@@ -73,7 +77,8 @@
     virtualFile.computeMapping(appView, lazyDexStrings.size(), timing);
     timing.end();
     timing.begin("Rewrite jumbo strings");
-    rewriteCodeWithJumboStrings(virtualFile.getObjectMapping(), virtualFile.classes());
+    rewriteCodeWithJumboStrings(
+        virtualFile.getObjectMapping(), virtualFile.classes(), executorService);
     timing.end();
   }
 
@@ -85,7 +90,10 @@
    * be used.
    */
   protected final void rewriteCodeWithJumboStrings(
-      ObjectToOffsetMapping mapping, Collection<DexProgramClass> classes) {
+      ObjectToOffsetMapping mapping,
+      Collection<DexProgramClass> classes,
+      ExecutorService executorService)
+      throws ExecutionException {
     // Do not bail out early if forcing jumbo string processing.
     if (!options.getTestingOptions().forceJumboStringProcessing) {
       // If there are no strings with jumbo indices at all this is a no-op.
@@ -93,19 +101,23 @@
         return;
       }
     }
-    for (DexProgramClass clazz : classes) {
-      clazz.forEachProgramMethodMatching(
-          DexEncodedMethod::hasCode,
-          method -> {
-            DexWritableCode code = method.getDefinition().getCode().asDexWritableCode();
-            DexWritableCode rewrittenCode =
-                code.rewriteCodeWithJumboStrings(
-                    method,
-                    mapping,
-                    appView,
-                    options.getTestingOptions().forceJumboStringProcessing);
-            method.setCode(rewrittenCode.asCode(), appView);
-          });
-    }
+
+    ThreadUtils.processItems(
+        classes,
+        clazz ->
+            clazz.forEachProgramMethodMatching(
+                DexEncodedMethod::hasCode,
+                method -> {
+                  DexWritableCode code = method.getDefinition().getCode().asDexWritableCode();
+                  DexWritableCode rewrittenCode =
+                      code.rewriteCodeWithJumboStrings(
+                          method,
+                          mapping,
+                          appView,
+                          options.getTestingOptions().forceJumboStringProcessing);
+                  method.setCode(rewrittenCode.asCode(), appView);
+                }),
+        options.getThreadingModule(),
+        executorService);
   }
 }