Add --preloaded-classes flag to dex2oat.
So that dex2oat knows which classes will be initialized by the zygote. We will use
this information in a follow-up CL to change how we compile static methods of known
uninitialized classes.
Test: m
Bug: 162110941
Change-Id: I82d3ca465e6ff92d3d81b8d6c14a404e3a62152d
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index b90a789..57b81b6 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1070,6 +1070,7 @@
AssignIfExists(args, M::AndroidRoot, &android_root_);
AssignIfExists(args, M::Profile, &profile_files_);
AssignIfExists(args, M::ProfileFd, &profile_file_fds_);
+ AssignIfExists(args, M::PreloadedClasses, &preloaded_classes_files_);
AssignIfExists(args, M::RuntimeOptions, &runtime_args_);
AssignIfExists(args, M::SwapFile, &swap_file_name_);
AssignIfExists(args, M::SwapFileFd, &swap_fd_);
@@ -1424,6 +1425,10 @@
return dex2oat::ReturnCode::kOther;
}
+ if (!PreparePreloadedClasses()) {
+ return dex2oat::ReturnCode::kOther;
+ }
+
callbacks_.reset(new QuickCompilerCallbacks(
// For class verification purposes, boot image extension is the same as boot image.
(IsBootImage() || IsBootImageExtension())
@@ -2520,6 +2525,16 @@
return true;
}
+ bool PreparePreloadedClasses() {
+ preloaded_classes_.reset(new HashSet<std::string>());
+ for (const std::string& file : preloaded_classes_files_) {
+ ReadCommentedInputFromFile<HashSet<std::string>>(file.c_str(),
+ nullptr,
+ preloaded_classes_.get());
+ }
+ return true;
+ }
+
void PruneNonExistentDexFiles() {
DCHECK_EQ(dex_filenames_.size(), dex_locations_.size());
size_t kept = 0u;
@@ -2748,6 +2763,17 @@
return true;
}
+ template <typename T>
+ static void ReadCommentedInputFromFile(
+ const char* input_filename, std::function<std::string(const char*)>* process, T* output) {
+ auto input_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(input_filename, "r"), fclose};
+ if (!input_file) {
+ LOG(ERROR) << "Failed to open input file " << input_filename;
+ return;
+ }
+ ReadCommentedInputStream<T>(input_file.get(), process, output);
+ }
+
// Read lines from the given file, dropping comments and empty lines. Post-process each line with
// the given function.
template <typename T>
@@ -2758,7 +2784,9 @@
LOG(ERROR) << "Failed to open input file " << input_filename;
return nullptr;
}
- return ReadCommentedInputStream<T>(input_file.get(), process);
+ std::unique_ptr<T> output(new T());
+ ReadCommentedInputStream<T>(input_file.get(), process, output.get());
+ return output;
}
// Read lines from the given fd, dropping comments and empty lines. Post-process each line with
@@ -2771,16 +2799,17 @@
LOG(ERROR) << "Failed to re-open input fd from /prof/self/fd/" << input_fd;
return nullptr;
}
- return ReadCommentedInputStream<T>(input_file.get(), process);
+ std::unique_ptr<T> output(new T());
+ ReadCommentedInputStream<T>(input_file.get(), process, output.get());
+ return output;
}
// Read lines from the given stream, dropping comments and empty lines. Post-process each line
// with the given function.
- template <typename T>
- static std::unique_ptr<T> ReadCommentedInputStream(
+ template <typename T> static void ReadCommentedInputStream(
std::FILE* in_stream,
- std::function<std::string(const char*)>* process) {
- std::unique_ptr<T> output(new T());
+ std::function<std::string(const char*)>* process,
+ T* output) {
char* line = nullptr;
size_t line_alloc = 0;
ssize_t len = 0;
@@ -2799,7 +2828,6 @@
}
}
free(line);
- return output;
}
void LogCompletionTime() {
@@ -2892,6 +2920,7 @@
const char* dirty_image_objects_filename_;
int dirty_image_objects_fd_;
std::unique_ptr<HashSet<std::string>> dirty_image_objects_;
+ std::unique_ptr<HashSet<std::string>> preloaded_classes_;
std::unique_ptr<std::vector<std::string>> passes_to_run_;
bool is_host_;
std::string android_root_;
@@ -2920,6 +2949,7 @@
int app_image_fd_;
std::vector<std::string> profile_files_;
std::vector<int> profile_file_fds_;
+ std::vector<std::string> preloaded_classes_files_;
std::unique_ptr<ProfileCompilationInfo> profile_compilation_info_;
TimingLogger* timings_;
std::vector<std::vector<const DexFile*>> dex_files_per_oat_file_;
diff --git a/dex2oat/dex2oat_options.cc b/dex2oat/dex2oat_options.cc
index b6fa71e..e8439cc 100644
--- a/dex2oat/dex2oat_options.cc
+++ b/dex2oat/dex2oat_options.cc
@@ -255,7 +255,11 @@
.IntoKey(M::ProfileFd)
.Define("--no-inline-from=_")
.WithType<std::string>()
- .IntoKey(M::NoInlineFrom);
+ .IntoKey(M::NoInlineFrom)
+ .Define("--preloaded-classes=_")
+ .WithType<std::vector<std::string>>().AppendValues()
+ .WithHelp("Specify files containing list of classes preloaded in the zygote.")
+ .IntoKey(M::PreloadedClasses);
}
static void AddTargetMappings(Builder& builder) {
diff --git a/dex2oat/dex2oat_options.def b/dex2oat/dex2oat_options.def
index 43a2b22..2b47735 100644
--- a/dex2oat/dex2oat_options.def
+++ b/dex2oat/dex2oat_options.def
@@ -103,5 +103,6 @@
DEX2OAT_OPTIONS_KEY (Unit, ForceAllowOjInlines)
DEX2OAT_OPTIONS_KEY (std::string, ApexVersions)
DEX2OAT_OPTIONS_KEY (Unit, ForcePaletteCompilationHooks)
+DEX2OAT_OPTIONS_KEY (std::vector<std::string>, PreloadedClasses)
#undef DEX2OAT_OPTIONS_KEY