Treat no profile the same as empty profile for app image generation
Prevent cases where a full app image gets generated since this should
be avoided for performance reasons.
Bug: 77340429
Test: test-art-host-gtest
(cherry picked from commit f85b3db7f63ef915bb48439c5f8ca34113bd524b)
Merged-In: Ib320fa7c56b4bf78af0df823a06b6881e6af7103
Change-Id: Iafd4b083362792da6c3b4c385fbcb3627e9c342a
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index ffd359a..44c9816 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -404,6 +404,7 @@
UsageError(" Example: --very-large-app-threshold=100000000");
UsageError("");
UsageError(" --app-image-fd=<file-descriptor>: specify output file descriptor for app image.");
+ UsageError(" The image is non-empty only if a profile is passed in.");
UsageError(" Example: --app-image-fd=10");
UsageError("");
UsageError(" --app-image-file=<file-name>: specify a file name for app image.");
@@ -1479,9 +1480,15 @@
}
void LoadClassProfileDescriptors() {
- if (profile_compilation_info_ != nullptr && IsImage()) {
- Runtime* runtime = Runtime::Current();
- CHECK(runtime != nullptr);
+ if (!IsImage()) {
+ return;
+ }
+ // If we don't have a profile, treat it as an empty set of classes. b/77340429
+ if (image_classes_ == nullptr) {
+ // May be non-null when --image-classes is passed in, in that case avoid clearing the list.
+ image_classes_.reset(new std::unordered_set<std::string>());
+ }
+ if (profile_compilation_info_ != nullptr) {
// Filter out class path classes since we don't want to include these in the image.
image_classes_.reset(
new std::unordered_set<std::string>(
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 0cd39ac..c890f8b 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -2093,4 +2093,36 @@
ASSERT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) != 0) << status << " " << output_;
}
+TEST_F(Dex2oatTest, AppImageNoProfile) {
+ ScratchFile app_image_file;
+ const std::string out_dir = GetScratchDir();
+ const std::string odex_location = out_dir + "/base.odex";
+ GenerateOdexForTest(GetTestDexFileName("ManyMethods"),
+ odex_location,
+ CompilerFilter::Filter::kSpeedProfile,
+ { "--app-image-fd=" + std::to_string(app_image_file.GetFd()) },
+ true, // expect_success
+ false, // use_fd
+ [](const OatFile&) {});
+ // Open our generated oat file.
+ std::string error_msg;
+ std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+ odex_location.c_str(),
+ nullptr,
+ nullptr,
+ false,
+ /*low_4gb*/false,
+ odex_location.c_str(),
+ &error_msg));
+ ASSERT_TRUE(odex_file != nullptr);
+ ImageHeader header = {};
+ ASSERT_TRUE(app_image_file.GetFile()->PreadFully(
+ reinterpret_cast<void*>(&header),
+ sizeof(header),
+ /*offset*/ 0u)) << app_image_file.GetFile()->GetLength();
+ EXPECT_GT(header.GetImageSection(ImageHeader::kSectionObjects).Size(), 0u);
+ EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtMethods).Size(), 0u);
+ EXPECT_EQ(header.GetImageSection(ImageHeader::kSectionArtFields).Size(), 0u);
+}
+
} // namespace art