diff options
| author | 2016-05-19 19:02:16 +0000 | |
|---|---|---|
| committer | 2016-05-19 19:02:16 +0000 | |
| commit | 93622f95a8ee8828d3130fa54f38fb4806119e45 (patch) | |
| tree | cde01f20be212ccedaaabf038b1a31f3a0896ca1 | |
| parent | 247250f28028a5b2260ba2eb0a7f555a183b996a (diff) | |
| parent | 39004a6fa5566007354379dfc4ae59823146e23e (diff) | |
Merge changes I0bbdf83d,I70156f98
* changes:
ART: Fix Mac build
ART: Optimize PreSetup pass for oat-file open
| -rw-r--r-- | runtime/oat_file.cc | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index ae84019a5e..c33a9cd6d1 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -98,6 +98,8 @@ class OatFileBase : public OatFile { virtual const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name, std::string* error_msg) const = 0; + virtual void PreLoad() = 0; + virtual bool Load(const std::string& elf_filename, uint8_t* oat_file_begin, bool writable, @@ -138,6 +140,9 @@ OatFileBase* OatFileBase::OpenOatFile(const std::string& elf_filename, const char* abs_dex_location, std::string* error_msg) { std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(location, executable)); + + ret->PreLoad(); + if (!ret->Load(elf_filename, oat_file_begin, writable, @@ -150,6 +155,7 @@ OatFileBase* OatFileBase::OpenOatFile(const std::string& elf_filename, if (!ret->ComputeFields(requested_base, elf_filename, error_msg)) { return nullptr; } + ret->PreSetup(elf_filename); if (!ret->Setup(abs_dex_location, error_msg)) { @@ -509,6 +515,7 @@ class DlOpenOatFile FINAL : public OatFileBase { DlOpenOatFile(const std::string& filename, bool executable) : OatFileBase(filename, executable), dlopen_handle_(nullptr), + shared_objects_before_(0), first_oat_(RegisterOatFileLocation(filename)) { } @@ -530,6 +537,8 @@ class DlOpenOatFile FINAL : public OatFileBase { return ptr; } + void PreLoad() OVERRIDE; + bool Load(const std::string& elf_filename, uint8_t* oat_file_begin, bool writable, @@ -551,12 +560,38 @@ class DlOpenOatFile FINAL : public OatFileBase { // Dummy memory map objects corresponding to the regions mapped by dlopen. std::vector<std::unique_ptr<MemMap>> dlopen_mmaps_; + // The number of shared objects the linker told us about before loading. Used to + // (optimistically) optimize the PreSetup stage (see comment there). + size_t shared_objects_before_; + // Track the registration status (= was this the first oat file) for the location. const bool first_oat_; DISALLOW_COPY_AND_ASSIGN(DlOpenOatFile); }; +void DlOpenOatFile::PreLoad() { +#ifdef __APPLE__ + UNUSED(shared_objects_before_); + LOG(FATAL) << "Should not reach here."; + UNREACHABLE(); +#else + // Count the entries in dl_iterate_phdr we get at this point in time. + struct dl_iterate_context { + static int callback(struct dl_phdr_info *info ATTRIBUTE_UNUSED, + size_t size ATTRIBUTE_UNUSED, + void *data) { + reinterpret_cast<dl_iterate_context*>(data)->count++; + return 0; // Continue iteration. + } + size_t count = 0; + } context; + + dl_iterate_phdr(dl_iterate_context::callback, &context); + shared_objects_before_ = context.count; +#endif +} + bool DlOpenOatFile::Load(const std::string& elf_filename, uint8_t* oat_file_begin, bool writable, @@ -657,6 +692,14 @@ void DlOpenOatFile::PreSetup(const std::string& elf_filename) { struct dl_iterate_context { static int callback(struct dl_phdr_info *info, size_t /* size */, void *data) { auto* context = reinterpret_cast<dl_iterate_context*>(data); + context->shared_objects_seen++; + if (context->shared_objects_seen < context->shared_objects_before) { + // We haven't been called yet for anything we haven't seen before. Just continue. + // Note: this is aggressively optimistic. If another thread was unloading a library, + // we may miss out here. However, this does not happen often in practice. + return 0; + } + // See whether this callback corresponds to the file which we have just loaded. bool contains_begin = false; for (int i = 0; i < info->dlpi_phnum; i++) { @@ -687,11 +730,22 @@ void DlOpenOatFile::PreSetup(const std::string& elf_filename) { } const uint8_t* const begin_; std::vector<std::unique_ptr<MemMap>>* const dlopen_mmaps_; - } context = { Begin(), &dlopen_mmaps_ }; + const size_t shared_objects_before; + size_t shared_objects_seen; + }; + dl_iterate_context context = { Begin(), &dlopen_mmaps_, shared_objects_before_, 0}; if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) { - PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); - LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps."; + // Hm. Maybe our optimization went wrong. Try another time with shared_objects_before == 0 + // before giving up. This should be unusual. + VLOG(oat) << "Need a second run in PreSetup, didn't find with shared_objects_before=" + << shared_objects_before_; + dl_iterate_context context0 = { Begin(), &dlopen_mmaps_, 0, 0}; + if (dl_iterate_phdr(dl_iterate_context::callback, &context0) == 0) { + // OK, give up and print an error. + PrintFileToLog("/proc/self/maps", LogSeverity::WARNING); + LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but cannot find its mmaps."; + } } #endif } @@ -728,6 +782,9 @@ class ElfOatFile FINAL : public OatFileBase { return ptr; } + void PreLoad() OVERRIDE { + } + bool Load(const std::string& elf_filename, uint8_t* oat_file_begin, // Override where the file is loaded to if not null bool writable, |