Add a method to OatFileAssistantContext to fetch all information.
artd can be multi-threaded, so it needs OatFileAssistantContext to be
thread-safe. This CL adds `OatFileAssistantContext::FetchAll`, which
fetches all information and makes subsequent operations read-only. artd
calls it the first time it initalizes OatFileAssistantContext.
Bug: 229268202
Test: adb shell pm art get-optimization-status \
com.google.android.youtube
Change-Id: Iacc36655e2cdbc7cb74b3f3cbf7f9ac1a1ffc28e
Merged-In: Iacc36655e2cdbc7cb74b3f3cbf7f9ac1a1ffc28e
(cherry picked from commit 93a13dab243e0141fadacb3137776aff882a1a69)
diff --git a/libartbase/arch/instruction_set.cc b/libartbase/arch/instruction_set.cc
index 9ec66fe..10a9919 100644
--- a/libartbase/arch/instruction_set.cc
+++ b/libartbase/arch/instruction_set.cc
@@ -17,6 +17,8 @@
#include "instruction_set.h"
#include "android-base/logging.h"
+#include "android-base/properties.h"
+#include "android-base/stringprintf.h"
#include "base/bit_utils.h"
#include "base/globals.h"
@@ -91,6 +93,45 @@
UNREACHABLE();
}
+std::vector<InstructionSet> GetSupportedInstructionSets(std::string* error_msg) {
+ std::string zygote_kinds = android::base::GetProperty("ro.zygote", {});
+ if (zygote_kinds.empty()) {
+ *error_msg = "Unable to get Zygote kinds";
+ return {};
+ }
+
+ switch (kRuntimeISA) {
+ case InstructionSet::kArm:
+ case InstructionSet::kArm64:
+ if (zygote_kinds == "zygote64_32" || zygote_kinds == "zygote32_64") {
+ return {InstructionSet::kArm64, InstructionSet::kArm};
+ } else if (zygote_kinds == "zygote64") {
+ return {InstructionSet::kArm64};
+ } else if (zygote_kinds == "zygote32") {
+ return {InstructionSet::kArm};
+ } else {
+ *error_msg = android::base::StringPrintf("Unknown Zygote kinds '%s'", zygote_kinds.c_str());
+ return {};
+ }
+ case InstructionSet::kX86:
+ case InstructionSet::kX86_64:
+ if (zygote_kinds == "zygote64_32" || zygote_kinds == "zygote32_64") {
+ return {InstructionSet::kX86_64, InstructionSet::kX86};
+ } else if (zygote_kinds == "zygote64") {
+ return {InstructionSet::kX86_64};
+ } else if (zygote_kinds == "zygote32") {
+ return {InstructionSet::kX86};
+ } else {
+ *error_msg = android::base::StringPrintf("Unknown Zygote kinds '%s'", zygote_kinds.c_str());
+ return {};
+ }
+ default:
+ *error_msg = android::base::StringPrintf("Unknown runtime ISA '%s'",
+ GetInstructionSetString(kRuntimeISA));
+ return {};
+ }
+}
+
namespace instruction_set_details {
static_assert(IsAligned<kPageSize>(kArmStackOverflowReservedBytes), "ARM gap not page aligned");
diff --git a/libartbase/arch/instruction_set.h b/libartbase/arch/instruction_set.h
index faf881d..155b186 100644
--- a/libartbase/arch/instruction_set.h
+++ b/libartbase/arch/instruction_set.h
@@ -19,6 +19,7 @@
#include <iosfwd>
#include <string>
+#include <vector>
#include "base/enums.h"
#include "base/macros.h"
@@ -195,6 +196,9 @@
InstructionSetAbort(isa);
}
+// Returns the instruction sets supported by the device, or an empty list on failure.
+std::vector<InstructionSet> GetSupportedInstructionSets(std::string* error_msg);
+
namespace instruction_set_details {
#if !defined(ART_STACK_OVERFLOW_GAP_arm) || !defined(ART_STACK_OVERFLOW_GAP_arm64) || \
diff --git a/runtime/oat_file_assistant_context.cc b/runtime/oat_file_assistant_context.cc
index d282d03..becc329 100644
--- a/runtime/oat_file_assistant_context.cc
+++ b/runtime/oat_file_assistant_context.cc
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "oat_file_assistant_context.h"
+
#include <memory>
#include <string>
#include <vector>
@@ -23,11 +25,11 @@
#include "arch/instruction_set.h"
#include "base/array_ref.h"
#include "base/logging.h"
+#include "base/mem_map.h"
#include "class_linker.h"
#include "dex/art_dex_file_loader.h"
#include "gc/heap.h"
#include "gc/space/image_space.h"
-#include "oat_file_assistant_context.h"
namespace art {
@@ -42,6 +44,8 @@
DCHECK_IMPLIES(
runtime_options_->boot_class_path_fds != nullptr,
runtime_options_->boot_class_path.size() == runtime_options_->boot_class_path_fds->size());
+ // Opening dex files and boot images require MemMap.
+ MemMap::Init();
}
OatFileAssistantContext::OatFileAssistantContext(Runtime* runtime)
@@ -90,6 +94,23 @@
return *runtime_options_;
}
+bool OatFileAssistantContext::FetchAll(std::string* error_msg) {
+ std::vector<InstructionSet> isas = GetSupportedInstructionSets(error_msg);
+ if (isas.empty()) {
+ return false;
+ }
+ for (InstructionSet isa : isas) {
+ GetBootImageInfoList(isa);
+ }
+ for (size_t i = 0; i < runtime_options_->boot_class_path.size(); i++) {
+ if (GetBcpChecksums(i, error_msg) == nullptr) {
+ return false;
+ }
+ }
+ GetApexVersions();
+ return true;
+}
+
const std::vector<OatFileAssistantContext::BootImageInfo>&
OatFileAssistantContext::GetBootImageInfoList(InstructionSet isa) {
if (auto it = boot_image_info_list_by_isa_.find(isa); it != boot_image_info_list_by_isa_.end()) {
diff --git a/runtime/oat_file_assistant_context.h b/runtime/oat_file_assistant_context.h
index 3288dc0..5f42ad9 100644
--- a/runtime/oat_file_assistant_context.h
+++ b/runtime/oat_file_assistant_context.h
@@ -30,6 +30,7 @@
// A helper class for OatFileAssistant that fetches and caches information including boot image
// checksums, bootclasspath checksums, and APEX versions. The same instance can be reused across
// OatFileAssistant calls on different dex files for different instruction sets.
+// This class is not thread-safe until `FetchAll` is called.
class OatFileAssistantContext {
public:
// Options that a runtime would take.
@@ -64,6 +65,9 @@
explicit OatFileAssistantContext(Runtime* runtime);
// Returns runtime options.
const RuntimeOptions& GetRuntimeOptions() const;
+ // Fetches all information that hasn't been fetched from disk amd caches it. All operations will
+ // be read-only after a successful call to this function.
+ bool FetchAll(std::string* error_msg);
// Returns information about the boot image of the given instruction set.
const std::vector<BootImageInfo>& GetBootImageInfoList(InstructionSet isa);
// Returns the checksums of the dex files in the BCP jar at the given index, or nullptr on error.