Remove unnecessary indirection from MemMap.
Avoid plain MemMap pointers being passed around by changing
the MemMap to moveable and return MemMap objects by value.
Previously we could have a valid zero-size MemMap but this
is now forbidden.
MemMap::RemapAtEnd() is changed to avoid the explicit call
to munmap(); mmap() with MAP_FIXED automatically removes
old mappings for overlapping regions.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: Pixel 2 XL boots.
Test: m test-art-target-gtest
Test: testrunner.py --target --optimizing
Change-Id: I12bd453c26a396edc20eb141bfd4dad20923f170
diff --git a/libdexfile/dex/art_dex_file_loader.cc b/libdexfile/dex/art_dex_file_loader.cc
index cc7d7aa..1846a13 100644
--- a/libdexfile/dex/art_dex_file_loader.cc
+++ b/libdexfile/dex/art_dex_file_loader.cc
@@ -23,6 +23,7 @@
#include "base/file_magic.h"
#include "base/file_utils.h"
+#include "base/mem_map.h"
#include "base/stl_util.h"
#include "base/systrace.h"
#include "base/unix_file/fd_file.h"
@@ -38,14 +39,14 @@
class MemMapContainer : public DexFileContainer {
public:
- explicit MemMapContainer(std::unique_ptr<MemMap>&& mem_map) : mem_map_(std::move(mem_map)) { }
+ explicit MemMapContainer(MemMap&& mem_map) : mem_map_(std::move(mem_map)) { }
virtual ~MemMapContainer() OVERRIDE { }
int GetPermissions() OVERRIDE {
- if (mem_map_.get() == nullptr) {
+ if (!mem_map_.IsValid()) {
return 0;
} else {
- return mem_map_->GetProtect();
+ return mem_map_.GetProtect();
}
}
@@ -55,24 +56,24 @@
bool EnableWrite() OVERRIDE {
CHECK(IsReadOnly());
- if (mem_map_.get() == nullptr) {
+ if (!mem_map_.IsValid()) {
return false;
} else {
- return mem_map_->Protect(PROT_READ | PROT_WRITE);
+ return mem_map_.Protect(PROT_READ | PROT_WRITE);
}
}
bool DisableWrite() OVERRIDE {
CHECK(!IsReadOnly());
- if (mem_map_.get() == nullptr) {
+ if (!mem_map_.IsValid()) {
return false;
} else {
- return mem_map_->Protect(PROT_READ);
+ return mem_map_.Protect(PROT_READ);
}
}
private:
- std::unique_ptr<MemMap> mem_map_;
+ MemMap mem_map_;
DISALLOW_COPY_AND_ASSIGN(MemMapContainer);
};
@@ -180,22 +181,24 @@
std::unique_ptr<const DexFile> ArtDexFileLoader::Open(const std::string& location,
uint32_t location_checksum,
- std::unique_ptr<MemMap> map,
+ MemMap&& map,
bool verify,
bool verify_checksum,
std::string* error_msg) const {
ScopedTrace trace(std::string("Open dex file from mapped-memory ") + location);
- CHECK(map.get() != nullptr);
+ CHECK(map.IsValid());
- if (map->Size() < sizeof(DexFile::Header)) {
+ size_t size = map.Size();
+ if (size < sizeof(DexFile::Header)) {
*error_msg = StringPrintf(
"DexFile: failed to open dex file '%s' that is too short to have a header",
location.c_str());
return nullptr;
}
- std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
- map->Size(),
+ uint8_t* begin = map.Begin();
+ std::unique_ptr<DexFile> dex_file = OpenCommon(begin,
+ size,
/*data_base*/ nullptr,
/*data_size*/ 0u,
location,
@@ -285,7 +288,7 @@
std::string* error_msg) const {
ScopedTrace trace(std::string("Open dex file ") + std::string(location));
CHECK(!location.empty());
- std::unique_ptr<MemMap> map;
+ MemMap map;
{
File delayed_close(fd, /* check_usage */ false);
struct stat sbuf;
@@ -300,31 +303,33 @@
return nullptr;
}
size_t length = sbuf.st_size;
- map.reset(MemMap::MapFile(length,
- PROT_READ,
- mmap_shared ? MAP_SHARED : MAP_PRIVATE,
- fd,
- 0,
- /*low_4gb*/false,
- location.c_str(),
- error_msg));
- if (map == nullptr) {
+ map = MemMap::MapFile(length,
+ PROT_READ,
+ mmap_shared ? MAP_SHARED : MAP_PRIVATE,
+ fd,
+ 0,
+ /*low_4gb*/false,
+ location.c_str(),
+ error_msg);
+ if (!map.IsValid()) {
DCHECK(!error_msg->empty());
return nullptr;
}
}
- if (map->Size() < sizeof(DexFile::Header)) {
+ const uint8_t* begin = map.Begin();
+ size_t size = map.Size();
+ if (size < sizeof(DexFile::Header)) {
*error_msg = StringPrintf(
"DexFile: failed to open dex file '%s' that is too short to have a header",
location.c_str());
return nullptr;
}
- const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(map->Begin());
+ const DexFile::Header* dex_header = reinterpret_cast<const DexFile::Header*>(begin);
- std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
- map->Size(),
+ std::unique_ptr<DexFile> dex_file = OpenCommon(begin,
+ size,
/*data_base*/ nullptr,
/*data_size*/ 0u,
location,
@@ -366,7 +371,7 @@
return nullptr;
}
- std::unique_ptr<MemMap> map;
+ MemMap map;
if (zip_entry->IsUncompressed()) {
if (!zip_entry->IsAlignedTo(alignof(DexFile::Header))) {
// Do not mmap unaligned ZIP entries because
@@ -376,8 +381,8 @@
<< "Falling back to extracting file.";
} else {
// Map uncompressed files within zip as file-backed to avoid a dirty copy.
- map.reset(zip_entry->MapDirectlyFromFile(location.c_str(), /*out*/error_msg));
- if (map == nullptr) {
+ map = zip_entry->MapDirectlyFromFile(location.c_str(), /*out*/error_msg);
+ if (!map.IsValid()) {
LOG(WARNING) << "Can't mmap dex file " << location << "!" << entry_name << " directly; "
<< "is your ZIP file corrupted? Falling back to extraction.";
// Try again with Extraction which still has a chance of recovery.
@@ -385,21 +390,23 @@
}
}
- if (map == nullptr) {
+ if (!map.IsValid()) {
// Default path for compressed ZIP entries,
// and fallback for stored ZIP entries.
- map.reset(zip_entry->ExtractToMemMap(location.c_str(), entry_name, error_msg));
+ map = zip_entry->ExtractToMemMap(location.c_str(), entry_name, error_msg);
}
- if (map == nullptr) {
+ if (!map.IsValid()) {
*error_msg = StringPrintf("Failed to extract '%s' from '%s': %s", entry_name, location.c_str(),
error_msg->c_str());
*error_code = DexFileLoaderErrorCode::kExtractToMemoryError;
return nullptr;
}
VerifyResult verify_result;
- std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
- map->Size(),
+ uint8_t* begin = map.Begin();
+ size_t size = map.Size();
+ std::unique_ptr<DexFile> dex_file = OpenCommon(begin,
+ size,
/*data_base*/ nullptr,
/*data_size*/ 0u,
location,