ART: Move boot-image loading to ImageSpace
Move the complete loading sequence for multi-image into ImageSpace.
This simplifies Heap initialization.
Test: m test-art-host
Change-Id: I5a9ee818ce26f205c641e96288f5b4c42257e202
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 8ff5e5a..3ed138c 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -294,66 +294,15 @@
}
// 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 6019540..c726944 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -1617,6 +1617,81 @@
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 0ba131b..489a289 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 @@
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 @@
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);
};