diff options
-rw-r--r-- | compiler/elf_patcher.cc | 3 | ||||
-rw-r--r-- | runtime/class_linker.cc | 56 | ||||
-rw-r--r-- | runtime/class_linker.h | 15 | ||||
-rw-r--r-- | runtime/dex_file.cc | 57 | ||||
-rw-r--r-- | runtime/dex_file.h | 26 | ||||
-rw-r--r-- | runtime/dex_file_test.cc | 6 | ||||
-rw-r--r-- | runtime/oat_file.cc | 55 | ||||
-rw-r--r-- | runtime/oat_file.h | 32 | ||||
-rw-r--r-- | runtime/runtime.cc | 4 | ||||
-rw-r--r-- | runtime/utils.h | 13 | ||||
-rw-r--r-- | test/116-nodex2oat/nodex2oat.cc | 6 | ||||
-rw-r--r-- | test/117-nopatchoat/nopatchoat.cc | 6 | ||||
-rw-r--r-- | test/118-noimage-dex2oat/noimage-dex2oat.cc | 6 |
13 files changed, 138 insertions, 147 deletions
diff --git a/compiler/elf_patcher.cc b/compiler/elf_patcher.cc index 72bf7d303f..f192227c1f 100644 --- a/compiler/elf_patcher.cc +++ b/compiler/elf_patcher.cc @@ -200,7 +200,8 @@ bool ElfPatcher::PatchElf() { mirror::ArtMethod* target = GetTargetMethod(patch); uintptr_t quick_code = reinterpret_cast<uintptr_t>(class_linker->GetQuickOatCodeFor(target)); DCHECK_NE(quick_code, 0U) << PrettyMethod(target); - const OatFile* target_oat = class_linker->FindOpenedOatFileForDexFile(*patch->GetTargetDexFile()); + const OatFile* target_oat = + class_linker->FindOpenedOatDexFileForDexFile(*patch->GetTargetDexFile())->GetOatFile(); // Get where the data actually starts. if target is this oat_file_ it is oat_data_start_, // otherwise it is wherever target_oat is loaded. uintptr_t oat_data_addr = GetBaseAddressFor(target_oat); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 563ee93e7d..637fd02a91 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -756,18 +756,18 @@ OatFile& ClassLinker::GetImageOatFile(gc::space::ImageSpace* space) { return *oat_file; } -const OatFile* ClassLinker::FindOpenedOatFileForDexFile(const DexFile& dex_file) { +const OatFile::OatDexFile* ClassLinker::FindOpenedOatDexFileForDexFile(const DexFile& dex_file) { const char* dex_location = dex_file.GetLocation().c_str(); uint32_t dex_location_checksum = dex_file.GetLocationChecksum(); - return FindOpenedOatFile(nullptr, dex_location, &dex_location_checksum); + return FindOpenedOatDexFile(nullptr, dex_location, &dex_location_checksum); } -const OatFile* ClassLinker::FindOpenedOatFile(const char* oat_location, const char* dex_location, - const uint32_t* const dex_location_checksum) { +const OatFile::OatDexFile* ClassLinker::FindOpenedOatDexFile(const char* oat_location, + const char* dex_location, + const uint32_t* dex_location_checksum) { ReaderMutexLock mu(Thread::Current(), dex_lock_); - for (size_t i = 0; i < oat_files_.size(); i++) { - const OatFile* oat_file = oat_files_[i]; - DCHECK(oat_file != NULL); + for (const OatFile* oat_file : oat_files_) { + DCHECK(oat_file != nullptr); if (oat_location != nullptr) { if (oat_file->GetLocation() != oat_location) { @@ -778,11 +778,11 @@ const OatFile* ClassLinker::FindOpenedOatFile(const char* oat_location, const ch const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location, dex_location_checksum, false); - if (oat_dex_file != NULL) { - return oat_file; + if (oat_dex_file != nullptr) { + return oat_dex_file; } } - return NULL; + return nullptr; } @@ -904,8 +904,10 @@ bool ClassLinker::OpenDexFilesFromOat(const char* dex_location, const char* oat_ bool needs_registering = false; - std::unique_ptr<const OatFile> open_oat_file(FindOpenedOatFile(oat_location, dex_location, - dex_location_checksum_pointer)); + const OatFile::OatDexFile* oat_dex_file = FindOpenedOatDexFile(oat_location, dex_location, + dex_location_checksum_pointer); + std::unique_ptr<const OatFile> open_oat_file( + oat_dex_file != nullptr ? oat_dex_file->GetOatFile() : nullptr); // 2) If we do not have an open one, maybe there's one on disk already. @@ -1026,7 +1028,8 @@ bool ClassLinker::OpenDexFilesFromOat(const char* dex_location, const char* oat_ } // Try to load again, but stronger checks. - success = LoadMultiDexFilesFromOatFile(open_oat_file.get(), dex_location, dex_location_checksum_pointer, + success = LoadMultiDexFilesFromOatFile(open_oat_file.get(), dex_location, + dex_location_checksum_pointer, true, error_msgs, dex_files); if (success) { RegisterOatFile(open_oat_file.release()); @@ -1201,12 +1204,11 @@ bool ClassLinker::VerifyOatAndDexFileChecksums(const OatFile* oat_file, if (oat_dex_file == NULL) { *error_msg = StringPrintf("oat file '%s' does not contain contents for '%s' with checksum 0x%x", oat_file->GetLocation().c_str(), dex_location, dex_location_checksum); - std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file->GetOatDexFiles(); - for (size_t i = 0; i < oat_dex_files.size(); i++) { - const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i]; - *error_msg += StringPrintf("\noat file '%s' contains contents for '%s'", + for (const OatFile::OatDexFile* oat_dex_file : oat_file->GetOatDexFiles()) { + *error_msg += StringPrintf("\noat file '%s' contains contents for '%s' with checksum 0x%x", oat_file->GetLocation().c_str(), - oat_dex_file->GetDexFileLocation().c_str()); + oat_dex_file->GetDexFileLocation().c_str(), + oat_dex_file->GetDexFileLocationChecksum()); } return false; } @@ -1248,7 +1250,7 @@ bool ClassLinker::VerifyOatWithDexFile(const OatFile* oat_file, const OatFile* ClassLinker::FindOatFileContainingDexFileFromDexLocation( const char* dex_location, - const uint32_t* const dex_location_checksum, + const uint32_t* dex_location_checksum, InstructionSet isa, std::vector<std::string>* error_msgs, bool* obsolete_file_cleanup_failed) { @@ -2400,15 +2402,11 @@ uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file, OatFile::OatClass ClassLinker::FindOatClass(const DexFile& dex_file, uint16_t class_def_idx, bool* found) { DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16); - const OatFile* oat_file = FindOpenedOatFileForDexFile(dex_file); - if (oat_file == nullptr) { + const OatFile::OatDexFile* oat_dex_file = FindOpenedOatDexFileForDexFile(dex_file); + if (oat_dex_file == nullptr) { *found = false; return OatFile::OatClass::Invalid(); } - uint dex_location_checksum = dex_file.GetLocationChecksum(); - const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation().c_str(), - &dex_location_checksum); - CHECK(oat_dex_file != NULL) << dex_file.GetLocation(); *found = true; return oat_dex_file->GetOatClass(class_def_idx); } @@ -3681,17 +3679,13 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class } } - const OatFile* oat_file = FindOpenedOatFileForDexFile(dex_file); + const OatFile::OatDexFile* oat_dex_file = FindOpenedOatDexFileForDexFile(dex_file); // Make this work with gtests, which do not set up the image properly. // TODO: we should clean up gtests to set up the image path properly. - if (Runtime::Current()->IsCompiler() || (oat_file == NULL)) { + if (Runtime::Current()->IsCompiler() || (oat_dex_file == nullptr)) { return false; } - CHECK(oat_file != NULL) << dex_file.GetLocation() << " " << PrettyClass(klass); - uint dex_location_checksum = dex_file.GetLocationChecksum(); - const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation().c_str(), - &dex_location_checksum); CHECK(oat_dex_file != NULL) << dex_file.GetLocation() << " " << PrettyClass(klass); uint16_t class_def_index = klass->GetDexClassDefIndex(); oat_file_class_status = oat_dex_file->GetOatClass(class_def_index).GetStatus(); diff --git a/runtime/class_linker.h b/runtime/class_linker.h index d1f5aa0ec3..0248a219be 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -549,14 +549,15 @@ class ClassLinker { } mirror::DexCache* GetDexCache(size_t idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, dex_lock_); - const OatFile* FindOpenedOatFileForDexFile(const DexFile& dex_file) + const OatFile::OatDexFile* FindOpenedOatDexFileForDexFile(const DexFile& dex_file) LOCKS_EXCLUDED(dex_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // Find an opened oat file that contains dex_location. If oat_location is not nullptr, the file - // must have that location, else any oat location is accepted. - const OatFile* FindOpenedOatFile(const char* oat_location, const char* dex_location, - const uint32_t* const dex_location_checksum) + // Find an opened oat dex file that contains dex_location. If oat_location is not nullptr, + // the file must have that location, else any oat location is accepted. + const OatFile::OatDexFile* FindOpenedOatDexFile(const char* oat_location, + const char* dex_location, + const uint32_t* dex_location_checksum) LOCKS_EXCLUDED(dex_lock_); // Will open the oat file directly without relocating, even if we could/should do relocation. @@ -606,8 +607,8 @@ class ClassLinker { // Note 1: this will not check open oat files, which are assumed to be stale when this is run. // Note 2: Does not register the oat file. It is the caller's job to register if the file is to // be kept. - const OatFile* FindOatFileContainingDexFileFromDexLocation(const char* location, - const uint32_t* const location_checksum, + const OatFile* FindOatFileContainingDexFileFromDexLocation(const char* dex_location, + const uint32_t* dex_location_checksum, InstructionSet isa, std::vector<std::string>* error_msgs, bool* obsolete_file_cleanup_failed) diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc index ed3592cb87..38e2e68cfe 100644 --- a/runtime/dex_file.cc +++ b/runtime/dex_file.cc @@ -77,14 +77,13 @@ bool DexFile::GetChecksum(const char* filename, uint32_t* checksum, std::string* // Strip ":...", which is the location const char* zip_entry_name = kClassesDex; const char* file_part = filename; - std::unique_ptr<const char> file_part_ptr; + std::string file_part_storage; - - if (IsMultiDexLocation(filename)) { - std::pair<const char*, const char*> pair = SplitMultiDexLocation(filename); - file_part_ptr.reset(pair.first); - file_part = pair.first; - zip_entry_name = pair.second; + if (DexFile::IsMultiDexLocation(filename)) { + file_part_storage = GetBaseLocation(filename); + file_part = file_part_storage.c_str(); + zip_entry_name = filename + file_part_storage.size() + 1; + DCHECK_EQ(zip_entry_name[-1], kMultiDexSeparator); } ScopedFd fd(OpenAndReadMagic(file_part, &magic, error_msg)); @@ -303,7 +302,7 @@ bool DexFile::OpenFromZip(const ZipArchive& zip_archive, const std::string& loca while (i < 100) { std::string name = StringPrintf("classes%zu.dex", i); - std::string fake_location = location + ":" + name; + std::string fake_location = location + kMultiDexSeparator + name; std::unique_ptr<const DexFile> next_dex_file(Open(zip_archive, name.c_str(), fake_location, error_msg, &error_code)); if (next_dex_file.get() == nullptr) { @@ -951,21 +950,6 @@ bool DexFile::IsMultiDexLocation(const char* location) { return strrchr(location, kMultiDexSeparator) != nullptr; } -std::pair<const char*, const char*> DexFile::SplitMultiDexLocation( - const char* location) { - const char* colon_ptr = strrchr(location, kMultiDexSeparator); - - // Check it's synthetic. - CHECK_NE(colon_ptr, static_cast<const char*>(nullptr)); - - size_t colon_index = colon_ptr - location; - char* tmp = new char[colon_index + 1]; - strncpy(tmp, location, colon_index); - tmp[colon_index] = 0; - - return std::make_pair(tmp, colon_ptr + 1); -} - std::string DexFile::GetMultiDexClassesDexName(size_t number, const char* dex_location) { if (number == 0) { return dex_location; @@ -976,26 +960,17 @@ std::string DexFile::GetMultiDexClassesDexName(size_t number, const char* dex_lo std::string DexFile::GetDexCanonicalLocation(const char* dex_location) { CHECK_NE(dex_location, static_cast<const char*>(nullptr)); - char* path = nullptr; - if (!IsMultiDexLocation(dex_location)) { - path = realpath(dex_location, nullptr); + std::string base_location = GetBaseLocation(dex_location); + const char* suffix = dex_location + base_location.size(); + DCHECK(suffix[0] == 0 || suffix[0] == kMultiDexSeparator); + UniqueCPtr<const char[]> path(realpath(base_location.c_str(), nullptr)); + if (path != nullptr && path.get() != base_location) { + return std::string(path.get()) + suffix; + } else if (suffix[0] == 0) { + return base_location; } else { - std::pair<const char*, const char*> pair = DexFile::SplitMultiDexLocation(dex_location); - const char* dex_real_location(realpath(pair.first, nullptr)); - delete pair.first; - if (dex_real_location != nullptr) { - int length = strlen(dex_real_location) + strlen(pair.second) + strlen(kMultiDexSeparatorString) + 1; - char* multidex_canonical_location = reinterpret_cast<char*>(malloc(sizeof(char) * length)); - snprintf(multidex_canonical_location, length, "%s" kMultiDexSeparatorString "%s", dex_real_location, pair.second); - free(const_cast<char*>(dex_real_location)); - path = multidex_canonical_location; - } + return dex_location; } - - // If realpath fails then we just copy the argument. - std::string result(path == nullptr ? dex_location : path); - free(path); - return result; } std::ostream& operator<<(std::ostream& os, const DexFile& dex_file) { diff --git a/runtime/dex_file.h b/runtime/dex_file.h index 118bd806c3..1b46a12ae8 100644 --- a/runtime/dex_file.h +++ b/runtime/dex_file.h @@ -389,14 +389,21 @@ class DexFile { // For normal dex files, location and base location coincide. If a dex file is part of a multidex // archive, the base location is the name of the originating jar/apk, stripped of any internal // classes*.dex path. - const std::string GetBaseLocation() const { - if (IsMultiDexLocation(location_.c_str())) { - std::pair<const char*, const char*> pair = SplitMultiDexLocation(location_.c_str()); - std::string res(pair.first); - delete[] pair.first; - return res; + static std::string GetBaseLocation(const char* location) { + const char* pos = strrchr(location, kMultiDexSeparator); + if (pos == nullptr) { + return location; } else { + return std::string(location, pos - location); + } + } + + std::string GetBaseLocation() const { + size_t pos = location_.rfind(kMultiDexSeparator); + if (pos == std::string::npos) { return location_; + } else { + return location_.substr(0, pos); } } @@ -918,13 +925,6 @@ class DexFile { // whether the string contains the separator character. static bool IsMultiDexLocation(const char* location); - // Splits a multidex location at the last separator character. The second component is a pointer - // to the character after the separator. The first is a copy of the substring up to the separator. - // - // Note: It's the caller's job to free the first component of the returned pair. - // Bug 15313523: gcc/libc++ don't allow a unique_ptr for the first component - static std::pair<const char*, const char*> SplitMultiDexLocation(const char* location); - // The base address of the memory mapping. const byte* const begin_; diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc index 330d045b42..d0c5603cc4 100644 --- a/runtime/dex_file_test.cc +++ b/runtime/dex_file_test.cc @@ -355,8 +355,8 @@ TEST_F(DexFileTest, GetMultiDexClassesDexName) { TEST_F(DexFileTest, GetDexCanonicalLocation) { ScratchFile file; - char* dex_location_real = realpath(file.GetFilename().c_str(), nullptr); - std::string dex_location(dex_location_real); + UniqueCPtr<const char[]> dex_location_real(realpath(file.GetFilename().c_str(), nullptr)); + std::string dex_location(dex_location_real.get()); ASSERT_EQ(dex_location, DexFile::GetDexCanonicalLocation(dex_location.c_str())); std::string multidex_location = DexFile::GetMultiDexClassesDexName(1, dex_location.c_str()); @@ -371,8 +371,6 @@ TEST_F(DexFileTest, GetDexCanonicalLocation) { ASSERT_EQ(multidex_location, DexFile::GetDexCanonicalLocation(multidex_location_sym.c_str())); ASSERT_EQ(0, unlink(dex_location_sym.c_str())); - - free(dex_location_real); } } // namespace art diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index d179a960b5..cf1c6e1918 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -140,7 +140,7 @@ OatFile::OatFile(const std::string& location, bool is_executable) } OatFile::~OatFile() { - STLDeleteValues(&oat_dex_files_); + STLDeleteElements(&oat_dex_files_storage_); if (dlopen_handle_ != NULL) { dlclose(dlopen_handle_); } @@ -238,7 +238,9 @@ bool OatFile::Setup(std::string* error_msg) { return false; } - for (size_t i = 0; i < GetOatHeader().GetDexFileCount(); i++) { + uint32_t dex_file_count = GetOatHeader().GetDexFileCount(); + oat_dex_files_storage_.reserve(dex_file_count); + for (size_t i = 0; i < dex_file_count; i++) { uint32_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat); if (UNLIKELY(dex_file_location_size == 0U)) { *error_msg = StringPrintf("In oat file '%s' found OatDexFile #%zd with empty location name", @@ -315,14 +317,24 @@ bool OatFile::Setup(std::string* error_msg) { return false; } - // Create the OatDexFile and add it to the owning map indexed by the dex file location. + std::string canonical_location = DexFile::GetDexCanonicalLocation(dex_file_location.c_str()); + + // Create the OatDexFile and add it to the owning container. OatDexFile* oat_dex_file = new OatDexFile(this, dex_file_location, + canonical_location, dex_file_checksum, dex_file_pointer, methods_offsets_pointer); + oat_dex_files_storage_.push_back(oat_dex_file); + + // Add the location and canonical location (if different) to the oat_dex_files_ table. StringPiece key(oat_dex_file->GetDexFileLocation()); oat_dex_files_.Put(key, oat_dex_file); + if (canonical_location != dex_file_location) { + StringPiece canonical_key(oat_dex_file->GetCanonicalDexFileLocation()); + oat_dex_files_.Put(canonical_key, oat_dex_file); + } } return true; } @@ -370,20 +382,13 @@ const OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location, oat_dex_file = secondary_lb->second; // May be nullptr. } else { // We haven't seen this dex_location before, we must check the canonical location. - if (UNLIKELY(oat_dex_files_by_canonical_location_.empty())) { - // Lazily fill in the oat_dex_files_by_canonical_location_. - for (const auto& entry : oat_dex_files_) { - const std::string& dex_location = entry.second->GetDexFileLocation(); - string_cache_.emplace_back(DexFile::GetDexCanonicalLocation(dex_location.c_str())); - StringPiece canonical_location_key(string_cache_.back()); - oat_dex_files_by_canonical_location_.Put(canonical_location_key, entry.second); - } - } std::string dex_canonical_location = DexFile::GetDexCanonicalLocation(dex_location); - StringPiece canonical_key(dex_canonical_location); - auto canonical_it = oat_dex_files_by_canonical_location_.find(canonical_key); - if (canonical_it != oat_dex_files_by_canonical_location_.end()) { - oat_dex_file = canonical_it->second; + if (dex_canonical_location != dex_location) { + StringPiece canonical_key(dex_canonical_location); + auto canonical_it = oat_dex_files_.find(canonical_key); + if (canonical_it != oat_dex_files_.end()) { + oat_dex_file = canonical_it->second; + } // else keep nullptr. } // else keep nullptr. // Copy the key to the string_cache_ and store the result in secondary map. @@ -408,11 +413,11 @@ const OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location, << " ( canonical path " << dex_canonical_location << ")" << " with checksum " << checksum << " in OatFile " << GetLocation(); if (kIsDebugBuild) { - for (Table::const_iterator it = oat_dex_files_.begin(); it != oat_dex_files_.end(); ++it) { + for (const OatDexFile* odf : oat_dex_files_storage_) { LOG(WARNING) << "OatFile " << GetLocation() - << " contains OatDexFile " << it->second->GetDexFileLocation() - << " (canonical path " << it->first << ")" - << " with checksum 0x" << std::hex << it->second->GetDexFileLocationChecksum(); + << " contains OatDexFile " << odf->GetDexFileLocation() + << " (canonical path " << odf->GetCanonicalDexFileLocation() << ")" + << " with checksum 0x" << std::hex << odf->GetDexFileLocationChecksum(); } } } @@ -420,21 +425,15 @@ const OatFile::OatDexFile* OatFile::GetOatDexFile(const char* dex_location, return NULL; } -std::vector<const OatFile::OatDexFile*> OatFile::GetOatDexFiles() const { - std::vector<const OatFile::OatDexFile*> result; - for (Table::const_iterator it = oat_dex_files_.begin(); it != oat_dex_files_.end(); ++it) { - result.push_back(it->second); - } - return result; -} - OatFile::OatDexFile::OatDexFile(const OatFile* oat_file, const std::string& dex_file_location, + const std::string& canonical_dex_file_location, uint32_t dex_file_location_checksum, const byte* dex_file_pointer, const uint32_t* oat_class_offsets_pointer) : oat_file_(oat_file), dex_file_location_(dex_file_location), + canonical_dex_file_location_(canonical_dex_file_location), dex_file_location_checksum_(dex_file_location_checksum), dex_file_pointer_(dex_file_pointer), oat_class_offsets_pointer_(oat_class_offsets_pointer) {} diff --git a/runtime/oat_file.h b/runtime/oat_file.h index 8cb47e20b8..2fd4f4c98a 100644 --- a/runtime/oat_file.h +++ b/runtime/oat_file.h @@ -214,6 +214,10 @@ class OatFile { // Opens the DexFile referred to by this OatDexFile from within the containing OatFile. const DexFile* OpenDexFile(std::string* error_msg) const; + const OatFile* GetOatFile() const { + return oat_file_; + } + // Returns the size of the DexFile refered to by this OatDexFile. size_t FileSize() const; @@ -222,6 +226,11 @@ class OatFile { return dex_file_location_; } + // Returns the canonical location of DexFile that was the source of this OatDexFile. + const std::string& GetCanonicalDexFileLocation() const { + return canonical_dex_file_location_; + } + // Returns checksum of original DexFile that was the source of this OatDexFile; uint32_t GetDexFileLocationChecksum() const { return dex_file_location_checksum_; @@ -235,12 +244,14 @@ class OatFile { private: OatDexFile(const OatFile* oat_file, const std::string& dex_file_location, + const std::string& canonical_dex_file_location, uint32_t dex_file_checksum, const byte* dex_file_pointer, const uint32_t* oat_class_offsets_pointer); const OatFile* const oat_file_; const std::string dex_file_location_; + const std::string canonical_dex_file_location_; const uint32_t dex_file_location_checksum_; const byte* const dex_file_pointer_; const uint32_t* const oat_class_offsets_pointer_; @@ -254,7 +265,9 @@ class OatFile { bool exception_if_not_found = true) const LOCKS_EXCLUDED(secondary_lookup_lock_); - std::vector<const OatDexFile*> GetOatDexFiles() const; + const std::vector<const OatDexFile*>& GetOatDexFiles() const { + return oat_dex_files_storage_; + } size_t Size() const { return End() - Begin(); @@ -307,6 +320,9 @@ class OatFile { // dlopen handle during runtime. void* dlopen_handle_; + // Owning storage for the OatDexFile objects. + std::vector<const OatDexFile*> oat_dex_files_storage_; + // NOTE: We use a StringPiece as the key type to avoid a memory allocation on every // lookup with a const char* key. The StringPiece doesn't own its backing storage, // therefore we're using the OatDexFile::dex_file_location_ as the backing storage @@ -314,11 +330,11 @@ class OatFile { // of keys in secondary_oat_dex_files_ and oat_dex_files_by_canonical_location_. typedef AllocationTrackingSafeMap<StringPiece, const OatDexFile*, kAllocatorTagOatFile> Table; - // Map each plain dex file location retrieved from the oat file to its OatDexFile. - // This map doesn't change after it's constructed in Setup() and therefore doesn't - // need any locking and provides the cheapest dex file lookup for GetOatDexFile() - // for a very frequent use case. Never contains a nullptr value. - Table oat_dex_files_; // Owns the OatDexFile* values. + // Map each location and canonical location (if different) retrieved from the + // oat file to its OatDexFile. This map doesn't change after it's constructed in Setup() + // and therefore doesn't need any locking and provides the cheapest dex file lookup + // for GetOatDexFile() for a very frequent use case. Never contains a nullptr value. + Table oat_dex_files_; // Lock guarding all members needed for secondary lookup in GetOatDexFile(). mutable Mutex secondary_lookup_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; @@ -329,10 +345,6 @@ class OatFile { // location and use oat_dex_files_by_canonical_location_. mutable Table secondary_oat_dex_files_ GUARDED_BY(secondary_lookup_lock_); - // Map the canonical location to an OatDexFile. This lazily constructed map is used - // when we're doing the secondary lookup for a given location for the first time. - mutable Table oat_dex_files_by_canonical_location_ GUARDED_BY(secondary_lookup_lock_); - // Cache of strings. Contains the backing storage for keys in the secondary_oat_dex_files_ // and the lazily initialized oat_dex_files_by_canonical_location_. // NOTE: We're keeping references to contained strings in form of StringPiece and adding diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 89ad505232..33b09a3b64 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -599,9 +599,7 @@ static bool OpenDexFilesFromImage(const std::vector<std::string>& dex_filenames, return false; } - std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file->GetOatDexFiles(); - for (size_t i = 0; i < oat_dex_files.size(); i++) { - const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i]; + for (const OatFile::OatDexFile* oat_dex_file : oat_file->GetOatDexFiles()) { if (oat_dex_file == nullptr) { *failures += 1; continue; diff --git a/runtime/utils.h b/runtime/utils.h index 7fb5bbd3da..50462b11b3 100644 --- a/runtime/utils.h +++ b/runtime/utils.h @@ -20,6 +20,7 @@ #include <pthread.h> #include <limits> +#include <memory> #include <string> #include <vector> @@ -502,6 +503,18 @@ void PushWord(std::vector<uint8_t>* buf, int32_t data); void EncodeUnsignedLeb128(uint32_t data, std::vector<uint8_t>* buf); void EncodeSignedLeb128(int32_t data, std::vector<uint8_t>* buf); +// Deleter using free() for use with std::unique_ptr<>. See also UniqueCPtr<> below. +struct FreeDelete { + // NOTE: Deleting a const object is valid but free() takes a non-const pointer. + void operator()(const void* ptr) const { + free(const_cast<void*>(ptr)); + } +}; + +// Alias for std::unique_ptr<> that uses the C function free() to delete objects. +template <typename T> +using UniqueCPtr = std::unique_ptr<T, FreeDelete>; + } // namespace art #endif // ART_RUNTIME_UTILS_H_ diff --git a/test/116-nodex2oat/nodex2oat.cc b/test/116-nodex2oat/nodex2oat.cc index 4326db0e54..04cac45f8e 100644 --- a/test/116-nodex2oat/nodex2oat.cc +++ b/test/116-nodex2oat/nodex2oat.cc @@ -28,9 +28,9 @@ class NoDex2OatTest { ScopedObjectAccess soa(Thread::Current()); mirror::Class* klass = soa.Decode<mirror::Class*>(cls); const DexFile& dex_file = klass->GetDexFile(); - const OatFile* oat_file = - Runtime::Current()->GetClassLinker()->FindOpenedOatFileForDexFile(dex_file); - return oat_file != nullptr; + const OatFile::OatDexFile* oat_dex_file = + Runtime::Current()->GetClassLinker()->FindOpenedOatDexFileForDexFile(dex_file); + return oat_dex_file != nullptr; } }; diff --git a/test/117-nopatchoat/nopatchoat.cc b/test/117-nopatchoat/nopatchoat.cc index ced7f6ef4f..5994653dc9 100644 --- a/test/117-nopatchoat/nopatchoat.cc +++ b/test/117-nopatchoat/nopatchoat.cc @@ -28,9 +28,9 @@ class NoPatchoatTest { ScopedObjectAccess soa(Thread::Current()); mirror::Class* klass = soa.Decode<mirror::Class*>(cls); const DexFile& dex_file = klass->GetDexFile(); - const OatFile* oat_file = - Runtime::Current()->GetClassLinker()->FindOpenedOatFileForDexFile(dex_file); - return oat_file != nullptr && oat_file->IsExecutable(); + const OatFile::OatDexFile* oat_dex_file = + Runtime::Current()->GetClassLinker()->FindOpenedOatDexFileForDexFile(dex_file); + return oat_dex_file != nullptr && oat_dex_file->GetOatFile()->IsExecutable(); } }; diff --git a/test/118-noimage-dex2oat/noimage-dex2oat.cc b/test/118-noimage-dex2oat/noimage-dex2oat.cc index 4a3d33cf0a..7340d9e7f7 100644 --- a/test/118-noimage-dex2oat/noimage-dex2oat.cc +++ b/test/118-noimage-dex2oat/noimage-dex2oat.cc @@ -28,9 +28,9 @@ class NoDex2OatTest { ScopedObjectAccess soa(Thread::Current()); mirror::Class* klass = soa.Decode<mirror::Class*>(cls); const DexFile& dex_file = klass->GetDexFile(); - const OatFile* oat_file = - Runtime::Current()->GetClassLinker()->FindOpenedOatFileForDexFile(dex_file); - return oat_file != nullptr; + const OatFile::OatDexFile* oat_dex_file = + Runtime::Current()->GetClassLinker()->FindOpenedOatDexFileForDexFile(dex_file); + return oat_dex_file != nullptr; } }; |