Reapply "Rewrite if rule evaluator to enqueuer extension"

This reverts commit 15288d969d4efec531b2fb30440eddbf7da2469a.

Change-Id: I9ad0bf0d9bb3773c41709d944d1f60456a1012e8
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 46d4c02..dfe2d75 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -270,7 +270,6 @@
   // Don't hold a direct pointer to app info (use appView).
   private AppInfoWithClassHierarchy appInfo;
   private final AppView<AppInfoWithClassHierarchy> appView;
-  private final IfRuleEvaluatorFactory ifRuleEvaluatorFactory;
   private final EnqueuerDeferredTracing deferredTracing;
   private final ExecutorService executorService;
   private SubtypingInfo subtypingInfo;
@@ -500,8 +499,6 @@
     InternalOptions options = appView.options();
     this.appInfo = appView.appInfo();
     this.appView = appView.withClassHierarchy();
-    this.ifRuleEvaluatorFactory =
-        new IfRuleEvaluatorFactory(appView.withClassHierarchy(), this, executorService);
     this.profileCollectionAdditions = profileCollectionAdditions;
     this.deferredTracing = EnqueuerDeferredTracing.create(appView, this, mode);
     this.executorService = executorService;
@@ -535,6 +532,7 @@
       ResourceAccessAnalysis.register(appView, this);
       CovariantReturnTypeEnqueuerExtension.register(appView, this);
     }
+    IfRuleEvaluatorFactory.register(appView, this, executorService);
 
     targetedMethods = new LiveMethodsSet(graphReporter::registerMethod);
     failedClassResolutionTargets = SetUtils.newIdentityHashSet(0);
@@ -831,6 +829,10 @@
     return keepInfo.getClassInfo(clazz);
   }
 
+  public SubtypingInfo getSubtypingInfo() {
+    return subtypingInfo;
+  }
+
   public boolean hasMinimumKeepInfoThatMatches(
       DexProgramClass clazz, Predicate<KeepClassInfo.Joiner> predicate) {
     MinimumKeepInfoCollection minimumKeepInfoCollection =
@@ -4730,7 +4732,6 @@
         long numberOfLiveItemsAfterProcessing = getNumberOfLiveItems();
         if (numberOfLiveItemsAfterProcessing > numberOfLiveItems) {
           timing.time("Conditional rules", () -> applicableRules.evaluateConditionalRules(this));
-          ifRuleEvaluatorFactory.run(subtypingInfo, timing);
           assert getNumberOfLiveItems() == numberOfLiveItemsAfterProcessing;
           if (!worklist.isEmpty()) {
             continue;
@@ -4762,6 +4763,7 @@
         // opportunity to add items to the worklist.
         for (EnqueuerAnalysis analysis : analyses) {
           analysis.notifyFixpoint(this, worklist, executorService, timing);
+          assert getNumberOfLiveItems() == numberOfLiveItemsAfterProcessing;
         }
         if (!worklist.isEmpty()) {
           continue;
@@ -4850,7 +4852,7 @@
     }
   }
 
-  private long getNumberOfLiveItems() {
+  public long getNumberOfLiveItems() {
     long result = liveTypes.getItems().size();
     result += liveMethods.items.size();
     result += liveFields.fields.size();
diff --git a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluatorFactory.java b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluatorFactory.java
index 5857e14..dc438f3 100644
--- a/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluatorFactory.java
+++ b/src/main/java/com/android/tools/r8/shaking/IfRuleEvaluatorFactory.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.SubtypingInfo;
+import com.android.tools.r8.graph.analysis.EnqueuerAnalysis;
 import com.android.tools.r8.shaking.RootSetUtils.ConsequentRootSet;
 import com.android.tools.r8.shaking.RootSetUtils.ConsequentRootSetBuilder;
 import com.android.tools.r8.threading.TaskCollection;
@@ -25,15 +26,16 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 
-public class IfRuleEvaluatorFactory {
+public class IfRuleEvaluatorFactory extends EnqueuerAnalysis {
 
   private final AppView<? extends AppInfoWithClassHierarchy> appView;
-  private final Enqueuer enqueuer;
 
   /** Map of active if rules. This is important for speeding up aapt2 generated keep rules. */
   private final Map<Wrapper<ProguardIfRule>, Set<ProguardIfRule>> activeIfRules;
 
   private final Set<DexProgramClass> effectivelyFakeLiveClasses;
+  private final Set<DexProgramClass> newlyLiveClasses = Sets.newIdentityHashSet();
+  private long previousNumberOfLiveItems = 0;
 
   private final TaskCollection<?> tasks;
 
@@ -42,12 +44,21 @@
       Enqueuer enqueuer,
       ExecutorService executorService) {
     this.appView = appView;
-    this.enqueuer = enqueuer;
     this.activeIfRules = createActiveIfRules(appView.rootSet().ifRules);
     this.effectivelyFakeLiveClasses = createEffectivelyFakeLiveClasses(appView, enqueuer);
     this.tasks = new TaskCollection<>(appView.options(), executorService);
   }
 
+  public static void register(
+      AppView<? extends AppInfoWithClassHierarchy> appView,
+      Enqueuer enqueuer,
+      ExecutorService executorService) {
+    Set<ProguardIfRule> ifRules = appView.rootSet().ifRules;
+    if (ifRules != null && !ifRules.isEmpty()) {
+      enqueuer.registerAnalysis(new IfRuleEvaluatorFactory(appView, enqueuer, executorService));
+    }
+  }
+
   @SuppressWarnings("MixedMutabilityReturnType")
   private static Map<Wrapper<ProguardIfRule>, Set<ProguardIfRule>> createActiveIfRules(
       Set<ProguardIfRule> ifRules) {
@@ -97,10 +108,19 @@
     return false;
   }
 
-  public void run(SubtypingInfo subtypingInfo, Timing timing) throws ExecutionException {
+  @Override
+  public void notifyFixpoint(
+      Enqueuer enqueuer, EnqueuerWorklist worklist, ExecutorService executorService, Timing timing)
+      throws ExecutionException {
+    // TODO(b/206086945): Leverage newlyLiveClasses.
     if (activeIfRules.isEmpty()) {
       return;
     }
+    long numberOfLiveItems = enqueuer.getNumberOfLiveItems();
+    if (numberOfLiveItems == previousNumberOfLiveItems) {
+      return;
+    }
+    SubtypingInfo subtypingInfo = enqueuer.getSubtypingInfo();
     ConsequentRootSetBuilder consequentRootSetBuilder =
         ConsequentRootSet.builder(appView, enqueuer, subtypingInfo);
     IfRuleEvaluator evaluator =
@@ -109,5 +129,14 @@
         "Find consequent items for -if rules...",
         () -> evaluator.run(activeIfRules, effectivelyFakeLiveClasses));
     enqueuer.addConsequentRootSet(consequentRootSetBuilder.buildConsequentRootSet());
+    previousNumberOfLiveItems = numberOfLiveItems;
+  }
+
+  @Override
+  public void processNewlyLiveClass(DexProgramClass clazz, EnqueuerWorklist worklist) {
+    if (effectivelyFakeLiveClasses.contains(clazz)) {
+      return;
+    }
+    newlyLiveClasses.add(clazz);
   }
 }