From 45724f9a0cc38dbb3071beb3eeab96499868b49c Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Wed, 17 Feb 2016 17:46:10 +0000 Subject: Revert "Allow method references across oat files for multi-image." Breaks Quick tests. This reverts commit 6065402316da2b51eed5fc34cffbd991766bd408. Change-Id: I8a5469ba7cea5f46b85cb489b3e0ef06ed548f03 --- compiler/common_compiler_test.cc | 11 +- compiler/dex/quick/quick_cfi_test.cc | 21 +- compiler/dex/quick/x86/quick_assemble_x86_test.cc | 23 +- compiler/driver/compiled_method_storage_test.cc | 26 +- compiler/driver/compiler_driver.cc | 18 +- compiler/driver/compiler_driver.h | 25 +- compiler/elf_builder.h | 298 ++++++---------------- compiler/elf_writer.h | 9 +- compiler/elf_writer_quick.cc | 52 ++-- compiler/image_test.cc | 5 +- compiler/image_writer.cc | 17 +- compiler/image_writer.h | 2 +- compiler/jit/jit_compiler.cc | 1 + compiler/linker/relative_patcher_test.h | 20 +- compiler/oat_test.cc | 24 +- 15 files changed, 200 insertions(+), 352 deletions(-) (limited to 'compiler') diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc index 239bc590e9..e4bfac9ee7 100644 --- a/compiler/common_compiler_test.cc +++ b/compiler/common_compiler_test.cc @@ -194,15 +194,16 @@ void CommonCompilerTest::CreateCompilerDriver(Compiler::Kind kind, InstructionSe kind, isa, instruction_set_features_.get(), - /* boot_image */ true, + true, GetImageClasses(), GetCompiledClasses(), GetCompiledMethods(), - /* thread_count */ 2, - /* dump_stats */ true, - /* dump_passes */ true, + 2, + true, + true, timer_.get(), - /* swap_fd */ -1, + -1, + /* dex_to_oat_map */ nullptr, GetProfileCompilationInfo())); // We typically don't generate an image in unit tests, disable this optimization by default. compiler_driver_->SetSupportBootImageFixup(false); diff --git a/compiler/dex/quick/quick_cfi_test.cc b/compiler/dex/quick/quick_cfi_test.cc index 6c6c9cfb1e..0cd41bbf4c 100644 --- a/compiler/dex/quick/quick_cfi_test.cc +++ b/compiler/dex/quick/quick_cfi_test.cc @@ -84,16 +84,17 @@ class QuickCFITest : public CFITest { Compiler::kQuick, isa, isa_features.get(), - /* boot_image */ false, - /* image_classes */ nullptr, - /* compiled_classes */ nullptr, - /* compiled_methods */ nullptr, - /* thread_count */ 0, - /* dump_stats */ false, - /* dump_passes */ false, - /* timer */ nullptr, - /* swap_fd */ -1, - /* profile_compilation_info */ nullptr); + false, + nullptr, + nullptr, + nullptr, + 0, + false, + false, + 0, + -1, + nullptr, + nullptr); ClassLinker* linker = nullptr; CompilationUnit cu(&pool, isa, &driver, linker); DexFile::CodeItem code_item { 0, 0, 0, 0, 0, 0, { 0 } }; // NOLINT diff --git a/compiler/dex/quick/x86/quick_assemble_x86_test.cc b/compiler/dex/quick/x86/quick_assemble_x86_test.cc index ff0ecea94c..efdc333261 100644 --- a/compiler/dex/quick/x86/quick_assemble_x86_test.cc +++ b/compiler/dex/quick/x86/quick_assemble_x86_test.cc @@ -64,17 +64,18 @@ class QuickAssembleX86TestBase : public testing::Test { method_inliner_map_.get(), Compiler::kQuick, isa_, - /* instruction_set_features*/ nullptr, - /* boot_image */ false, - /* image_classes */ nullptr, - /* compiled_classes */ nullptr, - /* compiled_methods */ nullptr, - /* thread_count */ 0, - /* dump_stats */ false, - /* dump_passes */ false, - /* timer */ nullptr, - /* swap_fd */ -1, - /* profile_compilation_info */ nullptr)); + nullptr, + false, + nullptr, + nullptr, + nullptr, + 0, + false, + false, + 0, + -1, + nullptr, + nullptr)); cu_.reset(new CompilationUnit(pool_.get(), isa_, compiler_driver_.get(), nullptr)); DexFile::CodeItem* code_item = static_cast( cu_->arena.Alloc(sizeof(DexFile::CodeItem), kArenaAllocMisc)); diff --git a/compiler/driver/compiled_method_storage_test.cc b/compiler/driver/compiled_method_storage_test.cc index 0695cb56b3..2e2d1f99f3 100644 --- a/compiler/driver/compiled_method_storage_test.cc +++ b/compiler/driver/compiled_method_storage_test.cc @@ -32,19 +32,19 @@ TEST(CompiledMethodStorage, Deduplicate) { CompilerDriver driver(&compiler_options, &verification_results, &method_inliner_map, - Compiler::kOptimizing, - /* instruction_set_ */ kNone, - /* instruction_set_features */ nullptr, - /* boot_image */ false, - /* image_classes */ nullptr, - /* compiled_classes */ nullptr, - /* compiled_methods */ nullptr, - /* thread_count */ 1u, - /* dump_stats */ false, - /* dump_passes */ false, - /* timer */ nullptr, - /* swap_fd */ -1, - /* profile_compilation_info */ nullptr); + Compiler::kOptimizing, kNone, + nullptr, + false, + nullptr, + nullptr, + nullptr, + 1u, + false, + false, + nullptr, + -1, + nullptr, + nullptr); CompiledMethodStorage* storage = driver.GetCompiledMethodStorage(); ASSERT_TRUE(storage->DedupeEnabled()); // The default. diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index e80730fe11..670fe94988 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -342,15 +342,12 @@ CompilerDriver::CompilerDriver( Compiler::Kind compiler_kind, InstructionSet instruction_set, const InstructionSetFeatures* instruction_set_features, - bool boot_image, - std::unordered_set* image_classes, + bool boot_image, std::unordered_set* image_classes, std::unordered_set* compiled_classes, std::unordered_set* compiled_methods, - size_t thread_count, - bool dump_stats, - bool dump_passes, - CumulativeLogger* timer, - int swap_fd, + size_t thread_count, bool dump_stats, bool dump_passes, + CumulativeLogger* timer, int swap_fd, + const std::unordered_map* dex_to_oat_map, const ProfileCompilationInfo* profile_compilation_info) : compiler_options_(compiler_options), verification_results_(verification_results), @@ -377,6 +374,7 @@ CompilerDriver::CompilerDriver( compiler_context_(nullptr), support_boot_image_fixup_(instruction_set != kMips && instruction_set != kMips64), dex_files_for_oat_file_(nullptr), + dex_file_oat_filename_map_(dex_to_oat_map), compiled_method_storage_(swap_fd), profile_compilation_info_(profile_compilation_info) { DCHECK(compiler_options_ != nullptr); @@ -1680,6 +1678,12 @@ void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType* type, InvokeType use_dex_cache = true; } } + if (!use_dex_cache && IsBootImage()) { + if (!AreInSameOatFile(&(const_cast(referrer_class)->GetDexFile()), + &declaring_class->GetDexFile())) { + use_dex_cache = true; + } + } // The method is defined not within this dex file. We need a dex cache slot within the current // dex file or direct pointers. bool must_use_direct_pointers = false; diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index ca340ee92c..5e35cbb309 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -94,11 +94,9 @@ class CompilerDriver { bool boot_image, std::unordered_set* image_classes, std::unordered_set* compiled_classes, std::unordered_set* compiled_methods, - size_t thread_count, - bool dump_stats, - bool dump_passes, - CumulativeLogger* timer, - int swap_fd, + size_t thread_count, bool dump_stats, bool dump_passes, + CumulativeLogger* timer, int swap_fd, + const std::unordered_map* dex_to_oat_map, const ProfileCompilationInfo* profile_compilation_info); ~CompilerDriver(); @@ -115,6 +113,20 @@ class CompilerDriver { : ArrayRef(); } + // Are the given dex files compiled into the same oat file? Should only be called after + // GetDexFilesForOatFile, as the conservative answer (when we don't have a map) is true. + bool AreInSameOatFile(const DexFile* d1, const DexFile* d2) { + if (dex_file_oat_filename_map_ == nullptr) { + // TODO: Check for this wrt/ apps and boot image calls. + return true; + } + auto it1 = dex_file_oat_filename_map_->find(d1); + DCHECK(it1 != dex_file_oat_filename_map_->end()); + auto it2 = dex_file_oat_filename_map_->find(d2); + DCHECK(it2 != dex_file_oat_filename_map_->end()); + return it1->second == it2->second; + } + void CompileAll(jobject class_loader, const std::vector& dex_files, TimingLogger* timings) @@ -688,6 +700,9 @@ class CompilerDriver { // List of dex files that will be stored in the oat file. const std::vector* dex_files_for_oat_file_; + // Map from dex files to the oat file (name) they will be compiled into. + const std::unordered_map* dex_file_oat_filename_map_; + CompiledMethodStorage compiled_method_storage_; // Info for profile guided compilation. diff --git a/compiler/elf_builder.h b/compiler/elf_builder.h index f7da609e5d..b673eeb3b6 100644 --- a/compiler/elf_builder.h +++ b/compiler/elf_builder.h @@ -86,24 +86,12 @@ class ElfBuilder FINAL { // Base class of all sections. class Section : public OutputStream { public: - Section(ElfBuilder* owner, - const std::string& name, - Elf_Word type, - Elf_Word flags, - const Section* link, - Elf_Word info, - Elf_Word align, - Elf_Word entsize) - : OutputStream(name), - owner_(owner), - header_(), - section_index_(0), - name_(name), - link_(link), - started_(false), - finished_(false), - phdr_flags_(PF_R), - phdr_type_(0) { + Section(ElfBuilder* owner, const std::string& name, + Elf_Word type, Elf_Word flags, const Section* link, + Elf_Word info, Elf_Word align, Elf_Word entsize) + : OutputStream(name), owner_(owner), header_(), + section_index_(0), name_(name), link_(link), + started_(false), finished_(false), phdr_flags_(PF_R), phdr_type_(0) { DCHECK_GE(align, 1u); header_.sh_type = type; header_.sh_flags = flags; @@ -240,84 +228,12 @@ class ElfBuilder FINAL { DISALLOW_COPY_AND_ASSIGN(Section); }; - class CachedSection : public Section { - public: - CachedSection(ElfBuilder* owner, - const std::string& name, - Elf_Word type, - Elf_Word flags, - const Section* link, - Elf_Word info, - Elf_Word align, - Elf_Word entsize) - : Section(owner, name, type, flags, link, info, align, entsize), cache_() { } - - Elf_Word Add(const void* data, size_t length) { - Elf_Word offset = cache_.size(); - const uint8_t* d = reinterpret_cast(data); - cache_.insert(cache_.end(), d, d + length); - return offset; - } - - Elf_Word GetCacheSize() { - return cache_.size(); - } - - void Write() { - this->WriteFully(cache_.data(), cache_.size()); - cache_.clear(); - cache_.shrink_to_fit(); - } - - void WriteCachedSection() { - this->Start(); - Write(); - this->End(); - } - - private: - std::vector cache_; - }; - - // Writer of .dynstr section. - class CachedStringSection FINAL : public CachedSection { - public: - CachedStringSection(ElfBuilder* owner, - const std::string& name, - Elf_Word flags, - Elf_Word align) - : CachedSection(owner, - name, - SHT_STRTAB, - flags, - /* link */ nullptr, - /* info */ 0, - align, - /* entsize */ 0) { } - - Elf_Word Add(const std::string& name) { - if (CachedSection::GetCacheSize() == 0u) { - DCHECK(name.empty()); - } - return CachedSection::Add(name.c_str(), name.length() + 1); - } - }; - - // Writer of .strtab and .shstrtab sections. + // Writer of .dynstr .strtab and .shstrtab sections. class StringSection FINAL : public Section { public: - StringSection(ElfBuilder* owner, - const std::string& name, - Elf_Word flags, - Elf_Word align) - : Section(owner, - name, - SHT_STRTAB, - flags, - /* link */ nullptr, - /* info */ 0, - align, - /* entsize */ 0), + StringSection(ElfBuilder* owner, const std::string& name, + Elf_Word flags, Elf_Word align) + : Section(owner, name, SHT_STRTAB, flags, nullptr, 0, align, 0), current_offset_(0) { } @@ -336,60 +252,42 @@ class ElfBuilder FINAL { }; // Writer of .dynsym and .symtab sections. - class SymbolSection FINAL : public CachedSection { + class SymbolSection FINAL : public Section { public: - SymbolSection(ElfBuilder* owner, - const std::string& name, - Elf_Word type, - Elf_Word flags, - Section* strtab) - : CachedSection(owner, - name, - type, - flags, - strtab, - /* info */ 0, - sizeof(Elf_Off), - sizeof(Elf_Sym)) { - // The symbol table always has to start with NULL symbol. - Elf_Sym null_symbol = Elf_Sym(); - CachedSection::Add(&null_symbol, sizeof(null_symbol)); + SymbolSection(ElfBuilder* owner, const std::string& name, + Elf_Word type, Elf_Word flags, StringSection* strtab) + : Section(owner, name, type, flags, strtab, 0, + sizeof(Elf_Off), sizeof(Elf_Sym)) { } // Buffer symbol for this section. It will be written later. // If the symbol's section is null, it will be considered absolute (SHN_ABS). // (we use this in JIT to reference code which is stored outside the debug ELF file) - void Add(Elf_Word name, - const Section* section, - Elf_Addr addr, - bool is_relative, - Elf_Word size, - uint8_t binding, - uint8_t type, - uint8_t other = 0) { - DCHECK(section != nullptr || !is_relative); - Elf_Addr abs_addr = addr + (is_relative ? section->GetAddress() : 0); - Elf_Word section_index = - (section != nullptr) ? section->GetSectionIndex() : static_cast(SHN_ABS); - Add(name, section_index, abs_addr, size, binding, type, other); - } - - void Add(Elf_Word name, - Elf_Word section_index, - Elf_Addr addr, - Elf_Word size, - uint8_t binding, - uint8_t type, - uint8_t other = 0) { + void Add(Elf_Word name, const Section* section, + Elf_Addr addr, bool is_relative, Elf_Word size, + uint8_t binding, uint8_t type, uint8_t other = 0) { Elf_Sym sym = Elf_Sym(); sym.st_name = name; - sym.st_value = addr; + sym.st_value = addr + (is_relative ? section->GetAddress() : 0); sym.st_size = size; sym.st_other = other; - sym.st_shndx = section_index; + sym.st_shndx = (section != nullptr ? section->GetSectionIndex() + : static_cast(SHN_ABS)); sym.st_info = (binding << 4) + (type & 0xf); - CachedSection::Add(&sym, sizeof(sym)); + symbols_.push_back(sym); + } + + void Write() { + // The symbol table always has to start with NULL symbol. + Elf_Sym null_symbol = Elf_Sym(); + this->WriteFully(&null_symbol, sizeof(null_symbol)); + this->WriteFully(symbols_.data(), symbols_.size() * sizeof(symbols_[0])); + symbols_.clear(); + symbols_.shrink_to_fit(); } + + private: + std::vector symbols_; }; ElfBuilder(InstructionSet isa, OutputStream* output) @@ -411,8 +309,6 @@ class ElfBuilder FINAL { debug_line_(this, ".debug_line", SHT_PROGBITS, 0, nullptr, 0, 1, 0), shstrtab_(this, ".shstrtab", 0, 1), started_(false), - write_program_headers_(false), - loaded_size_(0u), virtual_address_(0) { text_.phdr_flags_ = PF_R | PF_X; bss_.phdr_flags_ = PF_R | PF_W; @@ -484,14 +380,6 @@ class ElfBuilder FINAL { void End() { DCHECK(started_); - // Note: loaded_size_ == 0 for tests that don't write .rodata, .text, .bss, - // .dynstr, dynsym, .hash and .dynamic. These tests should not read loaded_size_. - // TODO: Either refactor the .eh_frame creation so that it counts towards loaded_size_, - // or remove all support for .eh_frame. (The currently unused .eh_frame counts towards - // the virtual_address_ but we don't consider it for loaded_size_.) - CHECK(loaded_size_ == 0 || loaded_size_ == RoundUp(virtual_address_, kPageSize)) - << loaded_size_ << " " << virtual_address_; - // Write section names and finish the section headers. shstrtab_.Start(); shstrtab_.Write(""); @@ -546,58 +434,45 @@ class ElfBuilder FINAL { // information like the address and size of .rodata and .text. // It also contains other metadata like the SONAME. // The .dynamic section is found using the PT_DYNAMIC program header. - void PrepareDynamicSection(const std::string& elf_file_path, - Elf_Word rodata_size, - Elf_Word text_size, - Elf_Word bss_size) { + void WriteDynamicSection(const std::string& elf_file_path) { std::string soname(elf_file_path); size_t directory_separator_pos = soname.rfind('/'); if (directory_separator_pos != std::string::npos) { soname = soname.substr(directory_separator_pos + 1); } - // Calculate addresses of .text, .bss and .dynstr. - DCHECK_EQ(rodata_.header_.sh_addralign, static_cast(kPageSize)); - DCHECK_EQ(text_.header_.sh_addralign, static_cast(kPageSize)); - DCHECK_EQ(bss_.header_.sh_addralign, static_cast(kPageSize)); - DCHECK_EQ(dynstr_.header_.sh_addralign, static_cast(kPageSize)); - Elf_Word rodata_address = rodata_.GetAddress(); - Elf_Word text_address = RoundUp(rodata_address + rodata_size, kPageSize); - Elf_Word bss_address = RoundUp(text_address + text_size, kPageSize); - Elf_Word dynstr_address = RoundUp(bss_address + bss_size, kPageSize); - - // Cache .dynstr, .dynsym and .hash data. - dynstr_.Add(""); // dynstr should start with empty string. - Elf_Word rodata_index = rodata_.GetSectionIndex(); - Elf_Word oatdata = dynstr_.Add("oatdata"); - dynsym_.Add(oatdata, rodata_index, rodata_address, rodata_size, STB_GLOBAL, STT_OBJECT); - if (text_size != 0u) { - Elf_Word text_index = rodata_index + 1u; - Elf_Word oatexec = dynstr_.Add("oatexec"); - dynsym_.Add(oatexec, text_index, text_address, text_size, STB_GLOBAL, STT_OBJECT); - Elf_Word oatlastword = dynstr_.Add("oatlastword"); - Elf_Word oatlastword_address = text_address + text_size - 4; - dynsym_.Add(oatlastword, text_index, oatlastword_address, 4, STB_GLOBAL, STT_OBJECT); - } else if (rodata_size != 0) { + dynstr_.Start(); + dynstr_.Write(""); // dynstr should start with empty string. + dynsym_.Add(dynstr_.Write("oatdata"), &rodata_, 0, true, + rodata_.GetSize(), STB_GLOBAL, STT_OBJECT); + if (text_.GetSize() != 0u) { + dynsym_.Add(dynstr_.Write("oatexec"), &text_, 0, true, + text_.GetSize(), STB_GLOBAL, STT_OBJECT); + dynsym_.Add(dynstr_.Write("oatlastword"), &text_, text_.GetSize() - 4, + true, 4, STB_GLOBAL, STT_OBJECT); + } else if (rodata_.GetSize() != 0) { // rodata_ can be size 0 for dwarf_test. - Elf_Word oatlastword = dynstr_.Add("oatlastword"); - Elf_Word oatlastword_address = rodata_address + rodata_size - 4; - dynsym_.Add(oatlastword, rodata_index, oatlastword_address, 4, STB_GLOBAL, STT_OBJECT); + dynsym_.Add(dynstr_.Write("oatlastword"), &rodata_, rodata_.GetSize() - 4, + true, 4, STB_GLOBAL, STT_OBJECT); } - if (bss_size != 0u) { - Elf_Word bss_index = rodata_index + 1u + (text_size != 0 ? 1u : 0u); - Elf_Word oatbss = dynstr_.Add("oatbss"); - dynsym_.Add(oatbss, bss_index, bss_address, bss_size, STB_GLOBAL, STT_OBJECT); - Elf_Word oatbsslastword = dynstr_.Add("oatbsslastword"); - Elf_Word bsslastword_address = bss_address + bss_size - 4; - dynsym_.Add(oatbsslastword, bss_index, bsslastword_address, 4, STB_GLOBAL, STT_OBJECT); + if (bss_.finished_) { + dynsym_.Add(dynstr_.Write("oatbss"), &bss_, + 0, true, bss_.GetSize(), STB_GLOBAL, STT_OBJECT); + dynsym_.Add(dynstr_.Write("oatbsslastword"), &bss_, + bss_.GetSize() - 4, true, 4, STB_GLOBAL, STT_OBJECT); } - Elf_Word soname_offset = dynstr_.Add(soname); + Elf_Word soname_offset = dynstr_.Write(soname); + dynstr_.End(); + + dynsym_.Start(); + dynsym_.Write(); + dynsym_.End(); // We do not really need a hash-table since there is so few entries. // However, the hash-table is the only way the linker can actually // determine the number of symbols in .dynsym so it is required. - int count = dynsym_.GetCacheSize() / sizeof(Elf_Sym); // Includes NULL. + hash_.Start(); + int count = dynsym_.GetSize() / sizeof(Elf_Sym); // Includes NULL. std::vector hash; hash.push_back(1); // Number of buckets. hash.push_back(count); // Number of chains. @@ -609,44 +484,21 @@ class ElfBuilder FINAL { hash.push_back(i + 1); // Each symbol points to the next one. } hash.push_back(0); // Last symbol terminates the chain. - hash_.Add(hash.data(), hash.size() * sizeof(hash[0])); - - // Calculate addresses of .dynsym, .hash and .dynamic. - DCHECK_EQ(dynstr_.header_.sh_flags, dynsym_.header_.sh_flags); - DCHECK_EQ(dynsym_.header_.sh_flags, hash_.header_.sh_flags); - Elf_Word dynsym_address = - RoundUp(dynstr_address + dynstr_.GetCacheSize(), dynsym_.header_.sh_addralign); - Elf_Word hash_address = - RoundUp(dynsym_address + dynsym_.GetCacheSize(), hash_.header_.sh_addralign); - DCHECK_EQ(dynamic_.header_.sh_addralign, static_cast(kPageSize)); - Elf_Word dynamic_address = RoundUp(hash_address + dynsym_.GetCacheSize(), kPageSize); + hash_.WriteFully(hash.data(), hash.size() * sizeof(hash[0])); + hash_.End(); + dynamic_.Start(); Elf_Dyn dyns[] = { - { DT_HASH, { hash_address } }, - { DT_STRTAB, { dynstr_address } }, - { DT_SYMTAB, { dynsym_address } }, + { DT_HASH, { hash_.GetAddress() } }, + { DT_STRTAB, { dynstr_.GetAddress() } }, + { DT_SYMTAB, { dynsym_.GetAddress() } }, { DT_SYMENT, { sizeof(Elf_Sym) } }, - { DT_STRSZ, { dynstr_.GetCacheSize() } }, + { DT_STRSZ, { dynstr_.GetSize() } }, { DT_SONAME, { soname_offset } }, { DT_NULL, { 0 } }, }; - dynamic_.Add(&dyns, sizeof(dyns)); - - loaded_size_ = RoundUp(dynamic_address + dynamic_.GetCacheSize(), kPageSize); - } - - void WriteDynamicSection() { - dynstr_.WriteCachedSection(); - dynsym_.WriteCachedSection(); - hash_.WriteCachedSection(); - dynamic_.WriteCachedSection(); - - CHECK_EQ(loaded_size_, RoundUp(dynamic_.GetAddress() + dynamic_.GetSize(), kPageSize)); - } - - Elf_Word GetLoadedSize() { - CHECK_NE(loaded_size_, 0u); - return loaded_size_; + dynamic_.WriteFully(&dyns, sizeof(dyns)); + dynamic_.End(); } // Returns true if all writes and seeks on the output stream succeeded. @@ -824,10 +676,10 @@ class ElfBuilder FINAL { Section rodata_; Section text_; Section bss_; - CachedStringSection dynstr_; + StringSection dynstr_; SymbolSection dynsym_; - CachedSection hash_; - CachedSection dynamic_; + Section hash_; + Section dynamic_; Section eh_frame_; Section eh_frame_hdr_; StringSection strtab_; @@ -842,14 +694,12 @@ class ElfBuilder FINAL { std::vector sections_; bool started_; - bool write_program_headers_; - - // The size of the memory taken by the ELF file when loaded. - size_t loaded_size_; // Used for allocation of virtual address space. Elf_Addr virtual_address_; + size_t write_program_headers_; + DISALLOW_COPY_AND_ASSIGN(ElfBuilder); }; diff --git a/compiler/elf_writer.h b/compiler/elf_writer.h index c9ea0083d5..d50a08cb20 100644 --- a/compiler/elf_writer.h +++ b/compiler/elf_writer.h @@ -52,12 +52,14 @@ class ElfWriter { virtual ~ElfWriter() {} virtual void Start() = 0; - virtual void SetLoadedSectionSizes(size_t rodata_size, size_t text_size, size_t bss_size) = 0; - virtual void PrepareDebugInfo(const ArrayRef& method_infos) = 0; + virtual void PrepareDebugInfo(size_t rodata_section_size, + size_t text_section_size, + const ArrayRef& method_infos) = 0; virtual OutputStream* StartRoData() = 0; virtual void EndRoData(OutputStream* rodata) = 0; virtual OutputStream* StartText() = 0; virtual void EndText(OutputStream* text) = 0; + virtual void SetBssSize(size_t bss_size) = 0; virtual void WriteDynamicSection() = 0; virtual void WriteDebugInfo(const ArrayRef& method_infos) = 0; virtual void WritePatchLocations(const ArrayRef& patch_locations) = 0; @@ -68,9 +70,6 @@ class ElfWriter { // should Seek() back to the position where the stream was before this operation. virtual OutputStream* GetStream() = 0; - // Get the size that the loaded ELF file will occupy in memory. - virtual size_t GetLoadedSize() = 0; - protected: ElfWriter() = default; }; diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc index 19346ecc2b..1d71e572d7 100644 --- a/compiler/elf_writer_quick.cc +++ b/compiler/elf_writer_quick.cc @@ -88,12 +88,14 @@ class ElfWriterQuick FINAL : public ElfWriter { ~ElfWriterQuick(); void Start() OVERRIDE; - void SetLoadedSectionSizes(size_t rodata_size, size_t text_size, size_t bss_size) OVERRIDE; - void PrepareDebugInfo(const ArrayRef& method_infos) OVERRIDE; + void PrepareDebugInfo(size_t rodata_section_size, + size_t text_section_size, + const ArrayRef& method_infos) OVERRIDE; OutputStream* StartRoData() OVERRIDE; void EndRoData(OutputStream* rodata) OVERRIDE; OutputStream* StartText() OVERRIDE; void EndText(OutputStream* text) OVERRIDE; + void SetBssSize(size_t bss_size) OVERRIDE; void WriteDynamicSection() OVERRIDE; void WriteDebugInfo(const ArrayRef& method_infos) OVERRIDE; void WritePatchLocations(const ArrayRef& patch_locations) OVERRIDE; @@ -101,17 +103,12 @@ class ElfWriterQuick FINAL : public ElfWriter { virtual OutputStream* GetStream() OVERRIDE; - size_t GetLoadedSize() OVERRIDE; - static void EncodeOatPatches(const std::vector& locations, std::vector* buffer); private: const CompilerOptions* const compiler_options_; File* const elf_file_; - size_t rodata_size_; - size_t text_size_; - size_t bss_size_; std::unique_ptr output_stream_; std::unique_ptr> builder_; std::unique_ptr debug_info_task_; @@ -137,9 +134,6 @@ ElfWriterQuick::ElfWriterQuick(InstructionSet instruction_set, : ElfWriter(), compiler_options_(compiler_options), elf_file_(elf_file), - rodata_size_(0u), - text_size_(0u), - bss_size_(0u), output_stream_(MakeUnique(MakeUnique(elf_file))), builder_(new ElfBuilder(instruction_set, output_stream_.get())) {} @@ -151,19 +145,6 @@ void ElfWriterQuick::Start() { builder_->Start(); } -template -void ElfWriterQuick::SetLoadedSectionSizes(size_t rodata_size, - size_t text_size, - size_t bss_size) { - DCHECK_EQ(rodata_size_, 0u); - rodata_size_ = rodata_size; - DCHECK_EQ(text_size_, 0u); - text_size_ = text_size; - DCHECK_EQ(bss_size_, 0u); - bss_size_ = bss_size; - builder_->PrepareDynamicSection(elf_file_->GetPath(), rodata_size_, text_size_, bss_size_); -} - template OutputStream* ElfWriterQuick::StartRoData() { auto* rodata = builder_->GetRoData(); @@ -191,21 +172,31 @@ void ElfWriterQuick::EndText(OutputStream* text) { } template -void ElfWriterQuick::WriteDynamicSection() { - if (bss_size_ != 0u) { - builder_->GetBss()->WriteNoBitsSection(bss_size_); +void ElfWriterQuick::SetBssSize(size_t bss_size) { + auto* bss = builder_->GetBss(); + if (bss_size != 0u) { + bss->WriteNoBitsSection(bss_size); } - builder_->WriteDynamicSection(); +} + +template +void ElfWriterQuick::WriteDynamicSection() { + builder_->WriteDynamicSection(elf_file_->GetPath()); } template void ElfWriterQuick::PrepareDebugInfo( + size_t rodata_section_size, + size_t text_section_size, const ArrayRef& method_infos) { if (!method_infos.empty() && compiler_options_->GetGenerateMiniDebugInfo()) { // Prepare the mini-debug-info in background while we do other I/O. Thread* self = Thread::Current(); debug_info_task_ = std::unique_ptr( - new DebugInfoTask(builder_->GetIsa(), rodata_size_, text_size_, method_infos)); + new DebugInfoTask(builder_->GetIsa(), + rodata_section_size, + text_section_size, + method_infos)); debug_info_thread_pool_ = std::unique_ptr( new ThreadPool("Mini-debug-info writer", 1)); debug_info_thread_pool_->AddTask(self, debug_info_task_.get()); @@ -254,11 +245,6 @@ OutputStream* ElfWriterQuick::GetStream() { return builder_->GetStream(); } -template -size_t ElfWriterQuick::GetLoadedSize() { - return builder_->GetLoadedSize(); -} - // Explicit instantiations template class ElfWriterQuick; template class ElfWriterQuick; diff --git a/compiler/image_test.cc b/compiler/image_test.cc index 32f0a94c39..4920f9baa5 100644 --- a/compiler/image_test.cc +++ b/compiler/image_test.cc @@ -124,10 +124,6 @@ void ImageTest::TestWriteRead(ImageHeader::StorageMode storage_mode) { &opened_dex_files); ASSERT_TRUE(dex_files_ok); oat_writer.PrepareLayout(compiler_driver_.get(), writer.get(), dex_files); - size_t rodata_size = oat_writer.GetOatHeader().GetExecutableOffset(); - size_t text_size = oat_writer.GetSize() - rodata_size; - elf_writer->SetLoadedSectionSizes(rodata_size, text_size, oat_writer.GetBssSize()); - bool image_space_ok = writer->PrepareImageAddressSpace(); ASSERT_TRUE(image_space_ok); @@ -143,6 +139,7 @@ void ImageTest::TestWriteRead(ImageHeader::StorageMode storage_mode) { bool header_ok = oat_writer.WriteHeader(elf_writer->GetStream(), 0u, 0u, 0u); ASSERT_TRUE(header_ok); + elf_writer->SetBssSize(oat_writer.GetBssSize()); elf_writer->WriteDynamicSection(); elf_writer->WriteDebugInfo(oat_writer.GetMethodDebugInfo()); elf_writer->WritePatchLocations(oat_writer.GetAbsolutePatchLocations()); diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 09046c7a3a..73574ba673 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -2274,18 +2274,25 @@ const ImageWriter::ImageInfo& ImageWriter::GetImageInfo(size_t index) const { return GetConstImageInfo(oat_filenames_[index]); } -void ImageWriter::UpdateOatFile(size_t index, size_t oat_loaded_size) { +void ImageWriter::UpdateOatFile(File* oat_file, const char* oat_filename) { + DCHECK(oat_file != nullptr); if (compile_app_image_) { CHECK_EQ(oat_filenames_.size(), 1u) << "App image should have no next image."; return; } + ImageInfo& cur_image_info = GetImageInfo(oat_filename); // Update the oat_offset of the next image info. - DCHECK_LT(index, oat_filenames_.size()); - if (index + 1u != oat_filenames_.size()) { + auto it = std::find(oat_filenames_.begin(), oat_filenames_.end(), oat_filename); + DCHECK(it != oat_filenames_.end()); + + it++; + if (it != oat_filenames_.end()) { + size_t oat_loaded_size = 0; + size_t oat_data_offset = 0; + ElfWriter::GetOatElfInformation(oat_file, &oat_loaded_size, &oat_data_offset); // There is a following one. - ImageInfo& cur_image_info = GetImageInfo(oat_filenames_[index]); - ImageInfo& next_image_info = GetImageInfo(oat_filenames_[index + 1u]); + ImageInfo& next_image_info = GetImageInfo(*it); next_image_info.oat_offset_ = cur_image_info.oat_offset_ + oat_loaded_size; } } diff --git a/compiler/image_writer.h b/compiler/image_writer.h index a4a252e389..9371d9ffa9 100644 --- a/compiler/image_writer.h +++ b/compiler/image_writer.h @@ -123,7 +123,7 @@ class ImageWriter FINAL { // Update the oat size for the given oat file. This will make the oat_offset for the next oat // file valid. - void UpdateOatFile(size_t index, size_t oat_loaded_size); + void UpdateOatFile(File* oat_file, const char* oat_filename); private: bool AllocMemory(); diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc index c2b29eb01a..3fe786141e 100644 --- a/compiler/jit/jit_compiler.cc +++ b/compiler/jit/jit_compiler.cc @@ -172,6 +172,7 @@ JitCompiler::JitCompiler() : total_time_(0) { /* dump_passes */ false, cumulative_logger_.get(), /* swap_fd */ -1, + /* dex to oat map */ nullptr, /* profile_compilation_info */ nullptr)); // Disable dedupe so we can remove compiled methods. compiler_driver_->SetDedupeEnabled(false); diff --git a/compiler/linker/relative_patcher_test.h b/compiler/linker/relative_patcher_test.h index 8bff41c976..bf8e786f64 100644 --- a/compiler/linker/relative_patcher_test.h +++ b/compiler/linker/relative_patcher_test.h @@ -44,22 +44,10 @@ class RelativePatcherTest : public testing::Test { : compiler_options_(), verification_results_(&compiler_options_), inliner_map_(), - driver_(&compiler_options_, - &verification_results_, - &inliner_map_, - Compiler::kQuick, - instruction_set, - /* instruction_set_features*/ nullptr, - /* boot_image */ false, - /* image_classes */ nullptr, - /* compiled_classes */ nullptr, - /* compiled_methods */ nullptr, - /* thread_count */ 1u, - /* dump_stats */ false, - /* dump_passes */ false, - /* timer */ nullptr, - /* swap_fd */ -1, - /* profile_compilation_info */ nullptr), + driver_(&compiler_options_, &verification_results_, &inliner_map_, + Compiler::kQuick, instruction_set, nullptr, + false, nullptr, nullptr, nullptr, 1u, + false, false, nullptr, -1, nullptr, nullptr), error_msg_(), instruction_set_(instruction_set), features_(InstructionSetFeatures::FromVariant(instruction_set, variant, &error_msg_)), diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc index d03b4f1055..894d29ee99 100644 --- a/compiler/oat_test.cc +++ b/compiler/oat_test.cc @@ -111,16 +111,17 @@ class OatTest : public CommonCompilerTest { compiler_kind, insn_set, insn_features_.get(), - /* boot_image */ false, - /* image_classes */ nullptr, - /* compiled_classes */ nullptr, - /* compiled_methods */ nullptr, - /* thread_count */ 2, - /* dump_stats */ true, - /* dump_passes */ true, + false, + nullptr, + nullptr, + nullptr, + 2, + true, + true, timer_.get(), - /* swap_fd */ -1, - /* profile_compilation_info */ nullptr)); + -1, + nullptr, + nullptr)); } bool WriteElf(File* file, @@ -200,10 +201,6 @@ class OatTest : public CommonCompilerTest { class_linker->RegisterDexFile(*dex_file, runtime->GetLinearAlloc()); } oat_writer.PrepareLayout(compiler_driver_.get(), nullptr, dex_files); - size_t rodata_size = oat_writer.GetOatHeader().GetExecutableOffset(); - size_t text_size = oat_writer.GetSize() - rodata_size; - elf_writer->SetLoadedSectionSizes(rodata_size, text_size, oat_writer.GetBssSize()); - if (!oat_writer.WriteRodata(rodata)) { return false; } @@ -219,6 +216,7 @@ class OatTest : public CommonCompilerTest { return false; } + elf_writer->SetBssSize(oat_writer.GetBssSize()); elf_writer->WriteDynamicSection(); elf_writer->WriteDebugInfo(oat_writer.GetMethodDebugInfo()); elf_writer->WritePatchLocations(oat_writer.GetAbsolutePatchLocations()); -- cgit v1.2.3-59-g8ed1b