Emit more timing information in Enqueuer

Bug: b/378464445
Change-Id: I2472478ec63cddf17230a0cbd26382a6a121bc41
diff --git a/src/main/java/com/android/tools/r8/shaking/EmptyEnqueuerDeferredTracing.java b/src/main/java/com/android/tools/r8/shaking/EmptyEnqueuerDeferredTracing.java
index 2faf20b..8872ed2 100644
--- a/src/main/java/com/android/tools/r8/shaking/EmptyEnqueuerDeferredTracing.java
+++ b/src/main/java/com/android/tools/r8/shaking/EmptyEnqueuerDeferredTracing.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.shaking.Enqueuer.FieldAccessKind;
 import com.android.tools.r8.shaking.Enqueuer.FieldAccessMetadata;
+import com.android.tools.r8.utils.Timing;
 import java.util.concurrent.ExecutorService;
 
 public class EmptyEnqueuerDeferredTracing extends EnqueuerDeferredTracing {
@@ -25,7 +26,7 @@
   }
 
   @Override
-  public boolean enqueueWorklistActions(EnqueuerWorklist worklist) {
+  public boolean enqueueWorklistActions(EnqueuerWorklist worklist, Timing timing) {
     return false;
   }
 
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 30d420d..9cfbfb7 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -4187,7 +4187,7 @@
     }
   }
 
