diff options
| author | 2016-12-06 19:31:44 +0000 | |
|---|---|---|
| committer | 2016-12-06 19:31:45 +0000 | |
| commit | f99e0d0f28a60032d9f5e84191ab627ae7adf009 (patch) | |
| tree | 9fa3da165e19bf28f04de7901a302e8846e2cf44 | |
| parent | 6746874b84a44ab8dff18457eec546a1ebb22e93 (diff) | |
| parent | 2bd842872a0231b691cdff2833014413845937e7 (diff) | |
Merge "ART: Move boot-image loading to ImageSpace"
| -rw-r--r-- | runtime/gc/heap.cc | 65 | ||||
| -rw-r--r-- | runtime/gc/space/image_space.cc | 75 | ||||
| -rw-r--r-- | runtime/gc/space/image_space.h | 34 |
3 files changed, 105 insertions, 69 deletions
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 8ff5e5a062..3ed138c00e 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -294,66 +294,15 @@ Heap::Heap(size_t initial_size, } // Load image space(s). - if (!image_file_name.empty()) { - // For code reuse, handle this like a work queue. - std::vector<std::string> image_file_names; - image_file_names.push_back(image_file_name); - // The loaded spaces. Secondary images may fail to load, in which case we need to remove - // already added spaces. - std::vector<space::Space*> added_image_spaces; - uint8_t* const original_requested_alloc_space_begin = requested_alloc_space_begin; - for (size_t index = 0; index < image_file_names.size(); ++index) { - std::string& image_name = image_file_names[index]; - std::string error_msg; - std::unique_ptr<space::ImageSpace> boot_image_space_uptr = space::ImageSpace::CreateBootImage( - image_name.c_str(), - image_instruction_set, - index > 0, - &error_msg); - if (boot_image_space_uptr != nullptr) { - space::ImageSpace* boot_image_space = boot_image_space_uptr.release(); - AddSpace(boot_image_space); - added_image_spaces.push_back(boot_image_space); - // Oat files referenced by image files immediately follow them in memory, ensure alloc space - // isn't going to get in the middle - uint8_t* oat_file_end_addr = boot_image_space->GetImageHeader().GetOatFileEnd(); - CHECK_GT(oat_file_end_addr, boot_image_space->End()); - requested_alloc_space_begin = AlignUp(oat_file_end_addr, kPageSize); - boot_image_spaces_.push_back(boot_image_space); - - if (index == 0) { - // If this was the first space, check whether there are more images to load. - const OatFile* boot_oat_file = boot_image_space->GetOatFile(); - if (boot_oat_file == nullptr) { - continue; - } - - const OatHeader& boot_oat_header = boot_oat_file->GetOatHeader(); - const char* boot_classpath = - boot_oat_header.GetStoreValueByKey(OatHeader::kBootClassPathKey); - if (boot_classpath == nullptr) { - continue; - } - - space::ImageSpace::ExtractMultiImageLocations(image_file_name, - boot_classpath, - &image_file_names); - } - } else { - LOG(ERROR) << "Could not create image space with image file '" << image_file_name << "'. " - << "Attempting to fall back to imageless running. Error was: " << error_msg - << "\nAttempted image: " << image_name; - // Remove already loaded spaces. - for (space::Space* loaded_space : added_image_spaces) { - RemoveSpace(loaded_space); - delete loaded_space; - } - boot_image_spaces_.clear(); - requested_alloc_space_begin = original_requested_alloc_space_begin; - break; - } + if (space::ImageSpace::LoadBootImage(image_file_name, + image_instruction_set, + &boot_image_spaces_, + &requested_alloc_space_begin)) { + for (auto space : boot_image_spaces_) { + AddSpace(space); } } + /* requested_alloc_space_begin -> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- +- nonmoving space (non_moving_space_capacity)+- diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 6019540c9e..c7269440f0 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -1617,6 +1617,81 @@ std::unique_ptr<ImageSpace> ImageSpace::CreateBootImage(const char* image_locati return nullptr; } +bool ImageSpace::LoadBootImage(const std::string& image_file_name, + const InstructionSet image_instruction_set, + std::vector<space::ImageSpace*>* boot_image_spaces, + uint8_t** oat_file_end) { + DCHECK(boot_image_spaces != nullptr); + DCHECK(boot_image_spaces->empty()); + DCHECK(oat_file_end != nullptr); + DCHECK_NE(image_instruction_set, InstructionSet::kNone); + + if (image_file_name.empty()) { + return false; + } + + // For code reuse, handle this like a work queue. + std::vector<std::string> image_file_names; + image_file_names.push_back(image_file_name); + + bool error = false; + uint8_t* oat_file_end_tmp = *oat_file_end; + + for (size_t index = 0; index < image_file_names.size(); ++index) { + std::string& image_name = image_file_names[index]; + std::string error_msg; + std::unique_ptr<space::ImageSpace> boot_image_space_uptr = CreateBootImage( + image_name.c_str(), + image_instruction_set, + index > 0, + &error_msg); + if (boot_image_space_uptr != nullptr) { + space::ImageSpace* boot_image_space = boot_image_space_uptr.release(); + boot_image_spaces->push_back(boot_image_space); + // Oat files referenced by image files immediately follow them in memory, ensure alloc space + // isn't going to get in the middle + uint8_t* oat_file_end_addr = boot_image_space->GetImageHeader().GetOatFileEnd(); + CHECK_GT(oat_file_end_addr, boot_image_space->End()); + oat_file_end_tmp = AlignUp(oat_file_end_addr, kPageSize); + + if (index == 0) { + // If this was the first space, check whether there are more images to load. + const OatFile* boot_oat_file = boot_image_space->GetOatFile(); + if (boot_oat_file == nullptr) { + continue; + } + + const OatHeader& boot_oat_header = boot_oat_file->GetOatHeader(); + const char* boot_classpath = + boot_oat_header.GetStoreValueByKey(OatHeader::kBootClassPathKey); + if (boot_classpath == nullptr) { + continue; + } + + ExtractMultiImageLocations(image_file_name, boot_classpath, &image_file_names); + } + } else { + error = true; + LOG(ERROR) << "Could not create image space with image file '" << image_file_name << "'. " + << "Attempting to fall back to imageless running. Error was: " << error_msg + << "\nAttempted image: " << image_name; + break; + } + } + + if (error) { + // Remove already loaded spaces. + for (space::Space* loaded_space : *boot_image_spaces) { + delete loaded_space; + } + boot_image_spaces->clear(); + return false; + } + + *oat_file_end = oat_file_end_tmp; + return true; +} + std::unique_ptr<ImageSpace> ImageSpace::CreateFromAppImage(const char* image, const OatFile* oat_file, std::string* error_msg) { diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h index 0ba131b5bf..489a2890fe 100644 --- a/runtime/gc/space/image_space.h +++ b/runtime/gc/space/image_space.h @@ -17,6 +17,7 @@ #ifndef ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_ #define ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_ +#include "arch/instruction_set.h" #include "gc/accounting/space_bitmap.h" #include "runtime.h" #include "space.h" @@ -35,18 +36,15 @@ class ImageSpace : public MemMapSpace { return kSpaceTypeImageSpace; } - // Create a boot image space from an image file for a specified instruction - // set. Cannot be used for future allocation or collected. + // Load boot image spaces from a primary image file for a specified instruction set. // - // Create also opens the OatFile associated with the image file so - // that it be contiguously allocated with the image before the - // creation of the alloc space. The ReleaseOatFile will later be - // used to transfer ownership of the OatFile to the ClassLinker when - // it is initialized. - static std::unique_ptr<ImageSpace> CreateBootImage(const char* image, - InstructionSet image_isa, - bool secondary_image, - std::string* error_msg) + // On successful return, the loaded spaces are added to boot_image_spaces (which must be + // empty on entry) and oat_file_end is updated with the (page-aligned) end of the last + // oat file. + static bool LoadBootImage(const std::string& image_file_name, + const InstructionSet image_instruction_set, + std::vector<space::ImageSpace*>* boot_image_spaces, + uint8_t** oat_file_end) REQUIRES_SHARED(Locks::mutator_lock_); // Try to open an existing app image space. @@ -189,6 +187,20 @@ class ImageSpace : public MemMapSpace { friend class Space; private: + // Create a boot image space from an image file for a specified instruction + // set. Cannot be used for future allocation or collected. + // + // Create also opens the OatFile associated with the image file so + // that it be contiguously allocated with the image before the + // creation of the alloc space. The ReleaseOatFile will later be + // used to transfer ownership of the OatFile to the ClassLinker when + // it is initialized. + static std::unique_ptr<ImageSpace> CreateBootImage(const char* image, + InstructionSet image_isa, + bool secondary_image, + std::string* error_msg) + REQUIRES_SHARED(Locks::mutator_lock_); + DISALLOW_COPY_AND_ASSIGN(ImageSpace); }; |