summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/elf_patcher.cc3
-rw-r--r--runtime/class_linker.cc56
-rw-r--r--runtime/class_linker.h15
-rw-r--r--runtime/dex_file.cc57
-rw-r--r--runtime/dex_file.h26
-rw-r--r--runtime/dex_file_test.cc6
-rw-r--r--runtime/oat_file.cc55
-rw-r--r--runtime/oat_file.h32
-rw-r--r--runtime/runtime.cc4
-rw-r--r--runtime/utils.h13
-rw-r--r--test/116-nodex2oat/nodex2oat.cc6
-rw-r--r--test/117-nopatchoat/nopatchoat.cc6
-rw-r--r--test/118-noimage-dex2oat/noimage-dex2oat.cc6
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;
}
};