ART: Allow to change boot image pickup order
Allow to change the pickup order of boot image files between
system-first and data-first.
Bug: 126307038
Test: m test-art-host
Test: Boot device with image in /data/dalvik-cache
Change-Id: Id80cfc06aeb023559e1a3706833e57ba4880f43b
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 5c171e6..6f72740 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -205,7 +205,8 @@
bool use_generational_cc,
uint64_t min_interval_homogeneous_space_compaction_by_oom,
bool dump_region_info_before_gc,
- bool dump_region_info_after_gc)
+ bool dump_region_info_after_gc,
+ space::ImageSpaceLoadingOrder image_space_loading_order)
: non_moving_space_(nullptr),
rosalloc_space_(nullptr),
dlmalloc_space_(nullptr),
@@ -370,6 +371,7 @@
boot_class_path_locations,
image_file_name,
image_instruction_set,
+ image_space_loading_order,
heap_reservation_size,
&boot_image_spaces,
&heap_reservation)) {
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 18dfbf5..898a51c 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -35,6 +35,7 @@
#include "gc/collector/iteration.h"
#include "gc/collector_type.h"
#include "gc/gc_cause.h"
+#include "gc/space/image_space_loading_order.h"
#include "gc/space/large_object_space.h"
#include "handle.h"
#include "obj_ptr.h"
@@ -215,7 +216,8 @@
bool use_generational_cc,
uint64_t min_interval_homogeneous_space_compaction_by_oom,
bool dump_region_info_before_gc,
- bool dump_region_info_after_gc);
+ bool dump_region_info_after_gc,
+ space::ImageSpaceLoadingOrder image_space_loading_order);
~Heap();
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 4a2dbf5..173e879 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -259,6 +259,7 @@
std::unique_ptr<ImageHeader> ImageSpace::ReadImageHeader(const char* image_location,
const InstructionSet image_isa,
+ ImageSpaceLoadingOrder order,
std::string* error_msg) {
std::string system_filename;
bool has_system = false;
@@ -274,10 +275,20 @@
&dalvik_cache_exists,
&has_cache,
&is_global_cache)) {
- if (has_system) {
- return ReadSpecificImageHeader(system_filename.c_str(), error_msg);
- } else if (has_cache) {
- return ReadSpecificImageHeader(cache_filename.c_str(), error_msg);
+ if (order == ImageSpaceLoadingOrder::kSystemFirst) {
+ if (has_system) {
+ return ReadSpecificImageHeader(system_filename.c_str(), error_msg);
+ }
+ if (has_cache) {
+ return ReadSpecificImageHeader(cache_filename.c_str(), error_msg);
+ }
+ } else {
+ if (has_cache) {
+ return ReadSpecificImageHeader(cache_filename.c_str(), error_msg);
+ }
+ if (has_system) {
+ return ReadSpecificImageHeader(system_filename.c_str(), error_msg);
+ }
}
}
@@ -1447,7 +1458,8 @@
return cache_filename_;
}
- bool LoadFromSystem(size_t extra_reservation_size,
+ bool LoadFromSystem(bool validate_oat_file,
+ size_t extra_reservation_size,
/*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
/*out*/MemMap* extra_reservation,
/*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -1455,7 +1467,7 @@
std::string filename = GetSystemImageFilename(image_location_.c_str(), image_isa_);
if (!LoadFromFile(filename,
- /*validate_oat_file=*/ false,
+ validate_oat_file,
extra_reservation_size,
&logger,
boot_image_spaces,
@@ -2020,6 +2032,7 @@
const std::vector<std::string>& boot_class_path_locations,
const std::string& image_location,
const InstructionSet image_isa,
+ ImageSpaceLoadingOrder order,
size_t extra_reservation_size,
/*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
/*out*/MemMap* extra_reservation) {
@@ -2076,30 +2089,41 @@
// Collect all the errors.
std::vector<std::string> error_msgs;
- // Step 1: Check if we have an existing image in /system.
+ auto try_load_from = [&](auto has_fn, auto load_fn, bool validate_oat_file) {
+ if ((loader.*has_fn)()) {
+ std::string local_error_msg;
+ if ((loader.*load_fn)(validate_oat_file,
+ extra_reservation_size,
+ boot_image_spaces,
+ extra_reservation,
+ &local_error_msg)) {
+ return true;
+ }
+ error_msgs.push_back(local_error_msg);
+ }
+ return false;
+ };
- if (loader.HasSystem()) {
- std::string local_error_msg;
- if (loader.LoadFromSystem(extra_reservation_size,
- boot_image_spaces,
- extra_reservation,
- &local_error_msg)) {
+ auto try_load_from_system = [&]() {
+ return try_load_from(&BootImageLoader::HasSystem, &BootImageLoader::LoadFromSystem, false);
+ };
+ auto try_load_from_cache = [&]() {
+ return try_load_from(&BootImageLoader::HasCache, &BootImageLoader::LoadFromDalvikCache, true);
+ };
+
+ auto invoke_sequentially = [](auto first, auto second) {
+ return first() || second();
+ };
+
+ // Step 1+2: Check system and cache images in the asked-for order.
+ if (order == ImageSpaceLoadingOrder::kSystemFirst) {
+ if (invoke_sequentially(try_load_from_system, try_load_from_cache)) {
return true;
}
- error_msgs.push_back(local_error_msg);
- }
-
- // Step 2: Check if we have an existing image in the dalvik cache.
- if (loader.HasCache()) {
- std::string local_error_msg;
- if (loader.LoadFromDalvikCache(/*validate_oat_file=*/ true,
- extra_reservation_size,
- boot_image_spaces,
- extra_reservation,
- &local_error_msg)) {
+ } else {
+ if (invoke_sequentially(try_load_from_cache, try_load_from_system)) {
return true;
}
- error_msgs.push_back(local_error_msg);
}
// Step 3: We do not have an existing image in /system,
@@ -2259,6 +2283,7 @@
std::string ImageSpace::GetBootClassPathChecksums(const std::vector<std::string>& boot_class_path,
const std::string& image_location,
InstructionSet image_isa,
+ ImageSpaceLoadingOrder order,
/*out*/std::string* error_msg) {
std::string system_filename;
bool has_system = false;
@@ -2281,7 +2306,9 @@
}
DCHECK(has_system || has_cache);
- const std::string& filename = has_system ? system_filename : cache_filename;
+ const std::string& filename = (order == ImageSpaceLoadingOrder::kSystemFirst)
+ ? (has_system ? system_filename : cache_filename)
+ : (has_cache ? cache_filename : system_filename);
std::unique_ptr<ImageHeader> header = ReadSpecificImageHeader(filename.c_str(), error_msg);
if (header == nullptr) {
return std::string();
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index bb19097..1c61f06 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -19,6 +19,7 @@
#include "gc/accounting/space_bitmap.h"
#include "image.h"
+#include "image_space_loading_order.h"
#include "space.h"
namespace art {
@@ -48,6 +49,7 @@
const std::vector<std::string>& boot_class_path_locations,
const std::string& image_location,
const InstructionSet image_isa,
+ ImageSpaceLoadingOrder order,
size_t extra_reservation_size,
/*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
/*out*/MemMap* extra_reservation) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -63,6 +65,7 @@
// reason in error_msg.
static std::unique_ptr<ImageHeader> ReadImageHeader(const char* image_location,
InstructionSet image_isa,
+ ImageSpaceLoadingOrder order,
std::string* error_msg);
// Give access to the OatFile.
@@ -132,6 +135,7 @@
static std::string GetBootClassPathChecksums(const std::vector<std::string>& boot_class_path,
const std::string& image_location,
InstructionSet image_isa,
+ ImageSpaceLoadingOrder order,
/*out*/std::string* error_msg);
// Returns the checksums for the boot image and extra boot class path dex files,
diff --git a/runtime/gc/space/image_space_fs.h b/runtime/gc/space/image_space_fs.h
index 262c6e0..0eab35f 100644
--- a/runtime/gc/space/image_space_fs.h
+++ b/runtime/gc/space/image_space_fs.h
@@ -20,7 +20,8 @@
#include <dirent.h>
#include <dlfcn.h>
-#include "android-base/stringprintf.h"
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include "base/file_utils.h"
#include "base/logging.h" // For VLOG.
diff --git a/runtime/gc/space/image_space_loading_order.h b/runtime/gc/space/image_space_loading_order.h
new file mode 100644
index 0000000..d8b0be4
--- /dev/null
+++ b/runtime/gc/space/image_space_loading_order.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_GC_SPACE_IMAGE_SPACE_LOADING_ORDER_H_
+#define ART_RUNTIME_GC_SPACE_IMAGE_SPACE_LOADING_ORDER_H_
+
+namespace art {
+namespace gc {
+namespace space {
+
+enum class ImageSpaceLoadingOrder : char {
+ kSystemFirst,
+ kDataFirst,
+};
+
+} // namespace space
+} // namespace gc
+} // namespace art
+
+#endif // ART_RUNTIME_GC_SPACE_IMAGE_SPACE_LOADING_ORDER_H_