diff options
author | Brian Carlstrom <bdc@google.com> | 2013-07-23 22:35:16 -0700 |
---|---|---|
committer | Brian Carlstrom <bdc@google.com> | 2013-07-24 09:19:30 -0700 |
commit | c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899 (patch) | |
tree | 4273347ed7aa19c6edbe70e986f588007ec8f5e0 | |
parent | a3d6b8cb884fce2fe34258e9d582b11ea9545fd9 (diff) | |
download | art-c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899.zip art-c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899.tar.gz art-c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899.tar.bz2 |
Remove OatWriter buffering to memory for ElfWriterQuick
This allows the oat contents to be directly written to the file.
Change-Id: Ibc7ddf57477b152f07784b52f7334be73fd22833
-rw-r--r-- | compiler/driver/compiler_driver.cc | 6 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 3 | ||||
-rw-r--r-- | compiler/elf_writer.h | 3 | ||||
-rw-r--r-- | compiler/elf_writer_mclinker.cc | 15 | ||||
-rw-r--r-- | compiler/elf_writer_mclinker.h | 4 | ||||
-rw-r--r-- | compiler/elf_writer_quick.cc | 23 | ||||
-rw-r--r-- | compiler/elf_writer_quick.h | 4 | ||||
-rw-r--r-- | compiler/image_writer.cc | 4 | ||||
-rw-r--r-- | compiler/oat_writer.cc | 215 | ||||
-rw-r--r-- | compiler/oat_writer.h | 51 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 27 | ||||
-rw-r--r-- | runtime/image_test.cc | 20 | ||||
-rw-r--r-- | runtime/oat_test.cc | 26 |
13 files changed, 211 insertions, 190 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 1f66730..ea2291c 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -2343,13 +2343,13 @@ bool CompilerDriver::RequiresConstructorBarrier(Thread* self, const DexFile* dex bool CompilerDriver::WriteElf(const std::string& android_root, bool is_host, const std::vector<const art::DexFile*>& dex_files, - std::vector<uint8_t>& oat_contents, + OatWriter& oat_writer, art::File* file) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { #if defined(ART_USE_PORTABLE_COMPILER) - return art::ElfWriterMclinker::Create(file, oat_contents, dex_files, android_root, is_host, *this); + return art::ElfWriterMclinker::Create(file, oat_writer, dex_files, android_root, is_host, *this); #else - return art::ElfWriterQuick::Create(file, oat_contents, dex_files, android_root, is_host, *this); + return art::ElfWriterQuick::Create(file, oat_writer, dex_files, android_root, is_host, *this); #endif } void CompilerDriver::InstructionSetToLLVMTarget(InstructionSet instruction_set, diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 1799057..f3f72dd 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -39,6 +39,7 @@ namespace art { class AOTCompilationStats; class ParallelCompilationManager; class DexCompilationUnit; +class OatWriter; class TimingLogger; enum CompilerBackend { @@ -192,7 +193,7 @@ class CompilerDriver { bool WriteElf(const std::string& android_root, bool is_host, const std::vector<const DexFile*>& dex_files, - std::vector<uint8_t>& oat_contents, + OatWriter& oat_writer, File* file); // TODO: move to a common home for llvm helpers once quick/portable are merged diff --git a/compiler/elf_writer.h b/compiler/elf_writer.h index 0dfce6e..0ef4185 100644 --- a/compiler/elf_writer.h +++ b/compiler/elf_writer.h @@ -33,6 +33,7 @@ namespace art { class CompilerDriver; class DexFile; class ElfFile; +class OatWriter; class ElfWriter { public: @@ -49,7 +50,7 @@ class ElfWriter { ElfWriter(const CompilerDriver& driver, File* elf_file); virtual ~ElfWriter(); - virtual bool Write(std::vector<uint8_t>& oat_contents, + virtual bool Write(OatWriter& oat_writer, const std::vector<const DexFile*>& dex_files, const std::string& android_root, bool is_host) diff --git a/compiler/elf_writer_mclinker.cc b/compiler/elf_writer_mclinker.cc index 05f3b02..2a9bc35 100644 --- a/compiler/elf_writer_mclinker.cc +++ b/compiler/elf_writer_mclinker.cc @@ -36,7 +36,9 @@ #include "mirror/abstract_method.h" #include "mirror/abstract_method-inl.h" #include "mirror/object-inl.h" +#include "oat_writer.h" #include "scoped_thread_state_change.h" +#include "vector_output_stream.h" namespace art { @@ -46,19 +48,25 @@ ElfWriterMclinker::ElfWriterMclinker(const CompilerDriver& driver, File* elf_fil ElfWriterMclinker::~ElfWriterMclinker() {} bool ElfWriterMclinker::Create(File* elf_file, - std::vector<uint8_t>& oat_contents, + OatWriter& oat_writer, const std::vector<const DexFile*>& dex_files, const std::string& android_root, bool is_host, const CompilerDriver& driver) { ElfWriterMclinker elf_writer(driver, elf_file); - return elf_writer.Write(oat_contents, dex_files, android_root, is_host); + return elf_writer.Write(oat_writer, dex_files, android_root, is_host); } -bool ElfWriterMclinker::Write(std::vector<uint8_t>& oat_contents, +bool ElfWriterMclinker::Write(OatWriter& oat_writer, const std::vector<const DexFile*>& dex_files, const std::string& android_root, bool is_host) { + std::vector<uint8_t> oat_contents; + oat_contents.reserve(oat_writer.GetSize()); + VectorOutputStream output_stream("oat contents", oat_contents); + CHECK(oat_writer.Write(output_stream)); + CHECK_EQ(oat_writer.GetSize(), oat_contents.size()); + Init(); AddOatInput(oat_contents); #if defined(ART_USE_PORTABLE_COMPILER) @@ -68,6 +76,7 @@ bool ElfWriterMclinker::Write(std::vector<uint8_t>& oat_contents, if (!Link()) { return false; } + oat_contents.clear(); #if defined(ART_USE_PORTABLE_COMPILER) FixupOatMethodOffsets(dex_files); #endif diff --git a/compiler/elf_writer_mclinker.h b/compiler/elf_writer_mclinker.h index 3b33bc4..bdadf8f 100644 --- a/compiler/elf_writer_mclinker.h +++ b/compiler/elf_writer_mclinker.h @@ -40,7 +40,7 @@ class ElfWriterMclinker : public ElfWriter { public: // Write an ELF file. Returns true on success, false on failure. static bool Create(File* file, - std::vector<uint8_t>& oat_contents, + OatWriter& oat_writer, const std::vector<const DexFile*>& dex_files, const std::string& android_root, bool is_host, @@ -48,7 +48,7 @@ class ElfWriterMclinker : public ElfWriter { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); protected: - virtual bool Write(std::vector<uint8_t>& oat_contents, + virtual bool Write(OatWriter& oat_writer, const std::vector<const DexFile*>& dex_files, const std::string& android_root, bool is_host) diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc index 9de96d2..f2db5d8 100644 --- a/compiler/elf_writer_quick.cc +++ b/compiler/elf_writer_quick.cc @@ -19,8 +19,10 @@ #include "base/logging.h" #include "base/unix_file/fd_file.h" #include "driver/compiler_driver.h" +#include "file_output_stream.h" #include "globals.h" #include "oat.h" +#include "oat_writer.h" #include "utils.h" namespace art { @@ -31,16 +33,16 @@ ElfWriterQuick::ElfWriterQuick(const CompilerDriver& driver, File* elf_file) ElfWriterQuick::~ElfWriterQuick() {} bool ElfWriterQuick::Create(File* elf_file, - std::vector<uint8_t>& oat_contents, + OatWriter& oat_writer, const std::vector<const DexFile*>& dex_files, const std::string& android_root, bool is_host, const CompilerDriver& driver) { ElfWriterQuick elf_writer(driver, elf_file); - return elf_writer.Write(oat_contents, dex_files, android_root, is_host); + return elf_writer.Write(oat_writer, dex_files, android_root, is_host); } -bool ElfWriterQuick::Write(std::vector<uint8_t>& oat_contents, +bool ElfWriterQuick::Write(OatWriter& oat_writer, const std::vector<const DexFile*>& dex_files_unused, const std::string& android_root_unused, bool is_host_unused) { @@ -193,9 +195,9 @@ bool ElfWriterQuick::Write(std::vector<uint8_t>& oat_contents, // .rodata uint32_t oat_data_alignment = kPageSize; uint32_t oat_data_offset = expected_offset = RoundUp(expected_offset, oat_data_alignment); - const OatHeader* oat_header = reinterpret_cast<OatHeader*>(&oat_contents[0]); - CHECK(oat_header->IsValid()); - uint32_t oat_data_size = oat_header->GetExecutableOffset(); + const OatHeader& oat_header = oat_writer.GetOatHeader(); + CHECK(oat_header.IsValid()); + uint32_t oat_data_size = oat_header.GetExecutableOffset(); expected_offset += oat_data_size; if (debug) { LOG(INFO) << "oat_data_offset=" << oat_data_offset << std::hex << " " << oat_data_offset; @@ -206,9 +208,9 @@ bool ElfWriterQuick::Write(std::vector<uint8_t>& oat_contents, uint32_t oat_exec_alignment = kPageSize; CHECK_ALIGNED(expected_offset, kPageSize); uint32_t oat_exec_offset = expected_offset = RoundUp(expected_offset, oat_exec_alignment); - uint32_t oat_exec_size = oat_contents.size() - oat_data_size; + uint32_t oat_exec_size = oat_writer.GetSize() - oat_data_size; expected_offset += oat_exec_size; - CHECK_EQ(oat_data_offset + oat_contents.size(), expected_offset); + CHECK_EQ(oat_data_offset + oat_writer.GetSize(), expected_offset); if (debug) { LOG(INFO) << "oat_exec_offset=" << oat_exec_offset << std::hex << " " << oat_exec_offset; LOG(INFO) << "oat_exec_size=" << oat_exec_size << std::hex << " " << oat_exec_size; @@ -617,13 +619,14 @@ bool ElfWriterQuick::Write(std::vector<uint8_t>& oat_contents, << " for " << elf_file_->GetPath(); return false; } - if (!elf_file_->WriteFully(&oat_contents[0], oat_contents.size())) { + FileOutputStream output_stream(elf_file_); + if (!oat_writer.Write(output_stream)) { PLOG(ERROR) << "Failed to write .rodata and .text for " << elf_file_->GetPath(); return false; } // .dynamic - DCHECK_LE(oat_data_offset + oat_contents.size(), dynamic_offset); + DCHECK_LE(oat_data_offset + oat_writer.GetSize(), dynamic_offset); if (static_cast<off_t>(dynamic_offset) != lseek(elf_file_->Fd(), dynamic_offset, SEEK_SET)) { PLOG(ERROR) << "Failed to seek to .dynamic offset " << dynamic_offset << " for " << elf_file_->GetPath(); diff --git a/compiler/elf_writer_quick.h b/compiler/elf_writer_quick.h index a15c239..f36d06f 100644 --- a/compiler/elf_writer_quick.h +++ b/compiler/elf_writer_quick.h @@ -25,7 +25,7 @@ class ElfWriterQuick : public ElfWriter { public: // Write an ELF file. Returns true on success, false on failure. static bool Create(File* file, - std::vector<uint8_t>& oat_contents, + OatWriter& oat_writer, const std::vector<const DexFile*>& dex_files, const std::string& android_root, bool is_host, @@ -33,7 +33,7 @@ class ElfWriterQuick : public ElfWriter { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); protected: - virtual bool Write(std::vector<uint8_t>& oat_contents, + virtual bool Write(OatWriter& oat_writer, const std::vector<const DexFile*>& dex_files, const std::string& android_root, bool is_host) diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index f395428..1612f7e 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -85,6 +85,10 @@ bool ImageWriter::Write(const std::string& image_filename, return false; } oat_file_ = OatFile::OpenWritable(oat_file.get(), oat_location); + if (oat_file_ == NULL) { + LOG(ERROR) << "Failed to open writable oat file " << oat_filename << " for " << oat_location; + return false; + } class_linker->RegisterOatFile(*oat_file_); interpreter_to_interpreter_entry_offset_ = oat_file_->GetOatHeader().GetInterpreterToInterpreterEntryOffset(); interpreter_to_quick_entry_offset_ = oat_file_->GetOatHeader().GetInterpreterToQuickEntryOffset(); diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index da05c49..5eb837b 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -35,20 +35,6 @@ namespace art { -bool OatWriter::Create(OutputStream& output_stream, - const std::vector<const DexFile*>& dex_files, - uint32_t image_file_location_oat_checksum, - uint32_t image_file_location_oat_begin, - const std::string& image_file_location, - const CompilerDriver& driver) { - OatWriter oat_writer(dex_files, - image_file_location_oat_checksum, - image_file_location_oat_begin, - image_file_location, - &driver); - return oat_writer.Write(output_stream); -} - OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, uint32_t image_file_location_oat_checksum, uint32_t image_file_location_oat_begin, @@ -89,6 +75,7 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, offset = InitOatClasses(offset); offset = InitOatCode(offset); offset = InitOatCodeDexFiles(offset); + size_ = offset; CHECK_EQ(dex_files_->size(), oat_dex_files_.size()); CHECK(image_file_location.empty() == compiler->IsImage()); @@ -190,7 +177,8 @@ size_t OatWriter::InitOatCode(size_t offset) { if (compiler_driver_->IsImage()) { InstructionSet instruction_set = compiler_driver_->GetInstructionSet(); oat_header_->SetInterpreterToInterpreterEntryOffset(offset); - interpreter_to_interpreter_entry_.reset(compiler_driver_->CreateInterpreterToInterpreterEntry()); + interpreter_to_interpreter_entry_.reset( + compiler_driver_->CreateInterpreterToInterpreterEntry()); offset += interpreter_to_interpreter_entry_->size(); offset = CompiledCode::AlignCode(offset, instruction_set); @@ -336,7 +324,8 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, mapping_table_offset = (mapping_table_size == 0) ? 0 : offset; // Deduplicate mapping tables - SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table); + SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = + mapping_table_offsets_.find(&mapping_table); if (mapping_iter != mapping_table_offsets_.end()) { mapping_table_offset = mapping_iter->second; } else { @@ -350,7 +339,8 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, vmap_table_offset = (vmap_table_size == 0) ? 0 : offset; // Deduplicate vmap tables - SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table); + SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = + vmap_table_offsets_.find(&vmap_table); if (vmap_iter != vmap_table_offsets_.end()) { vmap_table_offset = vmap_iter->second; } else { @@ -382,7 +372,8 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, #endif // Deduplicate GC maps - SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map); + SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = + gc_map_offsets_.find(&gc_map); if (gc_map_iter != gc_map_offsets_.end()) { gc_map_offset = gc_map_iter->second; } else { @@ -392,14 +383,14 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, } } - oat_class->method_offsets_[class_def_method_index] - = OatMethodOffsets(code_offset, - frame_size_in_bytes, - core_spill_mask, - fp_spill_mask, - mapping_table_offset, - vmap_table_offset, - gc_map_offset); + oat_class->method_offsets_[class_def_method_index] = + OatMethodOffsets(code_offset, + frame_size_in_bytes, + core_spill_mask, + fp_spill_mask, + mapping_table_offset, + vmap_table_offset, + gc_map_offset); if (compiler_driver_->IsImage()) { ClassLinker* linker = Runtime::Current()->GetClassLinker(); @@ -428,12 +419,16 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, } #define DCHECK_OFFSET() \ - DCHECK_EQ(static_cast<off_t>(offset), out.Seek(0, kSeekCurrent)) + DCHECK_EQ(static_cast<off_t>(file_offset + relative_offset), out.Seek(0, kSeekCurrent)) \ + << "file_offset=" << file_offset << " relative_offset=" << relative_offset #define DCHECK_OFFSET_() \ - DCHECK_EQ(static_cast<off_t>(offset_), out.Seek(0, kSeekCurrent)) + DCHECK_EQ(static_cast<off_t>(file_offset + offset_), out.Seek(0, kSeekCurrent)) \ + << "file_offset=" << file_offset << " offset_=" << offset_ bool OatWriter::Write(OutputStream& out) { + const size_t file_offset = out.Seek(0, kSeekCurrent); + if (!out.WriteFully(oat_header_, sizeof(*oat_header_))) { PLOG(ERROR) << "Failed to write oat header to " << out.GetLocation(); return false; @@ -446,19 +441,19 @@ bool OatWriter::Write(OutputStream& out) { } size_oat_header_image_file_location_ += image_file_location_.size(); - if (!WriteTables(out)) { + if (!WriteTables(out, file_offset)) { LOG(ERROR) << "Failed to write oat tables to " << out.GetLocation(); return false; } - size_t code_offset = WriteCode(out); - if (code_offset == 0) { + size_t relative_offset = WriteCode(out, file_offset); + if (relative_offset == 0) { LOG(ERROR) << "Failed to write oat code to " << out.GetLocation(); return false; } - code_offset = WriteCodeDexFiles(out, code_offset); - if (code_offset == 0) { + relative_offset = WriteCodeDexFiles(out, file_offset, relative_offset); + if (relative_offset == 0) { LOG(ERROR) << "Failed to write oat code for dex files to " << out.GetLocation(); return false; } @@ -495,21 +490,25 @@ bool OatWriter::Write(OutputStream& out) { #undef DO_STAT LOG(INFO) << "size_total=" << PrettySize(size_total) << " (" << size_total << "B)"; \ - CHECK_EQ(size_total, static_cast<uint32_t>(out.Seek(0, kSeekCurrent))); + CHECK_EQ(file_offset + size_total, static_cast<uint32_t>(out.Seek(0, kSeekCurrent))); + CHECK_EQ(size_, size_total); } + CHECK_EQ(file_offset + size_, static_cast<uint32_t>(out.Seek(0, kSeekCurrent))); + CHECK_EQ(size_, relative_offset); + return true; } -bool OatWriter::WriteTables(OutputStream& out) { +bool OatWriter::WriteTables(OutputStream& out, const size_t file_offset) { for (size_t i = 0; i != oat_dex_files_.size(); ++i) { - if (!oat_dex_files_[i]->Write(this, out)) { + if (!oat_dex_files_[i]->Write(this, out, file_offset)) { PLOG(ERROR) << "Failed to write oat dex information to " << out.GetLocation(); return false; } } for (size_t i = 0; i != oat_dex_files_.size(); ++i) { - uint32_t expected_offset = oat_dex_files_[i]->dex_file_offset_; + uint32_t expected_offset = file_offset + oat_dex_files_[i]->dex_file_offset_; off_t actual_offset = out.Seek(expected_offset, kSeekSet); if (static_cast<uint32_t>(actual_offset) != expected_offset) { const DexFile* dex_file = (*dex_files_)[i]; @@ -519,13 +518,14 @@ bool OatWriter::WriteTables(OutputStream& out) { } const DexFile* dex_file = (*dex_files_)[i]; if (!out.WriteFully(&dex_file->GetHeader(), dex_file->GetHeader().file_size_)) { - PLOG(ERROR) << "Failed to write dex file " << dex_file->GetLocation() << " to " << out.GetLocation(); + PLOG(ERROR) << "Failed to write dex file " << dex_file->GetLocation() + << " to " << out.GetLocation(); return false; } size_dex_file_ += dex_file->GetHeader().file_size_; } for (size_t i = 0; i != oat_classes_.size(); ++i) { - if (!oat_classes_[i]->Write(this, out)) { + if (!oat_classes_[i]->Write(this, out, file_offset)) { PLOG(ERROR) << "Failed to write oat methods information to " << out.GetLocation(); return false; } @@ -533,27 +533,29 @@ bool OatWriter::WriteTables(OutputStream& out) { return true; } -size_t OatWriter::WriteCode(OutputStream& out) { - uint32_t offset = oat_header_->GetExecutableOffset(); +size_t OatWriter::WriteCode(OutputStream& out, const size_t file_offset) { + size_t relative_offset = oat_header_->GetExecutableOffset(); off_t new_offset = out.Seek(size_executable_offset_alignment_, kSeekCurrent); - if (static_cast<uint32_t>(new_offset) != offset) { + size_t expected_file_offset = file_offset + relative_offset; + if (static_cast<uint32_t>(new_offset) != expected_file_offset) { PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset - << " Expected: " << offset << " File: " << out.GetLocation(); + << " Expected: " << expected_file_offset << " File: " << out.GetLocation(); return 0; } DCHECK_OFFSET(); if (compiler_driver_->IsImage()) { InstructionSet instruction_set = compiler_driver_->GetInstructionSet(); - if (!out.WriteFully(&(*interpreter_to_interpreter_entry_)[0], interpreter_to_interpreter_entry_->size())) { + if (!out.WriteFully(&(*interpreter_to_interpreter_entry_)[0], + interpreter_to_interpreter_entry_->size())) { PLOG(ERROR) << "Failed to write interpreter to interpreter entry to " << out.GetLocation(); return false; } size_interpreter_to_interpreter_entry_ += interpreter_to_interpreter_entry_->size(); - offset += interpreter_to_interpreter_entry_->size(); + relative_offset += interpreter_to_interpreter_entry_->size(); DCHECK_OFFSET(); - uint32_t aligned_offset = CompiledCode::AlignCode(offset, instruction_set); - uint32_t alignment_padding = aligned_offset - offset; + uint32_t aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set); + uint32_t alignment_padding = aligned_offset - relative_offset; out.Seek(alignment_padding, kSeekCurrent); size_stubs_alignment_ += alignment_padding; if (!out.WriteFully(&(*interpreter_to_quick_entry_)[0], interpreter_to_quick_entry_->size())) { @@ -561,60 +563,67 @@ size_t OatWriter::WriteCode(OutputStream& out) { return false; } size_interpreter_to_quick_entry_ += interpreter_to_quick_entry_->size(); - offset += alignment_padding + interpreter_to_quick_entry_->size(); + relative_offset += alignment_padding + interpreter_to_quick_entry_->size(); DCHECK_OFFSET(); - aligned_offset = CompiledCode::AlignCode(offset, instruction_set); - alignment_padding = aligned_offset - offset; + aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set); + alignment_padding = aligned_offset - relative_offset; out.Seek(alignment_padding, kSeekCurrent); size_stubs_alignment_ += alignment_padding; - if (!out.WriteFully(&(*portable_resolution_trampoline_)[0], portable_resolution_trampoline_->size())) { + if (!out.WriteFully(&(*portable_resolution_trampoline_)[0], + portable_resolution_trampoline_->size())) { PLOG(ERROR) << "Failed to write portable resolution trampoline to " << out.GetLocation(); return false; } size_portable_resolution_trampoline_ += portable_resolution_trampoline_->size(); - offset += alignment_padding + portable_resolution_trampoline_->size(); + relative_offset += alignment_padding + portable_resolution_trampoline_->size(); DCHECK_OFFSET(); - aligned_offset = CompiledCode::AlignCode(offset, instruction_set); - alignment_padding = aligned_offset - offset; + aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set); + alignment_padding = aligned_offset - relative_offset; out.Seek(alignment_padding, kSeekCurrent); size_stubs_alignment_ += alignment_padding; - if (!out.WriteFully(&(*quick_resolution_trampoline_)[0], quick_resolution_trampoline_->size())) { + if (!out.WriteFully(&(*quick_resolution_trampoline_)[0], + quick_resolution_trampoline_->size())) { PLOG(ERROR) << "Failed to write quick resolution trampoline to " << out.GetLocation(); return false; } size_quick_resolution_trampoline_ += quick_resolution_trampoline_->size(); - offset += alignment_padding + quick_resolution_trampoline_->size(); + relative_offset += alignment_padding + quick_resolution_trampoline_->size(); DCHECK_OFFSET(); } - return offset; + return relative_offset; } -size_t OatWriter::WriteCodeDexFiles(OutputStream& out, size_t code_offset) { +size_t OatWriter::WriteCodeDexFiles(OutputStream& out, + const size_t file_offset, + size_t relative_offset) { size_t oat_class_index = 0; for (size_t i = 0; i != oat_dex_files_.size(); ++i) { const DexFile* dex_file = (*dex_files_)[i]; CHECK(dex_file != NULL); - code_offset = WriteCodeDexFile(out, code_offset, oat_class_index, *dex_file); - if (code_offset == 0) { + relative_offset = WriteCodeDexFile(out, file_offset, relative_offset, oat_class_index, + *dex_file); + if (relative_offset == 0) { return 0; } } - return code_offset; + return relative_offset; } -size_t OatWriter::WriteCodeDexFile(OutputStream& out, size_t code_offset, size_t& oat_class_index, +size_t OatWriter::WriteCodeDexFile(OutputStream& out, const size_t file_offset, + size_t relative_offset, size_t& oat_class_index, const DexFile& dex_file) { for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++, oat_class_index++) { const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); - code_offset = WriteCodeClassDef(out, code_offset, oat_class_index, dex_file, class_def); - if (code_offset == 0) { + relative_offset = WriteCodeClassDef(out, file_offset, relative_offset, oat_class_index, + dex_file, class_def); + if (relative_offset == 0) { return 0; } } - return code_offset; + return relative_offset; } void OatWriter::ReportWriteFailure(const char* what, uint32_t method_idx, @@ -624,13 +633,15 @@ void OatWriter::ReportWriteFailure(const char* what, uint32_t method_idx, } size_t OatWriter::WriteCodeClassDef(OutputStream& out, - size_t code_offset, size_t oat_class_index, + const size_t file_offset, + size_t relative_offset, + size_t oat_class_index, const DexFile& dex_file, const DexFile::ClassDef& class_def) { const byte* class_data = dex_file.GetClassData(class_def); if (class_data == NULL) { // ie. an empty class such as a marker interface - return code_offset; + return relative_offset; } ClassDataItemIterator it(dex_file, class_data); // Skip fields @@ -644,27 +655,29 @@ size_t OatWriter::WriteCodeClassDef(OutputStream& out, size_t class_def_method_index = 0; while (it.HasNextDirectMethod()) { bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0; - code_offset = WriteCodeMethod(out, code_offset, oat_class_index, class_def_method_index, - is_static, it.GetMemberIndex(), dex_file); - if (code_offset == 0) { + relative_offset = WriteCodeMethod(out, file_offset, relative_offset, oat_class_index, + class_def_method_index, is_static, it.GetMemberIndex(), + dex_file); + if (relative_offset == 0) { return 0; } class_def_method_index++; it.Next(); } while (it.HasNextVirtualMethod()) { - code_offset = WriteCodeMethod(out, code_offset, oat_class_index, class_def_method_index, - false, it.GetMemberIndex(), dex_file); - if (code_offset == 0) { + relative_offset = WriteCodeMethod(out, file_offset, relative_offset, oat_class_index, + class_def_method_index, false, it.GetMemberIndex(), dex_file); + if (relative_offset == 0) { return 0; } class_def_method_index++; it.Next(); } - return code_offset; + return relative_offset; } -size_t OatWriter::WriteCodeMethod(OutputStream& out, size_t offset, size_t oat_class_index, +size_t OatWriter::WriteCodeMethod(OutputStream& out, const size_t file_offset, + size_t relative_offset, size_t oat_class_index, size_t class_def_method_index, bool is_static, uint32_t method_idx, const DexFile& dex_file) { const CompiledMethod* compiled_method = @@ -676,26 +689,27 @@ size_t OatWriter::WriteCodeMethod(OutputStream& out, size_t offset, size_t oat_c if (compiled_method != NULL) { // ie. not an abstract method #if !defined(ART_USE_PORTABLE_COMPILER) - uint32_t aligned_offset = compiled_method->AlignCode(offset); - uint32_t aligned_code_delta = aligned_offset - offset; + uint32_t aligned_offset = compiled_method->AlignCode(relative_offset); + uint32_t aligned_code_delta = aligned_offset - relative_offset; if (aligned_code_delta != 0) { off_t new_offset = out.Seek(aligned_code_delta, kSeekCurrent); size_code_alignment_ += aligned_code_delta; - if (static_cast<uint32_t>(new_offset) != aligned_offset) { + uint32_t expected_offset = file_offset + aligned_offset; + if (static_cast<uint32_t>(new_offset) != expected_offset) { PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset - << " Expected: " << aligned_offset << " File: " << out.GetLocation(); + << " Expected: " << expected_offset << " File: " << out.GetLocation(); return 0; } - offset += aligned_code_delta; + relative_offset += aligned_code_delta; DCHECK_OFFSET(); } - DCHECK_ALIGNED(offset, kArmAlignment); + DCHECK_ALIGNED(relative_offset, kArmAlignment); const std::vector<uint8_t>& code = compiled_method->GetCode(); uint32_t code_size = code.size() * sizeof(code[0]); CHECK_NE(code_size, 0U); // Deduplicate code arrays - size_t code_offset = offset + sizeof(code_size) + compiled_method->CodeDelta(); + size_t code_offset = relative_offset + sizeof(code_size) + compiled_method->CodeDelta(); SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code); if (code_iter != code_offsets_.end() && code_offset != method_offsets.code_offset_) { DCHECK(code_iter->second == method_offsets.code_offset_) @@ -707,14 +721,14 @@ size_t OatWriter::WriteCodeMethod(OutputStream& out, size_t offset, size_t oat_c return 0; } size_code_size_ += sizeof(code_size); - offset += sizeof(code_size); + relative_offset += sizeof(code_size); DCHECK_OFFSET(); if (!out.WriteFully(&code[0], code_size)) { ReportWriteFailure("method code", method_idx, dex_file, out); return 0; } size_code_ += code_size; - offset += code_size; + relative_offset += code_size; } DCHECK_OFFSET(); #endif @@ -726,20 +740,20 @@ size_t OatWriter::WriteCodeMethod(OutputStream& out, size_t offset, size_t oat_c SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table); if (mapping_iter != mapping_table_offsets_.end() && - offset != method_offsets.mapping_table_offset_) { + relative_offset != method_offsets.mapping_table_offset_) { DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0) || mapping_iter->second == method_offsets.mapping_table_offset_) << PrettyMethod(method_idx, dex_file); } else { DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0) - || offset == method_offsets.mapping_table_offset_) + || relative_offset == method_offsets.mapping_table_offset_) << PrettyMethod(method_idx, dex_file); if (!out.WriteFully(&mapping_table[0], mapping_table_size)) { ReportWriteFailure("mapping table", method_idx, dex_file, out); return 0; } size_mapping_table_ += mapping_table_size; - offset += mapping_table_size; + relative_offset += mapping_table_size; } DCHECK_OFFSET(); @@ -750,20 +764,20 @@ size_t OatWriter::WriteCodeMethod(OutputStream& out, size_t offset, size_t oat_c SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table); if (vmap_iter != vmap_table_offsets_.end() && - offset != method_offsets.vmap_table_offset_) { + relative_offset != method_offsets.vmap_table_offset_) { DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0) || vmap_iter->second == method_offsets.vmap_table_offset_) << PrettyMethod(method_idx, dex_file); } else { DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0) - || offset == method_offsets.vmap_table_offset_) + || relative_offset == method_offsets.vmap_table_offset_) << PrettyMethod(method_idx, dex_file); if (!out.WriteFully(&vmap_table[0], vmap_table_size)) { ReportWriteFailure("vmap table", method_idx, dex_file, out); return 0; } size_vmap_table_ += vmap_table_size; - offset += vmap_table_size; + relative_offset += vmap_table_size; } DCHECK_OFFSET(); @@ -774,25 +788,25 @@ size_t OatWriter::WriteCodeMethod(OutputStream& out, size_t offset, size_t oat_c SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map); if (gc_map_iter != gc_map_offsets_.end() && - offset != method_offsets.gc_map_offset_) { + relative_offset != method_offsets.gc_map_offset_) { DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0) || gc_map_iter->second == method_offsets.gc_map_offset_) << PrettyMethod(method_idx, dex_file); } else { DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0) - || offset == method_offsets.gc_map_offset_) + || relative_offset == method_offsets.gc_map_offset_) << PrettyMethod(method_idx, dex_file); if (!out.WriteFully(&gc_map[0], gc_map_size)) { ReportWriteFailure("GC map", method_idx, dex_file, out); return 0; } size_gc_map_ += gc_map_size; - offset += gc_map_size; + relative_offset += gc_map_size; } DCHECK_OFFSET(); } - return offset; + return relative_offset; } OatWriter::OatDexFile::OatDexFile(size_t offset, const DexFile& dex_file) { @@ -822,7 +836,9 @@ void OatWriter::OatDexFile::UpdateChecksum(OatHeader& oat_header) const { sizeof(methods_offsets_[0]) * methods_offsets_.size()); } -bool OatWriter::OatDexFile::Write(OatWriter* oat_writer, OutputStream& out) const { +bool OatWriter::OatDexFile::Write(OatWriter* oat_writer, + OutputStream& out, + const size_t file_offset) const { DCHECK_OFFSET_(); if (!out.WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) { PLOG(ERROR) << "Failed to write dex file location length to " << out.GetLocation(); @@ -881,14 +897,16 @@ void OatWriter::OatClass::UpdateChecksum(OatHeader& oat_header) const { sizeof(method_offsets_[0]) * method_offsets_.size()); } -bool OatWriter::OatClass::Write(OatWriter* oat_writer, OutputStream& out) const { +bool OatWriter::OatClass::Write(OatWriter* oat_writer, + OutputStream& out, + const size_t file_offset) const { DCHECK_OFFSET_(); if (!out.WriteFully(&status_, sizeof(status_))) { PLOG(ERROR) << "Failed to write class status to " << out.GetLocation(); return false; } oat_writer->size_oat_class_status_ += sizeof(status_); - DCHECK_EQ(static_cast<off_t>(GetOatMethodOffsetsOffsetFromOatHeader(0)), + DCHECK_EQ(static_cast<off_t>(file_offset + GetOatMethodOffsetsOffsetFromOatHeader(0)), out.Seek(0, kSeekCurrent)); if (!out.WriteFully(&method_offsets_[0], sizeof(method_offsets_[0]) * method_offsets_.size())) { @@ -896,7 +914,8 @@ bool OatWriter::OatClass::Write(OatWriter* oat_writer, OutputStream& out) const return false; } oat_writer->size_oat_class_method_offsets_ += sizeof(method_offsets_[0]) * method_offsets_.size(); - DCHECK_EQ(static_cast<off_t>(GetOatMethodOffsetsOffsetFromOatHeader(method_offsets_.size())), + DCHECK_EQ(static_cast<off_t>(file_offset + + GetOatMethodOffsetsOffsetFromOatHeader(method_offsets_.size())), out.Seek(0, kSeekCurrent)); return true; } diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h index ea7156e..f2c5626 100644 --- a/compiler/oat_writer.h +++ b/compiler/oat_writer.h @@ -62,23 +62,25 @@ class OutputStream; // class OatWriter { public: - // Write an oat file. Returns true on success, false on failure. - static bool Create(OutputStream& out, - const std::vector<const DexFile*>& dex_files, - uint32_t image_file_location_oat_checksum, - uint32_t image_file_location_oat_begin, - const std::string& image_file_location, - const CompilerDriver& compiler) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - - private: OatWriter(const std::vector<const DexFile*>& dex_files, uint32_t image_file_location_oat_checksum, uint32_t image_file_location_oat_begin, const std::string& image_file_location, const CompilerDriver* compiler) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + const OatHeader& GetOatHeader() const { + return *oat_header_; + } + + size_t GetSize() const { + return size_; + } + + bool Write(OutputStream& out); + ~OatWriter(); + private: size_t InitOatHeader(); size_t InitOatDexFiles(size_t offset); size_t InitDexFiles(size_t offset); @@ -101,17 +103,17 @@ class OatWriter { uint32_t method_idx, const DexFile*) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - bool Write(OutputStream& out); - bool WriteTables(OutputStream& out); - size_t WriteCode(OutputStream& out); - size_t WriteCodeDexFiles(OutputStream& out, size_t offset); - size_t WriteCodeDexFile(OutputStream& out, size_t offset, size_t& oat_class_index, - const DexFile& dex_file); - size_t WriteCodeClassDef(OutputStream& out, size_t offset, size_t oat_class_index, - const DexFile& dex_file, const DexFile::ClassDef& class_def); - size_t WriteCodeMethod(OutputStream& out, size_t offset, size_t oat_class_index, - size_t class_def_method_index, bool is_static, uint32_t method_idx, - const DexFile& dex_file); + bool WriteTables(OutputStream& out, const size_t file_offset); + size_t WriteCode(OutputStream& out, const size_t file_offset); + size_t WriteCodeDexFiles(OutputStream& out, const size_t file_offset, size_t relative_offset); + size_t WriteCodeDexFile(OutputStream& out, const size_t file_offset, size_t relative_offset, + size_t& oat_class_index, const DexFile& dex_file); + size_t WriteCodeClassDef(OutputStream& out, const size_t file_offset, size_t relative_offset, + size_t oat_class_index, const DexFile& dex_file, + const DexFile::ClassDef& class_def); + size_t WriteCodeMethod(OutputStream& out, const size_t file_offset, size_t relative_offset, + size_t oat_class_index, size_t class_def_method_index, bool is_static, + uint32_t method_idx, const DexFile& dex_file); void ReportWriteFailure(const char* what, uint32_t method_idx, const DexFile& dex_file, OutputStream& out) const; @@ -121,7 +123,7 @@ class OatWriter { explicit OatDexFile(size_t offset, const DexFile& dex_file); size_t SizeOf() const; void UpdateChecksum(OatHeader& oat_header) const; - bool Write(OatWriter* oat_writer, OutputStream& out) const; + bool Write(OatWriter* oat_writer, OutputStream& out, const size_t file_offset) const; // Offset of start of OatDexFile from beginning of OatHeader. It is // used to validate file position when writing. @@ -145,7 +147,7 @@ class OatWriter { size_t GetOatMethodOffsetsOffsetFromOatClass(size_t class_def_method_index_) const; size_t SizeOf() const; void UpdateChecksum(OatHeader& oat_header) const; - bool Write(OatWriter* oat_writer, OutputStream& out) const; + bool Write(OatWriter* oat_writer, OutputStream& out, const size_t file_offset) const; // Offset of start of OatClass from beginning of OatHeader. It is // used to validate file position when writing. For Portable, it @@ -167,6 +169,9 @@ class OatWriter { // note OatFile does not take ownership of the DexFiles const std::vector<const DexFile*>* dex_files_; + // Size required for Oat data structures. + size_t size_; + // dependencies on the image. uint32_t image_file_location_oat_checksum_; uint32_t image_file_location_oat_begin_; diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 0e32f0b..1a6a98a 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -282,27 +282,14 @@ class Dex2Oat { } } - std::vector<uint8_t> oat_contents; - // TODO: change ElfWriterQuick to not require the creation of oat_contents. The old pre-mclinker - // OatWriter streamed directly to disk. The new could can be adapted to do it as follows: - // 1.) use first pass of OatWriter to calculate size of oat structure, - // 2.) call ElfWriterQuick with pointer to OatWriter instead of contents, - // 3.) have ElfWriterQuick call back to OatWriter to stream generate the output directly in - // place in the elf file. - oat_contents.reserve(5 * MB); - VectorOutputStream vector_output_stream(oat_file->GetPath(), oat_contents); - if (!OatWriter::Create(vector_output_stream, - dex_files, - image_file_location_oat_checksum, - image_file_location_oat_data_begin, - image_file_location, - *driver.get())) { - LOG(ERROR) << "Failed to create oat file " << oat_file->GetPath(); - return NULL; - } + OatWriter oat_writer(dex_files, + image_file_location_oat_checksum, + image_file_location_oat_data_begin, + image_file_location, + driver.get()); timings.AddSplit("dex2oat OatWriter"); - if (!driver->WriteElf(android_root, is_host, dex_files, oat_contents, oat_file)) { + if (!driver->WriteElf(android_root, is_host, dex_files, oat_writer, oat_file)) { LOG(ERROR) << "Failed to write ELF file " << oat_file->GetPath(); return NULL; } @@ -1019,10 +1006,10 @@ static int dex2oat(int argc, char** argv) { *compiler.get()); timings.AddSplit("dex2oat ImageWriter"); Thread::Current()->TransitionFromSuspendedToRunnable(); - LOG(INFO) << "Image written successfully: " << image_filename; if (!image_creation_success) { return EXIT_FAILURE; } + LOG(INFO) << "Image written successfully: " << image_filename; } if (is_host) { diff --git a/runtime/image_test.cc b/runtime/image_test.cc index 11218ad..75eead4 100644 --- a/runtime/image_test.cc +++ b/runtime/image_test.cc @@ -41,7 +41,6 @@ class ImageTest : public CommonTest { TEST_F(ImageTest, WriteRead) { ScratchFile tmp_elf; { - std::vector<uint8_t> oat_contents; { jobject class_loader = NULL; ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); @@ -49,17 +48,14 @@ TEST_F(ImageTest, WriteRead) { compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), timings); ScopedObjectAccess soa(Thread::Current()); - VectorOutputStream output_stream(tmp_elf.GetFilename(), oat_contents); - bool success_oat = OatWriter::Create(output_stream, class_linker->GetBootClassPath(), - 0, 0, "", *compiler_driver_.get()); - ASSERT_TRUE(success_oat); - - bool success_elf = compiler_driver_->WriteElf(GetTestAndroidRoot(), - !kIsTargetBuild, - class_linker->GetBootClassPath(), - oat_contents, - tmp_elf.GetFile()); - ASSERT_TRUE(success_elf); + OatWriter oat_writer(class_linker->GetBootClassPath(), + 0, 0, "", compiler_driver_.get()); + bool success = compiler_driver_->WriteElf(GetTestAndroidRoot(), + !kIsTargetBuild, + class_linker->GetBootClassPath(), + oat_writer, + tmp_elf.GetFile()); + ASSERT_TRUE(success); } } // Workound bug that mcld::Linker::emit closes tmp_elf by reopening as tmp_oat. diff --git a/runtime/oat_test.cc b/runtime/oat_test.cc index 9a6bc19..3f2e43e 100644 --- a/runtime/oat_test.cc +++ b/runtime/oat_test.cc @@ -83,21 +83,17 @@ TEST_F(OatTest, WriteRead) { ScopedObjectAccess soa(Thread::Current()); ScratchFile tmp; - std::vector<uint8_t> oat_contents; - VectorOutputStream output_stream(tmp.GetFilename(), oat_contents); - bool success_oat = OatWriter::Create(output_stream, - class_linker->GetBootClassPath(), - 42U, - 4096U, - "lue.art", - *compiler_driver_.get()); - ASSERT_TRUE(success_oat); - bool success_elf = compiler_driver_->WriteElf(GetTestAndroidRoot(), - !kIsTargetBuild, - class_linker->GetBootClassPath(), - oat_contents, - tmp.GetFile()); - ASSERT_TRUE(success_elf); + OatWriter oat_writer(class_linker->GetBootClassPath(), + 42U, + 4096U, + "lue.art", + compiler_driver_.get()); + bool success = compiler_driver_->WriteElf(GetTestAndroidRoot(), + !kIsTargetBuild, + class_linker->GetBootClassPath(), + oat_writer, + tmp.GetFile()); + ASSERT_TRUE(success); if (compile) { // OatWriter strips the code, regenerate to compare TimingLogger timings("CommonTest::WriteRead", false); |