Revert "Allow method references across oat files for multi-image."
Breaks Quick tests.
This reverts commit 6065402316da2b51eed5fc34cffbd991766bd408.
Change-Id: I8a5469ba7cea5f46b85cb489b3e0ef06ed548f03
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index 239bc59..e4bfac9 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -194,15 +194,16 @@
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 6c6c9cf..0cd41bb 100644
--- a/compiler/dex/quick/quick_cfi_test.cc
+++ b/compiler/dex/quick/quick_cfi_test.cc
@@ -84,16 +84,17 @@
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 ff0ecea..efdc333 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 @@
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<DexFile::CodeItem*>(
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 0695cb5..2e2d1f9 100644
--- a/compiler/driver/compiled_method_storage_test.cc
+++ b/compiler/driver/compiled_method_storage_test.cc
@@ -32,19 +32,19 @@
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 e80730f..670fe94 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -342,15 +342,12 @@
Compiler::Kind compiler_kind,
InstructionSet instruction_set,
const InstructionSetFeatures* instruction_set_features,
- bool boot_image,
- std::unordered_set<std::string>* image_classes,
+ bool boot_image, std::unordered_set<std::string>* image_classes,
std::unordered_set<std::string>* compiled_classes,
std::unordered_set<std::string>* 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<const DexFile*, const char*>* dex_to_oat_map,
const ProfileCompilationInfo* profile_compilation_info)
: compiler_options_(compiler_options),
verification_results_(verification_results),
@@ -377,6 +374,7 @@
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 @@
use_dex_cache = true;
}
}
+ if (!use_dex_cache && IsBootImage()) {
+ if (!AreInSameOatFile(&(const_cast<mirror::Class*>(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 ca340ee..5e35cbb 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -94,11 +94,9 @@
bool boot_image, std::unordered_set<std::string>* image_classes,
std::unordered_set<std::string>* compiled_classes,
std::unordered_set<std::string>* 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<const DexFile*, const char*>* dex_to_oat_map,
const ProfileCompilationInfo* profile_compilation_info);
~CompilerDriver();
@@ -115,6 +113,20 @@
: ArrayRef<const DexFile* const>();
}
+ // 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<const DexFile*>& dex_files,
TimingLogger* timings)
@@ -688,6 +700,9 @@
// List of dex files that will be stored in the oat file.
const std::vector<const DexFile*>* dex_files_for_oat_file_;
+ // Map from dex files to the oat file (name) they will be compiled into.
+ const std::unordered_map<const DexFile*, const char*>* 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 f7da609..b673eeb 100644
--- a/compiler/elf_builder.h
+++ b/compiler/elf_builder.h
@@ -86,24 +86,12 @@
// Base class of all sections.
class Section : public OutputStream {
public:
- Section(ElfBuilder<ElfTypes>* 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<ElfTypes>* 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 @@
DISALLOW_COPY_AND_ASSIGN(Section);
};
- class CachedSection : public Section {
- public:
- CachedSection(ElfBuilder<ElfTypes>* 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<const uint8_t*>(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<uint8_t> cache_;
- };
-
- // Writer of .dynstr section.
- class CachedStringSection FINAL : public CachedSection {
- public:
- CachedStringSection(ElfBuilder<ElfTypes>* 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<ElfTypes>* 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<ElfTypes>* 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 @@
};
// Writer of .dynsym and .symtab sections.
- class SymbolSection FINAL : public CachedSection {
+ class SymbolSection FINAL : public Section {
public:
- SymbolSection(ElfBuilder<ElfTypes>* 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<ElfTypes>* 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<Elf_Word>(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<Elf_Word>(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<Elf_Sym> symbols_;
};
ElfBuilder(InstructionSet isa, OutputStream* output)
@@ -411,8 +309,6 @@
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 @@
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 @@
// 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<Elf_Word>(kPageSize));
- DCHECK_EQ(text_.header_.sh_addralign, static_cast<Elf_Word>(kPageSize));
- DCHECK_EQ(bss_.header_.sh_addralign, static_cast<Elf_Word>(kPageSize));
- DCHECK_EQ(dynstr_.header_.sh_addralign, static_cast<Elf_Word>(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<Elf_Word> hash;
hash.push_back(1); // Number of buckets.
hash.push_back(count); // Number of chains.
@@ -609,44 +484,21 @@
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]));
+ hash_.WriteFully(hash.data(), hash.size() * sizeof(hash[0]));
+ hash_.End();
- // 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<Elf_Word>(kPageSize));
- Elf_Word dynamic_address = RoundUp(hash_address + dynsym_.GetCacheSize(), kPageSize);
-
+ 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 @@
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 @@
std::vector<Section*> 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 c9ea0083..d50a08c 100644
--- a/compiler/elf_writer.h
+++ b/compiler/elf_writer.h
@@ -52,12 +52,14 @@
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<const debug::MethodDebugInfo>& method_infos) = 0;
+ virtual void PrepareDebugInfo(size_t rodata_section_size,
+ size_t text_section_size,
+ const ArrayRef<const debug::MethodDebugInfo>& 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<const debug::MethodDebugInfo>& method_infos) = 0;
virtual void WritePatchLocations(const ArrayRef<const uintptr_t>& patch_locations) = 0;
@@ -68,9 +70,6 @@
// 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 19346ec..1d71e57 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -88,12 +88,14 @@
~ElfWriterQuick();
void Start() OVERRIDE;
- void SetLoadedSectionSizes(size_t rodata_size, size_t text_size, size_t bss_size) OVERRIDE;
- void PrepareDebugInfo(const ArrayRef<const debug::MethodDebugInfo>& method_infos) OVERRIDE;
+ void PrepareDebugInfo(size_t rodata_section_size,
+ size_t text_section_size,
+ const ArrayRef<const debug::MethodDebugInfo>& 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<const debug::MethodDebugInfo>& method_infos) OVERRIDE;
void WritePatchLocations(const ArrayRef<const uintptr_t>& patch_locations) OVERRIDE;
@@ -101,17 +103,12 @@
virtual OutputStream* GetStream() OVERRIDE;
- size_t GetLoadedSize() OVERRIDE;
-
static void EncodeOatPatches(const std::vector<uintptr_t>& locations,
std::vector<uint8_t>* 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<BufferedOutputStream> output_stream_;
std::unique_ptr<ElfBuilder<ElfTypes>> builder_;
std::unique_ptr<DebugInfoTask> debug_info_task_;
@@ -137,9 +134,6 @@
: ElfWriter(),
compiler_options_(compiler_options),
elf_file_(elf_file),
- rodata_size_(0u),
- text_size_(0u),
- bss_size_(0u),
output_stream_(MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(elf_file))),
builder_(new ElfBuilder<ElfTypes>(instruction_set, output_stream_.get())) {}
@@ -152,19 +146,6 @@
}
template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::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 <typename ElfTypes>
OutputStream* ElfWriterQuick<ElfTypes>::StartRoData() {
auto* rodata = builder_->GetRoData();
rodata->Start();
@@ -191,21 +172,31 @@
}
template <typename ElfTypes>
-void ElfWriterQuick<ElfTypes>::WriteDynamicSection() {
- if (bss_size_ != 0u) {
- builder_->GetBss()->WriteNoBitsSection(bss_size_);
+void ElfWriterQuick<ElfTypes>::SetBssSize(size_t bss_size) {
+ auto* bss = builder_->GetBss();
+ if (bss_size != 0u) {
+ bss->WriteNoBitsSection(bss_size);
}
- builder_->WriteDynamicSection();
+}
+
+template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::WriteDynamicSection() {
+ builder_->WriteDynamicSection(elf_file_->GetPath());
}
template <typename ElfTypes>
void ElfWriterQuick<ElfTypes>::PrepareDebugInfo(
+ size_t rodata_section_size,
+ size_t text_section_size,
const ArrayRef<const debug::MethodDebugInfo>& 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<DebugInfoTask>(
- 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<ThreadPool>(
new ThreadPool("Mini-debug-info writer", 1));
debug_info_thread_pool_->AddTask(self, debug_info_task_.get());
@@ -254,11 +245,6 @@
return builder_->GetStream();
}
-template <typename ElfTypes>
-size_t ElfWriterQuick<ElfTypes>::GetLoadedSize() {
- return builder_->GetLoadedSize();
-}
-
// Explicit instantiations
template class ElfWriterQuick<ElfTypes32>;
template class ElfWriterQuick<ElfTypes64>;
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index 32f0a94..4920f9b 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -124,10 +124,6 @@
&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 @@
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 09046c7..73574ba 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -2274,18 +2274,25 @@
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 a4a252e..9371d9f 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -123,7 +123,7 @@
// 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 c2b29eb..3fe7861 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -172,6 +172,7 @@
/* 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 8bff41c..bf8e786 100644
--- a/compiler/linker/relative_patcher_test.h
+++ b/compiler/linker/relative_patcher_test.h
@@ -44,22 +44,10 @@
: 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 d03b4f1..894d29e 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -111,16 +111,17 @@
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_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 @@
return false;
}
+ elf_writer->SetBssSize(oat_writer.GetBssSize());
elf_writer->WriteDynamicSection();
elf_writer->WriteDebugInfo(oat_writer.GetMethodDebugInfo());
elf_writer->WritePatchLocations(oat_writer.GetAbsolutePatchLocations());