Create type lookup tables early.

This is a partial revert and cleanup of
    https://android-review.googlesource.com/1143022
to create the type lookup tables before compilation.
Creating them too late increased the compilation time.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: Manual, time dex2oat --compiler-filter=quicken.
Bug: 142680736
Bug: 29790079
Change-Id: Ied3f86a80b4f2aaacb5acc9716652f06bdc98c82
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 8c8bc4e..cd8f98d 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1585,6 +1585,21 @@
       key_value_store_->Put(OatHeader::kClassPathKey, class_path_key);
     }
 
+    // Now that we have finalized key_value_store_, start writing the .rodata section.
+    // Among other things, this creates type lookup tables that speed up the compilation.
+    {
+      TimingLogger::ScopedTiming t_dex("Starting .rodata", timings_);
+      rodata_.reserve(oat_writers_.size());
+      for (size_t i = 0, size = oat_writers_.size(); i != size; ++i) {
+        rodata_.push_back(elf_writers_[i]->StartRoData());
+        if (!oat_writers_[i]->StartRoData(dex_files_per_oat_file_[i],
+                                          rodata_.back(),
+                                          (i == 0u) ? key_value_store_.get() : nullptr)) {
+          return dex2oat::ReturnCode::kOther;
+        }
+      }
+    }
+
     // We had to postpone the swap decision till now, as this is the point when we actually
     // know about the dex files we're going to use.
 
@@ -1925,21 +1940,12 @@
       }
     }
 
