Always create IMT conflict tables when generating an image.

It is required by the runtime. Also remove obsolete code around forcing
array class initialization: we now always intialize in array classes in
ClassLinker::FinishArrayClassSetup.

Test: eng builds
Bug: 166327764
Change-Id: I2f2398a8ba60360588c089affc4a73897d9df97b
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index ef0677d..c08227a 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -851,6 +851,51 @@
   }
 }
 
+class CreateConflictTablesVisitor : public ClassVisitor {
+ public:
+  explicit CreateConflictTablesVisitor(VariableSizedHandleScope& hs)
+      : hs_(hs) {}
+
+  bool operator()(ObjPtr<mirror::Class> klass) override
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    if (Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass)) {
+      return true;
+    }
+    // Collect handles since there may be thread suspension in future EnsureInitialized.
+    to_visit_.push_back(hs_.NewHandle(klass));
+    return true;
+  }
+
+  void FillAllIMTAndConflictTables() REQUIRES_SHARED(Locks::mutator_lock_) {
+    for (Handle<mirror::Class> c : to_visit_) {
+      // Create the conflict tables.
+      FillIMTAndConflictTables(c.Get());
+    }
+  }
+
+ private:
+  void FillIMTAndConflictTables(ObjPtr<mirror::Class> klass)
+      REQUIRES_SHARED(Locks::mutator_lock_) {
+    if (!klass->ShouldHaveImt()) {
+      return;
+    }
+    if (visited_classes_.find(klass) != visited_classes_.end()) {
+      return;
+    }
+    if (klass->HasSuperClass()) {
+      FillIMTAndConflictTables(klass->GetSuperClass());
+    }
+    if (!klass->IsTemp()) {
+      Runtime::Current()->GetClassLinker()->FillIMTAndConflictTables(klass);
+    }
+    visited_classes_.insert(klass);
+  }
+
+  VariableSizedHandleScope& hs_;
+  std::vector<Handle<mirror::Class>> to_visit_;
+  std::unordered_set<ObjPtr<mirror::Class>, HashObjPtr> visited_classes_;
+};
+
 void CompilerDriver::PreCompile(jobject class_loader,
                                 const std::vector<const DexFile*>& dex_files,
                                 TimingLogger* timings,
@@ -927,6 +972,15 @@
       InitializeClasses(class_loader, dex_files, timings);
       VLOG(compiler) << "InitializeClasses: " << GetMemoryUsageString(false);
     }
+    {
+      // Create conflict tables, as the runtime expects boot image classes to
+      // always have their conflict tables filled.
+      ScopedObjectAccess soa(Thread::Current());
+      VariableSizedHandleScope hs(soa.Self());
+      CreateConflictTablesVisitor visitor(hs);
+      Runtime::Current()->GetClassLinker()->VisitClassesWithoutClassesLock(&visitor);
+      visitor.FillAllIMTAndConflictTables();
+    }
 
     UpdateImageClasses(timings, image_classes);
     VLOG(compiler) << "UpdateImageClasses: " << GetMemoryUsageString(false);
@@ -2623,56 +2677,6 @@
   class_linker->MakeInitializedClassesVisiblyInitialized(Thread::Current(), /*wait=*/ true);
 }
 
-class InitializeArrayClassesAndCreateConflictTablesVisitor : public ClassVisitor {
- public:
-  explicit InitializeArrayClassesAndCreateConflictTablesVisitor(VariableSizedHandleScope& hs)
-      : hs_(hs) {}
-
-  bool operator()(ObjPtr<mirror::Class> klass) override
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass)) {
-      return true;
-    }
-    if (klass->IsArrayClass()) {
-      StackHandleScope<1> hs(Thread::Current());
-      auto h_klass = hs.NewHandleWrapper(&klass);
-      Runtime::Current()->GetClassLinker()->EnsureInitialized(hs.Self(), h_klass, true, true);
-    }
-    // Collect handles since there may be thread suspension in future EnsureInitialized.
-    to_visit_.push_back(hs_.NewHandle(klass));
-    return true;
-  }
-
-  void FillAllIMTAndConflictTables() REQUIRES_SHARED(Locks::mutator_lock_) {
-    for (Handle<mirror::Class> c : to_visit_) {
-      // Create the conflict tables.
-      FillIMTAndConflictTables(c.Get());
-    }
-  }
-
- private:
-  void FillIMTAndConflictTables(ObjPtr<mirror::Class> klass)
-      REQUIRES_SHARED(Locks::mutator_lock_) {
-    if (!klass->ShouldHaveImt()) {
-      return;
-    }
-    if (visited_classes_.find(klass) != visited_classes_.end()) {
-      return;
-    }
-    if (klass->HasSuperClass()) {
-      FillIMTAndConflictTables(klass->GetSuperClass());
-    }
-    if (!klass->IsTemp()) {
-      Runtime::Current()->GetClassLinker()->FillIMTAndConflictTables(klass);
-    }
-    visited_classes_.insert(klass);
-  }
-
-  VariableSizedHandleScope& hs_;
-  std::vector<Handle<mirror::Class>> to_visit_;
-  std::unordered_set<ObjPtr<mirror::Class>, HashObjPtr> visited_classes_;
-};
-
 void CompilerDriver::InitializeClasses(jobject class_loader,
                                        const std::vector<const DexFile*>& dex_files,
                                        TimingLogger* timings) {
@@ -2681,20 +2685,6 @@
     CHECK(dex_file != nullptr);
     InitializeClasses(class_loader, *dex_file, dex_files, timings);
   }
-  if (GetCompilerOptions().IsBootImage() ||
-      GetCompilerOptions().IsBootImageExtension() ||
-      GetCompilerOptions().IsAppImage()) {
-    // Make sure that we call EnsureIntiailized on all the array classes to call
-    // SetVerificationAttempted so that the access flags are set. If we do not do this they get
-    // changed at runtime resulting in more dirty image pages.
-    // Also create conflict tables.
-    // Only useful if we are compiling an image.
-    ScopedObjectAccess soa(Thread::Current());
-    VariableSizedHandleScope hs(soa.Self());
-    InitializeArrayClassesAndCreateConflictTablesVisitor visitor(hs);
-    Runtime::Current()->GetClassLinker()->VisitClassesWithoutClassesLock(&visitor);
-    visitor.FillAllIMTAndConflictTables();
-  }
   if (GetCompilerOptions().IsBootImage() || GetCompilerOptions().IsBootImageExtension()) {
     // Prune garbage objects created during aborted transactions.
     Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ true);
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 059b09c..09fa99b 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -7046,9 +7046,6 @@
                        &new_conflict,
                        &imt_data[0]);
   }
-  if (!klass->ShouldHaveImt()) {
-    return;
-  }
   // Compare the IMT with the super class including the conflict methods. If they are equivalent,
   // we can just use the same pointer.
   ImTable* imt = nullptr;