Track what intern tables are from boot images

Goal: Use this to make it faster to do collision checks between app
image intern tables against the non boot image intern tables.

Bug: 116059983
Test: test-art-host

Change-Id: I7a2305167335da5b6685822894f7985970e99053
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 10d2b6f..d22b301 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -2178,6 +2178,22 @@
     EXPECT_TRUE(preresolved_seen.find("Other class init") == preresolved_seen.end());
     // Expect the sets match.
     EXPECT_GE(seen.size(), preresolved_seen.size());
+
+    // Verify what strings are marked as boot image.
+    std::set<std::string> boot_image_strings;
+    std::set<std::string> app_image_strings;
+
+    MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
+    intern_table.VisitInterns([&](const GcRoot<mirror::String>& root)
+        REQUIRES_SHARED(Locks::mutator_lock_) {
+      boot_image_strings.insert(root.Read()->ToModifiedUtf8());
+    }, /*visit_boot_images=*/true, /*visit_non_boot_images=*/false);
+    intern_table.VisitInterns([&](const GcRoot<mirror::String>& root)
+        REQUIRES_SHARED(Locks::mutator_lock_) {
+      app_image_strings.insert(root.Read()->ToModifiedUtf8());
+    }, /*visit_boot_images=*/false, /*visit_non_boot_images=*/true);
+    EXPECT_EQ(boot_image_strings.size(), 0u);
+    EXPECT_TRUE(app_image_strings == seen);
   }
 }
 
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index fd10b6b..5ca7f07 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -2614,17 +2614,19 @@
     CHECK_EQ(intern_table_bytes, image_info.intern_table_bytes_);
     // Fixup the pointers in the newly written intern table to contain image addresses.
     InternTable temp_intern_table;
-    // Note that we require that ReadFromMemory does not make an internal copy of the elements so that
-    // the VisitRoots() will update the memory directly rather than the copies.
+    // Note that we require that ReadFromMemory does not make an internal copy of the elements so
+    // that the VisitRoots() will update the memory directly rather than the copies.
     // This also relies on visit roots not doing any verification which could fail after we update
     // the roots to be the image addresses.
-    temp_intern_table.AddTableFromMemory(intern_table_memory_ptr, VoidFunctor());
+    temp_intern_table.AddTableFromMemory(intern_table_memory_ptr,
+                                         VoidFunctor(),
+                                         /*is_boot_image=*/ false);
     CHECK_EQ(temp_intern_table.Size(), intern_table->Size());
     temp_intern_table.VisitRoots(&root_visitor, kVisitRootFlagAllRoots);
     // Record relocations. (The root visitor does not get to see the slot addresses.)
     MutexLock lock(Thread::Current(), *Locks::intern_table_lock_);
     DCHECK(!temp_intern_table.strong_interns_.tables_.empty());
-    DCHECK(!temp_intern_table.strong_interns_.tables_[0].empty());  // Inserted at the beginning.
+    DCHECK(!temp_intern_table.strong_interns_.tables_[0].Empty());  // Inserted at the beginning.
   }
   // Write the class table(s) into the image. class_table_bytes_ may be 0 if there are multiple
   // class loaders. Writing multiple class tables into the image is currently unsupported.