summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2014-09-05 14:01:17 +0100
committerVladimir Marko <vmarko@google.com>2014-09-10 16:02:14 +0100
commitaa4497db59f1eeec954f2ba5da6d458fcdf9b3a4 (patch)
tree1efe5c6c5fe93ae73b6ad02db1a4ac368c71c00e /runtime
parent6724a9531c92368491dd17937d0087f73a7c0642 (diff)
downloadandroid_art-aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4.tar.gz
android_art-aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4.tar.bz2
android_art-aa4497db59f1eeec954f2ba5da6d458fcdf9b3a4.zip
Improve dex location canonicalization-related performance.
Eagerly add canonical dex file locations to the OatFile's primary lookup map in Setup(). This moves the boot.oat work from every app startup to the zygote initialization. Since we always ended up initializing the canonical location map anyway due to the way that we're loading dex files, the lazy initialization didn't save anything. Clean up dex file name canonicalization to make sure we free() the memory returned by realpath() rather than using std::unique_ptr<> with the default deleter. Avoid some unnecessary duplicate OatDexFile lookups. Bug: 16828525 Bug: 17346103 Change-Id: Id8fbc8992f62996138eb2006a0046c6529747c09
Diffstat (limited to 'runtime')
-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
9 files changed, 127 insertions, 137 deletions
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_