diff options
author | 2015-12-10 09:33:21 -0800 | |
---|---|---|
committer | 2015-12-10 10:28:19 -0800 | |
commit | ceb07b3285eaab350a8cd12f7d74be3e40a255dd (patch) | |
tree | 4d5f7c1ab47ea6b8399d2112b69a818a0519b2de /runtime/gc/space/image_space.cc | |
parent | 836ee764c86892aff1dca6b0f8b27e32c7374cc7 (diff) |
Revert "Revert "Add support for LZ4 compressed image files""
Needed to call compiler_driver_->SetSupportBootImageFixup(false).
Bug: 22858531
This reverts commit 83d4d72aa0e4170209ab50c67ba22e46b71352c1.
Change-Id: Iaed6a810a0c088f1f2c57cf2f12087f3978a3de1
Diffstat (limited to 'runtime/gc/space/image_space.cc')
-rw-r--r-- | runtime/gc/space/image_space.cc | 101 |
1 files changed, 76 insertions, 25 deletions
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index e2b2431054..8f67c213a6 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -17,12 +17,12 @@ #include "image_space.h" #include <dirent.h> +#include <lz4.h> +#include <random> #include <sys/statvfs.h> #include <sys/types.h> #include <unistd.h> -#include <random> - #include "art_method.h" #include "base/macros.h" #include "base/stl_util.h" @@ -677,11 +677,12 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat *error_msg = StringPrintf("Invalid image header in '%s'", image_filename); return nullptr; } - // Check that the file is large enough. - uint64_t image_file_size = static_cast<uint64_t>(file->GetLength()); - if (image_header.GetImageSize() > image_file_size) { - *error_msg = StringPrintf("Image file too small for image heap: %" PRIu64 " vs. %zu.", - image_file_size, image_header.GetImageSize()); + // Check that the file is larger or equal to the header size + data size. + const uint64_t image_file_size = static_cast<uint64_t>(file->GetLength()); + if (image_file_size < sizeof(ImageHeader) + image_header.GetDataSize()) { + *error_msg = StringPrintf("Image file truncated: %" PRIu64 " vs. %" PRIu64 ".", + image_file_size, + image_header.GetDataSize()); return nullptr; } @@ -697,7 +698,11 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat } const auto& bitmap_section = image_header.GetImageSection(ImageHeader::kSectionImageBitmap); - auto end_of_bitmap = static_cast<size_t>(bitmap_section.End()); + // The location we want to map from is the first aligned page after the end of the stored + // (possibly compressed) data. + const size_t image_bitmap_offset = RoundUp(sizeof(image_header) + image_header.GetDataSize(), + kPageSize); + const size_t end_of_bitmap = image_bitmap_offset + bitmap_section.Size(); if (end_of_bitmap != image_file_size) { *error_msg = StringPrintf( "Image file size does not equal end of bitmap: size=%" PRIu64 " vs. %zu.", image_file_size, @@ -706,16 +711,60 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat } // Note: The image header is part of the image due to mmap page alignment required of offset. - std::unique_ptr<MemMap> map(MemMap::MapFileAtAddress(image_header.GetImageBegin(), - image_header.GetImageSize(), - PROT_READ | PROT_WRITE, + std::unique_ptr<MemMap> map; + if (image_header.GetStorageMode() == ImageHeader::kStorageModeUncompressed) { + map.reset(MemMap::MapFileAtAddress(image_header.GetImageBegin(), + image_header.GetImageSize(), + PROT_READ | PROT_WRITE, + MAP_PRIVATE, + file->Fd(), + 0, + /*low_4gb*/false, + /*reuse*/false, + image_filename, + error_msg)); + } else { + // Reserve output and decompress into it. + map.reset(MemMap::MapAnonymous(image_location, + image_header.GetImageBegin(), + image_header.GetImageSize(), + PROT_READ | PROT_WRITE, + /*low_4gb*/false, + /*reuse*/false, + error_msg)); + if (map != nullptr) { + const size_t stored_size = image_header.GetDataSize(); + const size_t write_offset = sizeof(image_header); // Skip the header. + std::unique_ptr<MemMap> temp_map(MemMap::MapFile(sizeof(ImageHeader) + stored_size, + PROT_READ, MAP_PRIVATE, file->Fd(), - 0, + /*offset*/0, /*low_4gb*/false, - /*reuse*/false, image_filename, error_msg)); + if (temp_map == nullptr) { + DCHECK(!error_msg->empty()); + return nullptr; + } + memcpy(map->Begin(), &image_header, sizeof(image_header)); + const uint64_t start = NanoTime(); + const size_t decompressed_size = LZ4_decompress_safe( + reinterpret_cast<char*>(temp_map->Begin()) + sizeof(ImageHeader), + reinterpret_cast<char*>(map->Begin()) + write_offset, + stored_size, + map->Size()); + // TODO: VLOG(image) + VLOG(class_linker) << "Decompressing image took " << PrettyDuration(NanoTime() - start); + if (decompressed_size + sizeof(ImageHeader) != image_header.GetImageSize()) { + *error_msg = StringPrintf("Decompressed size does not match expected image size %zu vs %zu", + decompressed_size + sizeof(ImageHeader), + image_header.GetImageSize()); + return nullptr; + } + } + } + if (map == nullptr) { DCHECK(!error_msg->empty()); return nullptr; @@ -723,16 +772,16 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat CHECK_EQ(image_header.GetImageBegin(), map->Begin()); DCHECK_EQ(0, memcmp(&image_header, map->Begin(), sizeof(ImageHeader))); - std::unique_ptr<MemMap> image_map(MemMap::MapFileAtAddress(nullptr, - bitmap_section.Size(), - PROT_READ, MAP_PRIVATE, - file->Fd(), - bitmap_section.Offset(), - /*low_4gb*/false, - /*reuse*/false, - image_filename, - error_msg)); - if (image_map.get() == nullptr) { + std::unique_ptr<MemMap> image_bitmap_map(MemMap::MapFileAtAddress(nullptr, + bitmap_section.Size(), + PROT_READ, MAP_PRIVATE, + file->Fd(), + image_bitmap_offset, + /*low_4gb*/false, + /*reuse*/false, + image_filename, + error_msg)); + if (image_bitmap_map == nullptr) { *error_msg = StringPrintf("Failed to map image bitmap: %s", error_msg->c_str()); return nullptr; } @@ -741,9 +790,11 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat bitmap_index)); std::unique_ptr<accounting::ContinuousSpaceBitmap> bitmap( accounting::ContinuousSpaceBitmap::CreateFromMemMap( - bitmap_name, image_map.release(), reinterpret_cast<uint8_t*>(map->Begin()), + bitmap_name, + image_bitmap_map.release(), + reinterpret_cast<uint8_t*>(map->Begin()), accounting::ContinuousSpaceBitmap::ComputeHeapSize(bitmap_section.Size()))); - if (bitmap.get() == nullptr) { + if (bitmap == nullptr) { *error_msg = StringPrintf("Could not create bitmap '%s'", bitmap_name.c_str()); return nullptr; } |