Make image test multi image
Required for testing multi image layout in future CLs.
Bug: 28640955
Test: clean-oat-host, test-art-host, device booting
(cherry picked from commit 25adcfb7dc81131add3a0a681ae18bced6f7a0e0)
Change-Id: I14809f56e711b4a87e01056c327eddbbd087f4ee
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 7234952..8a48604 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -76,9 +76,10 @@
file_.reset(new File(fd, GetFilename(), true));
}
-ScratchFile::ScratchFile(const ScratchFile& other, const char* suffix) {
- filename_ = other.GetFilename();
- filename_ += suffix;
+ScratchFile::ScratchFile(const ScratchFile& other, const char* suffix)
+ : ScratchFile(other.GetFilename() + suffix) {}
+
+ScratchFile::ScratchFile(const std::string& filename) : filename_(filename) {
int fd = open(filename_.c_str(), O_RDWR | O_CREAT, 0666);
CHECK_NE(-1, fd);
file_.reset(new File(fd, GetFilename(), true));
@@ -90,6 +91,18 @@
file_.reset(file);
}
+ScratchFile::ScratchFile(ScratchFile&& other) {
+ *this = std::move(other);
+}
+
+ScratchFile& ScratchFile::operator=(ScratchFile&& other) {
+ if (GetFile() != other.GetFile()) {
+ std::swap(filename_, other.filename_);
+ std::swap(file_, other.file_);
+ }
+ return *this;
+}
+
ScratchFile::~ScratchFile() {
Unlink();
}
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index b2090b7..2376e6a 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -40,8 +40,14 @@
public:
ScratchFile();
+ explicit ScratchFile(const std::string& filename);
+
ScratchFile(const ScratchFile& other, const char* suffix);
+ explicit ScratchFile(ScratchFile&& other);
+
+ ScratchFile& operator=(ScratchFile&& other);
+
explicit ScratchFile(File* file);
~ScratchFile();
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index cb5226b..11d4af8 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -327,9 +327,9 @@
continue;
}
- space::ImageSpace::CreateMultiImageLocations(image_file_name,
- boot_classpath,
- &image_file_names);
+ 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 << "'. "
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index e41c532..d17ef81 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -1619,9 +1619,54 @@
<< ",name=\"" << GetName() << "\"]";
}
-void ImageSpace::CreateMultiImageLocations(const std::string& input_image_file_name,
- const std::string& boot_classpath,
- std::vector<std::string>* image_file_names) {
+std::string ImageSpace::GetMultiImageBootClassPath(
+ const std::vector<const char*>& dex_locations,
+ const std::vector<const char*>& oat_filenames,
+ const std::vector<const char*>& image_filenames) {
+ DCHECK_GT(oat_filenames.size(), 1u);
+ // If the image filename was adapted (e.g., for our tests), we need to change this here,
+ // too, but need to strip all path components (they will be re-established when loading).
+ std::ostringstream bootcp_oss;
+ bool first_bootcp = true;
+ for (size_t i = 0; i < dex_locations.size(); ++i) {
+ if (!first_bootcp) {
+ bootcp_oss << ":";
+ }
+
+ std::string dex_loc = dex_locations[i];
+ std::string image_filename = image_filenames[i];
+
+ // Use the dex_loc path, but the image_filename name (without path elements).
+ size_t dex_last_slash = dex_loc.rfind('/');
+
+ // npos is max(size_t). That makes this a bit ugly.
+ size_t image_last_slash = image_filename.rfind('/');
+ size_t image_last_at = image_filename.rfind('@');
+ size_t image_last_sep = (image_last_slash == std::string::npos)
+ ? image_last_at
+ : (image_last_at == std::string::npos)
+ ? std::string::npos
+ : std::max(image_last_slash, image_last_at);
+ // Note: whenever image_last_sep == npos, +1 overflow means using the full string.
+
+ if (dex_last_slash == std::string::npos) {
+ dex_loc = image_filename.substr(image_last_sep + 1);
+ } else {
+ dex_loc = dex_loc.substr(0, dex_last_slash + 1) +
+ image_filename.substr(image_last_sep + 1);
+ }
+
+ // Image filenames already end with .art, no need to replace.
+
+ bootcp_oss << dex_loc;
+ first_bootcp = false;
+ }
+ return bootcp_oss.str();
+}
+
+void ImageSpace::ExtractMultiImageLocations(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;
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index c407259..0ba131b 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -125,10 +125,14 @@
// 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,
+ static void ExtractMultiImageLocations(const std::string& input_image_file_name,
const std::string& boot_classpath,
std::vector<std::string>* image_filenames);
+ static std::string GetMultiImageBootClassPath(const std::vector<const char*>& dex_locations,
+ const std::vector<const char*>& oat_filenames,
+ const std::vector<const char*>& 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/runtime.cc b/runtime/runtime.cc
index 15e3b1c..2be3b52 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -856,9 +856,9 @@
const OatHeader& boot_oat_header = oat_file->GetOatHeader();
const char* boot_cp = boot_oat_header.GetStoreValueByKey(OatHeader::kBootClassPathKey);
if (boot_cp != nullptr) {
- gc::space::ImageSpace::CreateMultiImageLocations(image_locations[0],
- boot_cp,
- &image_locations);
+ gc::space::ImageSpace::ExtractMultiImageLocations(image_locations[0],
+ boot_cp,
+ &image_locations);
}
}