-    // Initialize the writers with the compiler driver, image writer and their dex files
-    // and start writing the .rodata sections.
-    {
-      TimingLogger::ScopedTiming t2("dex2oat Starting oat .rodata section(s)", timings_);
-      rodata_.reserve(oat_writers_.size());
-      for (size_t i = 0, size = oat_files_.size(); i != size; ++i) {
-        rodata_.push_back(elf_writers_[i]->StartRoData());
-        if (!oat_writers_[i]->StartRoData(driver_.get(),
-                                          image_writer_.get(),
-                                          dex_files_per_oat_file_[i],
-                                          rodata_.back(),
-                                          (i == 0u) ? key_value_store_.get() : nullptr)) {
-          return false;
-        }
-      }
+    // Initialize the writers with the compiler driver, image writer, and their
+    // dex files. The writers were created without those being there yet.
+    for (size_t i = 0, size = oat_files_.size(); i != size; ++i) {
+      std::unique_ptr<linker::OatWriter>& oat_writer = oat_writers_[i];
+      std::vector<const DexFile*>& dex_files = dex_files_per_oat_file_[i];
+      oat_writer->Initialize(driver_.get(), image_writer_.get(), dex_files);
     }
 
     {
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index d1d22a5..053ad79 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -287,12 +287,11 @@
         OatWriter* const oat_writer = oat_writers[i].get();
         ElfWriter* const elf_writer = elf_writers[i].get();
         std::vector<const DexFile*> cur_dex_files(1u, class_path[i]);
-        bool initialize_ok = oat_writer->StartRoData(driver,
-                                                     writer.get(),
-                                                     cur_dex_files,
-                                                     rodata[i],
-                                                     (i == 0u) ? &key_value_store : nullptr);
-        ASSERT_TRUE(initialize_ok);
+        bool start_rodata_ok = oat_writer->StartRoData(cur_dex_files,
+                                                       rodata[i],
+                                                       (i == 0u) ? &key_value_store : nullptr);
+        ASSERT_TRUE(start_rodata_ok);
+        oat_writer->Initialize(driver, writer.get(), cur_dex_files);
 
         std::unique_ptr<BufferedOutputStream> vdex_out =
             std::make_unique<BufferedOutputStream>(
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 2c1837e..4183dd9 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -685,16 +685,10 @@
   return true;
 }
 
-// Initialize the writer with the given parameters.
-bool OatWriter::StartRoData(const CompilerDriver* compiler_driver,
-                            ImageWriter* image_writer,
-                            const std::vector<const DexFile*>& dex_files,
+bool OatWriter::StartRoData(const std::vector<const DexFile*>& dex_files,
                             OutputStream* oat_rodata,
                             SafeMap<std::string, std::string>* key_value_store) {
   CHECK(write_state_ == WriteState::kStartRoData);
-  compiler_driver_ = compiler_driver;
-  image_writer_ = image_writer;
-  dex_files_ = &dex_files;
 
   // Record the ELF rodata section offset, i.e. the beginning of the OAT data.
   if (!RecordOatDataOffset(oat_rodata)) {
@@ -720,10 +714,21 @@
     return false;
   }
 
-  write_state_ = WriteState::kPrepareLayout;
+  write_state_ = WriteState::kInitialize;
   return true;
 }
 
+// Initialize the writer with the given parameters.
+void OatWriter::Initialize(const CompilerDriver* compiler_driver,
+                           ImageWriter* image_writer,
+                           const std::vector<const DexFile*>& dex_files) {
+  CHECK(write_state_ == WriteState::kInitialize);
+  compiler_driver_ = compiler_driver;
+  image_writer_ = image_writer;
+  dex_files_ = &dex_files;
+  write_state_ = WriteState::kPrepareLayout;
+}
+
 void OatWriter::PrepareLayout(MultiOatRelativePatcher* relative_patcher) {
   CHECK(write_state_ == WriteState::kPrepareLayout);
 
@@ -3801,6 +3806,8 @@
 
     // Create the lookup table. When `nullptr` is given as the storage buffer,
     // TypeLookupTable allocates its own and OatDexFile takes ownership.
+    // TODO: Create the table in an mmap()ed region of the output file to reduce dirty memory.
+    // (We used to do that when dex files were still copied into the oat file.)
     const DexFile& dex_file = *opened_dex_files[i];
     {
       TypeLookupTable type_lookup_table = TypeLookupTable::Create(dex_file);
@@ -3853,9 +3860,8 @@
   return true;
 }
 
-bool OatWriter::WriteDexLayoutSections(
-    OutputStream* oat_rodata,
-    const std::vector<const DexFile*>& opened_dex_files) {
+bool OatWriter::WriteDexLayoutSections(OutputStream* oat_rodata,
+                                       const std::vector<const DexFile*>& opened_dex_files) {
   TimingLogger::ScopedTiming split(__FUNCTION__, timings_);
 
   if (!kWriteDexLayoutInfo) {
diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h
index c95b4dd..fb263d9 100644
--- a/dex2oat/linker/oat_writer.h
+++ b/dex2oat/linker/oat_writer.h
@@ -177,13 +177,14 @@
                             CopyOption copy_dex_files,
                             /*out*/ std::vector<MemMap>* opened_dex_files_map,
                             /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files);
-  // Initialize the writer with the given parameters and start writing .rodata.
-  // Supporting data structures for dex files are written into the .rodata section of the oat file.
-  bool StartRoData(const CompilerDriver* compiler_driver,
-                   ImageWriter* image_writer,
-                   const std::vector<const DexFile*>& dex_files,
+  // Start writing .rodata, including supporting data structures for dex files.
+  bool StartRoData(const std::vector<const DexFile*>& dex_files,
                    OutputStream* oat_rodata,
                    SafeMap<std::string, std::string>* key_value_store);
+  // Initialize the writer with the given parameters.
+  void Initialize(const CompilerDriver* compiler_driver,
+                  ImageWriter* image_writer,
+                  const std::vector<const DexFile*>& dex_files);
   bool WriteQuickeningInfo(OutputStream* vdex_out);
   bool WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps);
   bool WriteChecksumsAndVdexHeader(OutputStream* vdex_out);
@@ -356,6 +357,7 @@
   enum class WriteState {
     kAddingDexFileSources,
     kStartRoData,
+    kInitialize,
     kPrepareLayout,
     kWriteRoData,
     kWriteText,
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index 0a92baf..2eb4476 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -197,13 +197,10 @@
     MultiOatRelativePatcher patcher(compiler_options_->GetInstructionSet(),
                                     compiler_options_->GetInstructionSetFeatures(),
                                     compiler_driver_->GetCompiledMethodStorage());
-    if (!oat_writer.StartRoData(compiler_driver_.get(),
-                                /*image_writer=*/ nullptr,
-                                dex_files,
-                                oat_rodata,
-                                &key_value_store)) {
+    if (!oat_writer.StartRoData(dex_files, oat_rodata, &key_value_store)) {
       return false;
     }
+    oat_writer.Initialize(compiler_driver_.get(), /*image_writer=*/ nullptr, dex_files);
     oat_writer.PrepareLayout(&patcher);
     elf_writer->PrepareDynamicSection(oat_writer.GetOatHeader().GetExecutableOffset(),
                                       oat_writer.GetCodeSize(),