-  private void synthesize() throws ExecutionException {
+  private void synthesize(Timing timing) throws ExecutionException {
     if (!mode.isInitialTreeShaking()) {
       return;
     }
@@ -4195,20 +4195,20 @@
     // In particular these additions are order independent, i.e., it does not matter which are
     // registered first and no dependencies may exist among them.
     SyntheticAdditions additions = new SyntheticAdditions(appView.createProcessorContext());
-    desugar(additions);
-    synthesizeInterfaceMethodBridges();
+    timing.time("Desugar", () -> desugar(additions));
+    timing.time("Synthesize interface method bridges", this::synthesizeInterfaceMethodBridges);
     if (additions.isEmpty()) {
       return;
     }
 
     // Commit the pending synthetics and recompute subtypes.
-    appInfo = appInfo.rebuildWithClassHierarchy(app -> app);
+    appInfo = timing.time("Rebuild AppInfo", () -> appInfo.rebuildWithClassHierarchy(app -> app));
     appView.setAppInfo(appInfo);
-    subtypingInfo = SubtypingInfo.create(appView);
+    subtypingInfo = timing.time("Create SubtypingInfo", () -> SubtypingInfo.create(appView));
 
     // Finally once all synthesized items "exist" it is now safe to continue tracing. The new work
     // items are enqueued and the fixed point will continue once this subroutine returns.
-    additions.enqueueWorkItems(this);
+    timing.time("Enqueue work items", () -> additions.enqueueWorkItems(this));
   }
 
   private boolean mustMoveToInterfaceCompanionMethod(ProgramMethod method) {
@@ -4638,7 +4638,9 @@
   private void trace(ExecutorService executorService, Timing timing) throws ExecutionException {
     timing.begin("Grow the tree.");
     try {
+      int round = 1;
       while (true) {
+        timing.begin("Compute fixpoint #" + round++);
         long numberOfLiveItems = getNumberOfLiveItems();
         while (worklist.hasNext()) {
           EnqueuerAction action = worklist.poll();
@@ -4651,38 +4653,49 @@
           timing.time("Conditional rules", () -> applicableRules.evaluateConditionalRules(this));
           assert getNumberOfLiveItems() == numberOfLiveItemsAfterProcessing;
           if (worklist.hasNext()) {
+            timing.end();
             continue;
           }
         }
 
         // Process all deferred annotations.
+        timing.begin("Process deferred annotations");
         processDeferredAnnotations(deferredAnnotations, AnnotatedKind::from);
         processDeferredAnnotations(
             deferredParameterAnnotations, annotatedItem -> AnnotatedKind.PARAMETER);
+        timing.end();
 
         // Continue fix-point processing while there are additional work items to ensure items that
         // are passed to Java reflections are traced.
         if (!pendingReflectiveUses.isEmpty()) {
+          timing.begin("Handle reflective behavior");
           pendingReflectiveUses.forEach(this::handleReflectiveBehavior);
           pendingReflectiveUses.clear();
+          timing.end();
         }
         if (worklist.hasNext()) {
+          timing.end();
           continue;
         }
 
         // Allow deferred tracing to enqueue worklist items.
-        if (deferredTracing.enqueueWorklistActions(worklist)) {
+        if (deferredTracing.enqueueWorklistActions(worklist, timing)) {
           assert worklist.hasNext();
+          timing.end();
           continue;
         }
 
         // Notify each analysis that a fixpoint has been reached, and give each analysis an
         // opportunity to add items to the worklist.
-        analyses.notifyFixpoint(this, worklist, executorService, timing);
+        timing.time(
+            "Notify analyses",
+            () -> analyses.notifyFixpoint(this, worklist, executorService, timing));
         if (worklist.hasNext()) {
+          timing.end();
           continue;
         }
 
+        timing.begin("Process delayed root set items");
         for (DelayedRootSetActionItem delayedRootSetActionItem :
             rootSet.delayedRootSetActionItems) {
           if (delayedRootSetActionItem.isInterfaceMethodSyntheticBridgeAction()) {
@@ -4690,26 +4703,31 @@
                 delayedRootSetActionItem.asInterfaceMethodSyntheticBridgeAction());
           }
         }
+        timing.end();
 
-        synthesize();
+        timing.time("Synthesize", () -> synthesize(timing));
 
+        timing.begin("Delayed interface method synthetic bridges");
         ConsequentRootSet consequentRootSet = computeDelayedInterfaceMethodSyntheticBridges();
         addConsequentRootSet(consequentRootSet);
         rootSet
             .getDependentMinimumKeepInfo()
             .merge(consequentRootSet.getDependentMinimumKeepInfo());
         rootSet.delayedRootSetActionItems.clear();
+        timing.end();
 
         if (worklist.hasNext()) {
+          timing.end();
           continue;
         }
 
         // Reached the fixpoint.
+        timing.end();
         break;
       }
 
       if (mode.isInitialTreeShaking()) {
-        postProcessingDesugaring();
+        timing.time("Post processing desugaring", this::postProcessingDesugaring);
       }
     } finally {
       timing.end();
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracing.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracing.java
index d7369fbd..1955dfe 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracing.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracing.java
@@ -14,6 +14,7 @@
 import com.android.tools.r8.shaking.Enqueuer.FieldAccessMetadata;
 import com.android.tools.r8.shaking.Enqueuer.Mode;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Timing;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 
@@ -56,7 +57,7 @@
    *
    * @return true if any worklist items were enqueued.
    */
-  public abstract boolean enqueueWorklistActions(EnqueuerWorklist worklist);
+  public abstract boolean enqueueWorklistActions(EnqueuerWorklist worklist, Timing timing);
 
   /**
    * Called when tree shaking has ended, to allow rewriting the application according to the tracing
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
index 1c3889d..bf3e76d 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
@@ -229,15 +229,19 @@
   }
 
   @Override
-  public boolean enqueueWorklistActions(EnqueuerWorklist worklist) {
-    return deferredEnqueuerActions.removeIf(
-        (field, worklistActions) -> {
-          if (isEligibleForPruning(field)) {
-            return false;
-          }
-          worklist.enqueueAll(worklistActions);
-          return true;
-        });
+  public boolean enqueueWorklistActions(EnqueuerWorklist worklist, Timing timing) {
+    timing.begin("Process deferred tracing");
+    boolean changed =
+        deferredEnqueuerActions.removeIf(
+            (field, worklistActions) -> {
+              if (isEligibleForPruning(field)) {
+                return false;
+              }
+              worklist.enqueueAll(worklistActions);
+              return true;
+            });
+    timing.end();
+    return changed;
   }
 
   @Override