Clear reference type lattice element cache after main dex computation

This is needed since the class type lattice elements store information about the interfaces that they implement, which may become obsolete as a result of vertical class merging.

Bug: 130051274
Change-Id: I093b88e2ec29f3774d7df144220de99a8bff1f0f
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index f0d4ffb..f903cce 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -398,6 +398,11 @@
         appView.appInfo().unsetObsolete();
       }
 
+      // The class type lattice elements include information about the interfaces that a class
+      // implements. This information can change as a result of vertical class merging, so we need
+      // to clear the cache, so that we will recompute the type lattice elements.
+      appView.dexItemFactory().clearReferenceTypeLatticeElementsCache();
+
       if (options.getProguardConfiguration().isAccessModificationAllowed()) {
         GraphLense publicizedLense =
             ClassAndMemberPublicizer.run(
@@ -411,82 +416,79 @@
         }
       }
 
-      if (appView.appInfo().hasLiveness()) {
-        AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
-        appView.setGraphLense(new MemberRebindingAnalysis(appViewWithLiveness).run());
-        if (options.enableHorizontalClassMerging) {
-          timing.begin("HorizontalStaticClassMerger");
-          StaticClassMerger staticClassMerger =
-              new StaticClassMerger(appViewWithLiveness, options, mainDexClasses);
-          boolean changed = appView.setGraphLense(staticClassMerger.run());
-          if (changed) {
-            appViewWithLiveness.setAppInfo(
-                appViewWithLiveness
-                    .appInfo()
-                    .rewrittenWithLense(application.asDirect(), appView.graphLense()));
-          }
-          timing.end();
+      AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+      appView.setGraphLense(new MemberRebindingAnalysis(appViewWithLiveness).run());
+      if (options.enableHorizontalClassMerging) {
+        timing.begin("HorizontalStaticClassMerger");
+        StaticClassMerger staticClassMerger =
+            new StaticClassMerger(appViewWithLiveness, options, mainDexClasses);
+        boolean changed = appView.setGraphLense(staticClassMerger.run());
+        if (changed) {
+          appViewWithLiveness.setAppInfo(
+              appViewWithLiveness
+                  .appInfo()
+                  .rewrittenWithLense(application.asDirect(), appView.graphLense()));
         }
-        if (options.enableVerticalClassMerging) {
-          timing.begin("VerticalClassMerger");
-          VerticalClassMerger verticalClassMerger =
-              new VerticalClassMerger(
-                  application,
-                  appViewWithLiveness,
-                  executorService,
-                  timing,
-                  mainDexClasses);
-          boolean changed = appView.setGraphLense(verticalClassMerger.run());
+        timing.end();
+      }
+      if (options.enableVerticalClassMerging) {
+        timing.begin("VerticalClassMerger");
+        VerticalClassMerger verticalClassMerger =
+            new VerticalClassMerger(
+                application, appViewWithLiveness, executorService, timing, mainDexClasses);
+        boolean changed = appView.setGraphLense(verticalClassMerger.run());
+        if (changed) {
+          appView.setVerticallyMergedClasses(verticalClassMerger.getMergedClasses());
+          application = application.asDirect().rewrittenWithLense(appView.graphLense());
+          appViewWithLiveness.setAppInfo(
+              appViewWithLiveness
+                  .appInfo()
+                  .prunedCopyFrom(application, verticalClassMerger.getRemovedClasses())
+                  .rewrittenWithLense(application.asDirect(), appView.graphLense()));
+        }
+        timing.end();
+      }
+      if (options.enableArgumentRemoval) {
+        if (options.enableUnusedArgumentRemoval) {
+          timing.begin("UnusedArgumentRemoval");
+          boolean changed =
+              appView.setGraphLense(
+                  new UnusedArgumentsCollector(
+                          appViewWithLiveness, new MethodPoolCollection(appView))
+                      .run(executorService, timing));
           if (changed) {
-            appView.setVerticallyMergedClasses(verticalClassMerger.getMergedClasses());
             application = application.asDirect().rewrittenWithLense(appView.graphLense());
             appViewWithLiveness.setAppInfo(
                 appViewWithLiveness
                     .appInfo()
-                    .prunedCopyFrom(application, verticalClassMerger.getRemovedClasses())
                     .rewrittenWithLense(application.asDirect(), appView.graphLense()));
           }
           timing.end();
         }
-        if (options.enableArgumentRemoval) {
-          if (options.enableUnusedArgumentRemoval) {
-            timing.begin("UnusedArgumentRemoval");
-            boolean changed =
-                appView.setGraphLense(
-                    new UnusedArgumentsCollector(
-                            appViewWithLiveness, new MethodPoolCollection(appView))
-                        .run(executorService, timing));
-            if (changed) {
-              application = application.asDirect().rewrittenWithLense(appView.graphLense());
-              appViewWithLiveness.setAppInfo(
-                  appViewWithLiveness
-                      .appInfo()
-                      .rewrittenWithLense(application.asDirect(), appView.graphLense()));
-            }
-            timing.end();
+        if (options.enableUninstantiatedTypeOptimization) {
+          timing.begin("UninstantiatedTypeOptimization");
+          boolean changed =
+              appView.setGraphLense(
+                  new UninstantiatedTypeOptimization(appViewWithLiveness)
+                      .run(new MethodPoolCollection(appView), executorService, timing));
+          if (changed) {
+            application = application.asDirect().rewrittenWithLense(appView.graphLense());
+            appViewWithLiveness.setAppInfo(
+                appViewWithLiveness
+                    .appInfo()
+                    .rewrittenWithLense(application.asDirect(), appView.graphLense()));
           }
-          if (options.enableUninstantiatedTypeOptimization) {
-            timing.begin("UninstantiatedTypeOptimization");
-            boolean changed =
-                appView.setGraphLense(
-                    new UninstantiatedTypeOptimization(appViewWithLiveness)
-                        .run(new MethodPoolCollection(appView), executorService, timing));
-            if (changed) {
-              application = application.asDirect().rewrittenWithLense(appView.graphLense());
-              appViewWithLiveness.setAppInfo(
-                  appViewWithLiveness
-                      .appInfo()
-                      .rewrittenWithLense(application.asDirect(), appView.graphLense()));
-            }
-            timing.end();
-          }
+          timing.end();
         }
-
-        // Collect switch maps and ordinals maps.
-        appViewWithLiveness.setAppInfo(new SwitchMapCollector(appViewWithLiveness).run());
-        appViewWithLiveness.setAppInfo(new EnumOrdinalMapCollector(appViewWithLiveness).run());
       }
 
+      // None of the optimizations above should lead to the creation of type lattice elements.
+      assert appView.dexItemFactory().verifyNoCachedReferenceTypeLatticeElements();
+
+      // Collect switch maps and ordinals maps.
+      appViewWithLiveness.setAppInfo(new SwitchMapCollector(appViewWithLiveness).run());
+      appViewWithLiveness.setAppInfo(new EnumOrdinalMapCollector(appViewWithLiveness).run());
+
       appView.setAppServices(appView.appServices().rewrittenWithLens(appView.graphLense()));
 
       timing.begin("Create IR");
@@ -563,7 +565,6 @@
           || options.getProguardConfiguration().hasApplyMappingFile()) {
         timing.begin("Post optimization code stripping");
         try {
-
           GraphConsumer keptGraphConsumer = null;
           WhyAreYouKeepingConsumer whyAreYouKeepingConsumer = null;
           if (options.isShrinking()) {
@@ -582,7 +583,6 @@
                   executorService,
                   timing));
 
-          AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
           if (options.isShrinking()) {
             TreePruner pruner = new TreePruner(application, appViewWithLiveness);
             application = pruner.run();
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 4934f4a..2e85ad1 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -1173,6 +1173,15 @@
     return method.name == classConstructorMethodName;
   }
 
+  public void clearReferenceTypeLatticeElementsCache() {
+    referenceTypeLatticeElements.clear();
+  }
+
+  public boolean verifyNoCachedReferenceTypeLatticeElements() {
+    assert referenceTypeLatticeElements.isEmpty();
+    return true;
+  }
+
   public ReferenceTypeLatticeElement createReferenceTypeLatticeElement(
       DexType type, Nullability nullability, AppView<? extends AppInfo> appView) {
     // Class case: