Combine class sets when writing a class table

Reduces the boot.art size since we allocate a new class set with the
default load factor. The load factor in the combined class table is
higher to pruning classes, this reduces the size of the boot image.

Also fixes the hypothetical case where the class table being written
has multiple class sets.

Boot.art size
Before: 8122368
After: 8044544

Slight cleanup in patchoat.cc.

Bug: 22858531
Change-Id: I31b3ea2004ece6f6c853ee906074bb2792dee958
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index 7d2d899..723bb17 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -528,7 +528,6 @@
 
 void PatchOat::PatchClassTable(const ImageHeader* image_header) {
   const auto& section = image_header->GetImageSection(ImageHeader::kSectionClassTable);
-  // ClassTable temp_table;
   // Note that we require that ReadFromMemory does not make an internal copy of the elements.
   // This also relies on visit roots not doing any verification which could fail after we update
   // the roots to be the image addresses.
diff --git a/runtime/class_table.cc b/runtime/class_table.cc
index 4656b74..df2dbf4 100644
--- a/runtime/class_table.cc
+++ b/runtime/class_table.cc
@@ -149,17 +149,21 @@
 }
 
 size_t ClassTable::WriteToMemory(uint8_t* ptr) const {
-  size_t ret = 0;
-  for (const ClassSet& set : classes_) {
-    uint8_t* address = (ptr != nullptr) ? ptr + ret : nullptr;
-    ret += set.WriteToMemory(address);
-    // Sanity check 2.
-    if (kIsDebugBuild && ptr != nullptr) {
-      size_t read_count;
-      ClassSet class_set(ptr, /*make copy*/false, &read_count);
-      class_set.Verify();
+  ClassSet combined;
+  // Combine all the class sets in case there are multiple, also adjusts load factor back to
+  // default in case classes were pruned.
+  for (const ClassSet& class_set : classes_) {
+    for (const GcRoot<mirror::Class>& root : class_set) {
+      combined.Insert(root);
     }
   }
+  const size_t ret = combined.WriteToMemory(ptr);
+  // Sanity check.
+  if (kIsDebugBuild && ptr != nullptr) {
+    size_t read_count;
+    ClassSet class_set(ptr, /*make copy*/false, &read_count);
+    class_set.Verify();
+  }
   return ret;
 }
 
diff --git a/runtime/class_table.h b/runtime/class_table.h
index 219e2c6..c911365 100644
--- a/runtime/class_table.h
+++ b/runtime/class_table.h
@@ -104,6 +104,7 @@
       REQUIRES(Locks::classlinker_classes_lock_)
       SHARED_REQUIRES(Locks::mutator_lock_);
 
+  // Combines all of the tables into one class set.
   size_t WriteToMemory(uint8_t* ptr) const
       REQUIRES(Locks::classlinker_classes_lock_)
       SHARED_REQUIRES(Locks::mutator_lock_);