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(),