Revert "Revert "ART: Fix up some multi-image cases""
This reverts commit de38b797c3e5ba3ee44c480db7093386975c51eb.
Fix up imgdiag for std::string and multi-image.
Bug: 26317072
Bug: 26320300
Change-Id: I94ce9528e9fea6fb3231a70c32db02d567143db9
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 3e432c7..7f67ae4 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -265,6 +265,9 @@
// 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;
for (size_t index = 0; index < image_file_names.size(); ++index) {
std::string& image_name = image_file_names[index];
@@ -277,6 +280,7 @@
ATRACE_END();
if (boot_image_space != nullptr) {
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();
@@ -298,66 +302,18 @@
continue;
}
- std::vector<std::string> images;
- Split(boot_classpath, ':', &images);
-
- // Add the rest into the list. We have to adjust locations, possibly:
- //
- // For example, image_file_name is /a/b/c/d/e.art
- // images[0] is f/c/d/e.art
- // ----------------------------------------------
- // images[1] is g/h/i/j.art -> /a/b/h/i/j.art
-
- // Derive pattern.
- std::vector<std::string> left;
- Split(image_file_name, '/', &left);
- std::vector<std::string> right;
- Split(images[0], '/', &right);
-
- size_t common = 1;
- while (common < left.size() && common < right.size()) {
- if (left[left.size() - common - 1] != right[right.size() - common - 1]) {
- break;
- }
- common++;
- }
-
- std::vector<std::string> prefix_vector(left.begin(), left.end() - common);
- std::string common_prefix = Join(prefix_vector, '/');
- if (!common_prefix.empty() && common_prefix[0] != '/' && image_file_name[0] == '/') {
- common_prefix = "/" + common_prefix;
- }
-
- // Apply pattern to images[1] .. images[n].
- for (size_t i = 1; i < images.size(); ++i) {
- std::string image = images[i];
-
- size_t rslash = std::string::npos;
- for (size_t j = 0; j < common; ++j) {
- if (rslash != std::string::npos) {
- rslash--;
- }
-
- rslash = image.rfind('/', rslash);
- if (rslash == std::string::npos) {
- rslash = 0;
- }
- if (rslash == 0) {
- break;
- }
- }
- std::string image_part = image.substr(rslash);
-
- std::string new_image = common_prefix + (StartsWith(image_part, "/") ? "" : "/") +
- image_part;
- image_file_names.push_back(new_image);
- }
+ space::ImageSpace::CreateMultiImageLocations(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;
- // TODO: Remove already loaded spaces.
+ // Remove already loaded spaces.
+ for (space::Space* loaded_space : added_image_spaces) {
+ RemoveSpace(loaded_space);
+ }
break;
}
}
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 952759c..dfdbd04 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -523,6 +523,9 @@
} else if (!ImageCreationAllowed(is_global_cache, &reason)) {
// Whether we can write to the cache.
success = false;
+ } else if (secondary_image) {
+ reason = "Should not have to patch secondary image.";
+ success = false;
} else {
// Try to relocate.
success = RelocateImage(image_location, cache_filename.c_str(), image_isa, &reason);
@@ -615,6 +618,9 @@
return nullptr;
} else if (!ImageCreationAllowed(is_global_cache, error_msg)) {
return nullptr;
+ } else if (secondary_image) {
+ *error_msg = "Cannot compile a secondary image.";
+ return nullptr;
} else if (!GenerateImage(cache_filename, image_isa, error_msg)) {
*error_msg = StringPrintf("Failed to generate image '%s': %s",
cache_filename.c_str(), error_msg->c_str());
@@ -969,6 +975,67 @@
<< ",name=\"" << GetName() << "\"]";
}
+void ImageSpace::CreateMultiImageLocations(const std::string& input_image_file_name,
+ const std::string& boot_classpath,
+ std::vector<std::string>* image_file_names) {
+ DCHECK(image_file_names != nullptr);
+
+ std::vector<std::string> images;
+ Split(boot_classpath, ':', &images);
+
+ // Add the rest into the list. We have to adjust locations, possibly:
+ //
+ // For example, image_file_name is /a/b/c/d/e.art
+ // images[0] is f/c/d/e.art
+ // ----------------------------------------------
+ // images[1] is g/h/i/j.art -> /a/b/h/i/j.art
+
+ // Derive pattern.
+ std::vector<std::string> left;
+ Split(input_image_file_name, '/', &left);
+ std::vector<std::string> right;
+ Split(images[0], '/', &right);
+
+ size_t common = 1;
+ while (common < left.size() && common < right.size()) {
+ if (left[left.size() - common - 1] != right[right.size() - common - 1]) {
+ break;
+ }
+ common++;
+ }
+
+ std::vector<std::string> prefix_vector(left.begin(), left.end() - common);
+ std::string common_prefix = Join(prefix_vector, '/');
+ if (!common_prefix.empty() && common_prefix[0] != '/' && input_image_file_name[0] == '/') {
+ common_prefix = "/" + common_prefix;
+ }
+
+ // Apply pattern to images[1] .. images[n].
+ for (size_t i = 1; i < images.size(); ++i) {
+ std::string image = images[i];
+
+ size_t rslash = std::string::npos;
+ for (size_t j = 0; j < common; ++j) {
+ if (rslash != std::string::npos) {
+ rslash--;
+ }
+
+ rslash = image.rfind('/', rslash);
+ if (rslash == std::string::npos) {
+ rslash = 0;
+ }
+ if (rslash == 0) {
+ break;
+ }
+ }
+ std::string image_part = image.substr(rslash);
+
+ std::string new_image = common_prefix + (StartsWith(image_part, "/") ? "" : "/") +
+ image_part;
+ image_file_names->push_back(new_image);
+ }
+}
+
} // namespace space
} // namespace gc
} // namespace art
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index a54358a..b8ae4a0 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -122,6 +122,12 @@
bool* has_data,
bool *is_global_cache);
+ // Use the input image filename to adapt the names in the given boot classpath to establish
+ // complete locations for secondary images.
+ static void CreateMultiImageLocations(const std::string& input_image_file_name,
+ const std::string& boot_classpath,
+ std::vector<std::string>* image_filenames);
+
// Return the end of the image which includes non-heap objects such as ArtMethods and ArtFields.
uint8_t* GetImageEnd() const {
return Begin() + GetImageHeader().GetImageSize();
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc
index cb80cc9..8543ff4 100644
--- a/runtime/oat_file_assistant.cc
+++ b/runtime/oat_file_assistant.cc
@@ -846,7 +846,12 @@
std::string OatFileAssistant::ImageLocation() {
Runtime* runtime = Runtime::Current();
- return runtime->GetHeap()->GetBootImageSpaces()[0]->GetImageLocation();
+ const std::vector<gc::space::ImageSpace*>& image_spaces =
+ runtime->GetHeap()->GetBootImageSpaces();
+ if (image_spaces.empty()) {
+ return "";
+ }
+ return image_spaces[0]->GetImageLocation();
}
const uint32_t* OatFileAssistant::GetRequiredDexChecksum() {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 98aa8d8..5c72629 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -827,13 +827,9 @@
const OatHeader& boot_oat_header = oat_file->GetOatHeader();
const char* boot_cp = boot_oat_header.GetStoreValueByKey(OatHeader::kBootClassPath);
if (boot_cp != nullptr) {
- std::vector<std::string> cp;
- Split(boot_cp, ':', &cp);
-
- if (cp.size() > 1) {
- // More images, enqueue (skipping the first).
- image_locations.insert(image_locations.end(), cp.begin() + 1, cp.end());
- }
+ gc::space::ImageSpace::CreateMultiImageLocations(image_locations[0],
+ boot_cp,
+ &image_locations);
}
}