Revert^4 "Add the mainline framework boot image extensio...
Revert submission 2465993-boot-image-mainline-revert
Reason for revert: Relanding the changes
Reverted changes: /q/submissionid:2465993-boot-image-mainline-revert
Change-Id: I5dd81f74c08faccd1643c2b01826e6a76cbb10c5
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index 4f85140..3ad696b 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -2183,9 +2183,9 @@
// fields. Limit the max number of encoded fields.
if (!klass->IsInitialized() &&
(is_app_image || is_boot_image || is_boot_image_extension) &&
- try_initialize_with_superclasses &&
- !too_many_encoded_fields &&
- compiler_options.IsImageClass(descriptor)) {
+ try_initialize_with_superclasses && !too_many_encoded_fields &&
+ compiler_options.IsImageClass(descriptor) &&
+ compiler_options.IsAotCompilationEnabled()) {
bool can_init_static_fields = false;
if (is_boot_image || is_boot_image_extension) {
// We need to initialize static fields, we only do this for image classes that aren't
diff --git a/dexoptanalyzer/dexoptanalyzer.cc b/dexoptanalyzer/dexoptanalyzer.cc
index ef43157..b182f68 100644
--- a/dexoptanalyzer/dexoptanalyzer.cc
+++ b/dexoptanalyzer/dexoptanalyzer.cc
@@ -239,11 +239,16 @@
// If we don't receive the image, try to use the default one.
// Tests may specify a different image (e.g. core image).
std::string error_msg;
- image_ = GetDefaultBootImageLocation(&error_msg);
-
+ std::string android_root = GetAndroidRootSafe(&error_msg);
+ if (android_root.empty()) {
+ LOG(ERROR) << error_msg;
+ Usage("--image unspecified and ANDROID_ROOT not set.");
+ }
+ image_ = GetDefaultBootImageLocationSafe(
+ android_root, /*deny_art_apex_data_files=*/false, &error_msg);
if (image_.empty()) {
LOG(ERROR) << error_msg;
- Usage("--image unspecified and ANDROID_ROOT not set or image file does not exist.");
+ Usage("--image unspecified and failed to get default boot image location.");
}
}
}
diff --git a/libartbase/base/file_utils.cc b/libartbase/base/file_utils.cc
index 2396289..d2afbcc 100644
--- a/libartbase/base/file_utils.cc
+++ b/libartbase/base/file_utils.cc
@@ -40,6 +40,7 @@
#include <memory>
#include <sstream>
+#include <vector>
#include "android-base/file.h"
#include "android-base/logging.h"
@@ -50,6 +51,7 @@
#include "base/os.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
+#include "base/utils.h"
#if defined(__APPLE__)
#include <crt_externs.h>
@@ -78,6 +80,7 @@
static constexpr const char* kAndroidI18nRootEnvVar = "ANDROID_I18N_ROOT";
static constexpr const char* kApexDefaultPath = "/apex/";
static constexpr const char* kArtApexDataEnvVar = "ART_APEX_DATA";
+static constexpr const char* kBootImageStem = "boot";
// Get the "root" directory containing the "lib" directory where this instance
// of the libartbase library (which contains `GetRootContainingLibartbase`) is
@@ -298,10 +301,82 @@
return GetPrebuiltPrimaryBootImageDir(android_root);
}
-std::string GetDefaultBootImageLocation(const std::string& android_root,
- bool deny_art_apex_data_files) {
+std::string GetFirstMainlineFrameworkLibraryFilename(std::string* error_msg) {
+ const char* env_bcp = getenv("BOOTCLASSPATH");
+ const char* env_dex2oat_bcp = getenv("DEX2OATBOOTCLASSPATH");
+ if (env_bcp == nullptr || env_dex2oat_bcp == nullptr) {
+ *error_msg = "BOOTCLASSPATH and DEX2OATBOOTCLASSPATH must not be empty";
+ return "";
+ }
+
+ // DEX2OATBOOTCLASSPATH contains core libraries and framework libraries. We used to only compile
+ // those libraries. Now we compile mainline framework libraries as well, and we have repurposed
+ // DEX2OATBOOTCLASSPATH to indicate the separation between mainline framework libraries and other
+ // libraries.
+ std::string_view mainline_bcp(env_bcp);
+ if (!android::base::ConsumePrefix(&mainline_bcp, env_dex2oat_bcp)) {
+ *error_msg = "DEX2OATBOOTCLASSPATH must be a prefix of BOOTCLASSPATH";
+ return "";
+ }
+
+ std::vector<std::string_view> mainline_bcp_jars;
+ Split(mainline_bcp, ':', &mainline_bcp_jars);
+ if (mainline_bcp_jars.empty()) {
+ *error_msg = "No mainline framework library found";
+ return "";
+ }
+
+ return std::string(mainline_bcp_jars[0]);
+}
+
+static std::string GetFirstMainlineFrameworkLibraryName(std::string* error_msg) {
+ std::string filename = GetFirstMainlineFrameworkLibraryFilename(error_msg);
+ if (filename.empty()) {
+ return "";
+ }
+
+ std::string jar_name = android::base::Basename(filename);
+
+ std::string_view library_name(jar_name);
+ if (!android::base::ConsumeSuffix(&library_name, ".jar")) {
+ *error_msg = "Invalid mainline framework jar: " + jar_name;
+ return "";
+ }
+
+ return std::string(library_name);
+}
+
+// Returns true when no error occurs, even if the extension doesn't exist.
+static bool MaybeAppendBootImageMainlineExtension(const std::string& android_root,
+ /*inout*/ std::string* location,
+ /*out*/ std::string* error_msg) {
+ if (!kIsTargetAndroid) {
+ return true;
+ }
+ // Due to how the runtime determines the mapping between boot images and bootclasspath jars, the
+ // name of the boot image extension must be in the format of
+ // `<primary-boot-image-stem>-<first-library-name>.art`.
+ std::string library_name = GetFirstMainlineFrameworkLibraryName(error_msg);
+ if (library_name.empty()) {
+ return false;
+ }
+ std::string mainline_extension_location = StringPrintf(
+ "%s/framework/%s-%s.art", android_root.c_str(), kBootImageStem, library_name.c_str());
+ std::string mainline_extension_path =
+ GetSystemImageFilename(mainline_extension_location.c_str(), kRuntimeISA);
+ if (!OS::FileExists(mainline_extension_path.c_str(), /*check_file_type=*/true)) {
+ // This is expected when the ART module is preloaded on an old source tree that doesn't
+ // dexpreopt mainline BCP jars, so it shouldn't be considered as an error.
+ return true;
+ }
+ *location += ":" + mainline_extension_location;
+ return true;
+}
+
+std::string GetDefaultBootImageLocationSafe(const std::string& android_root,
+ bool deny_art_apex_data_files,
+ std::string* error_msg) {
constexpr static const char* kEtcBootImageProf = "etc/boot-image.prof";
- constexpr static const char* kBootImageStem = "boot";
constexpr static const char* kMinimalBootImageStem = "boot_minimal";
// If an update for the ART module has been been installed, a single boot image for the entire
@@ -347,28 +422,37 @@
PLOG(ERROR) << "Minimal boot image check failed, could not stat: " << boot_image_filename;
}
}
- // Boot image consists of two parts:
- // - the primary boot image (contains the Core Libraries)
- // - the boot image extensions (contains framework libraries)
- // Typically "/apex/com.android.art/javalib/boot.art!/apex/com.android.art/etc/boot-image.prof:
- // /system/framework/boot-framework.art!/system/etc/boot-image.prof".
- return StringPrintf("%s/%s.art!%s/%s:%s/framework/%s-framework.art!%s/%s",
- GetPrebuiltPrimaryBootImageDir(android_root).c_str(),
- kBootImageStem,
- kAndroidArtApexDefaultPath,
- kEtcBootImageProf,
- android_root.c_str(),
- kBootImageStem,
- android_root.c_str(),
- kEtcBootImageProf);
-}
-std::string GetDefaultBootImageLocation(std::string* error_msg) {
- std::string android_root = GetAndroidRootSafe(error_msg);
- if (android_root.empty()) {
+ // Boot image consists of three parts:
+ // - the primary boot image (contains the Core Libraries)
+ // - the boot image framework extension (contains framework libraries)
+ // - the boot image mainline extension (contains mainline framework libraries)
+ // Typically "/system/framework/boot.art!/apex/com.android.art/etc/boot-image.prof:
+ // /system/framework/boot-framework.art!/system/etc/boot-image.prof:
+ // /system/framework/boot-framework-adservices.art".
+
+ std::string location = StringPrintf("%s/%s.art!%s/%s:%s/framework/%s-framework.art!%s/%s",
+ GetPrebuiltPrimaryBootImageDir(android_root).c_str(),
+ kBootImageStem,
+ kAndroidArtApexDefaultPath,
+ kEtcBootImageProf,
+ android_root.c_str(),
+ kBootImageStem,
+ android_root.c_str(),
+ kEtcBootImageProf);
+ if (!MaybeAppendBootImageMainlineExtension(android_root, &location, error_msg)) {
return "";
}
- return GetDefaultBootImageLocation(android_root, /*deny_art_apex_data_files=*/false);
+ return location;
+}
+
+std::string GetDefaultBootImageLocation(const std::string& android_root,
+ bool deny_art_apex_data_files) {
+ std::string error_msg;
+ std::string location =
+ GetDefaultBootImageLocationSafe(android_root, deny_art_apex_data_files, &error_msg);
+ CHECK(!location.empty()) << error_msg;
+ return location;
}
std::string GetJitZygoteBootImageLocation() {
diff --git a/libartbase/base/file_utils.h b/libartbase/base/file_utils.h
index f539f5f..faec95e 100644
--- a/libartbase/base/file_utils.h
+++ b/libartbase/base/file_utils.h
@@ -78,11 +78,18 @@
// generated at build time).
std::string GetPrebuiltPrimaryBootImageDir();
-// Returns the default boot image location (ANDROID_ROOT/framework/boot.art).
-// Returns an empty string if ANDROID_ROOT is not set.
-std::string GetDefaultBootImageLocation(std::string* error_msg);
+// Returns the filename of the first mainline framework library.
+std::string GetFirstMainlineFrameworkLibraryFilename(std::string* error_msg);
// Returns the default boot image location, based on the passed `android_root`.
+// Returns an empty string if an error occurs.
+// The default boot image location can only be used with the default bootclasspath (the value of the
+// BOOTCLASSPATH environment variable).
+std::string GetDefaultBootImageLocationSafe(const std::string& android_root,
+ bool deny_art_apex_data_files,
+ std::string* error_msg);
+
+// Same as above, but fails if an error occurs.
std::string GetDefaultBootImageLocation(const std::string& android_root,
bool deny_art_apex_data_files);
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 5994410..092d652 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -714,35 +714,20 @@
}
/**
- * Update entrypoints (native and Java) of methods before the first fork. This
+ * Update entrypoints of methods before the first fork. This
* helps sharing pages where ArtMethods are allocated between the zygote and
* forked apps.
*/
class UpdateMethodsPreFirstForkVisitor : public ClassVisitor {
public:
- UpdateMethodsPreFirstForkVisitor(Thread* self, ClassLinker* class_linker)
- : vm_(down_cast<JNIEnvExt*>(self->GetJniEnv())->GetVm()),
- self_(self),
- class_linker_(class_linker),
+ explicit UpdateMethodsPreFirstForkVisitor(ClassLinker* class_linker)
+ : class_linker_(class_linker),
can_use_nterp_(interpreter::CanRuntimeUseNterp()) {}
bool operator()(ObjPtr<mirror::Class> klass) override REQUIRES_SHARED(Locks::mutator_lock_) {
bool is_initialized = klass->IsVisiblyInitialized();
for (ArtMethod& method : klass->GetDeclaredMethods(kRuntimePointerSize)) {
- if (is_initialized || !method.NeedsClinitCheckBeforeCall()) {
- if (method.IsNative()) {
- const void* existing = method.GetEntryPointFromJni();
- if (method.IsCriticalNative()
- ? class_linker_->IsJniDlsymLookupCriticalStub(existing)
- : class_linker_->IsJniDlsymLookupStub(existing)) {
- const void* native_code =
- vm_->FindCodeForNativeMethod(&method, /*error_msg=*/ nullptr, /*can_suspend=*/ false);
- if (native_code != nullptr) {
- class_linker_->RegisterNative(self_, &method, native_code);
- }
- }
- }
- } else if (can_use_nterp_) {
+ if (!is_initialized && method.NeedsClinitCheckBeforeCall() && can_use_nterp_) {
const void* existing = method.GetEntryPointFromQuickCompiledCode();
if (class_linker_->IsQuickResolutionStub(existing) && CanMethodUseNterp(&method)) {
method.SetEntryPointFromQuickCompiledCode(interpreter::GetNterpWithClinitEntryPoint());
@@ -753,8 +738,6 @@
}
private:
- JavaVMExt* const vm_;
- Thread* const self_;
ClassLinker* const class_linker_;
const bool can_use_nterp_;
@@ -775,7 +758,7 @@
class_linker_->MakeInitializedClassesVisiblyInitialized(self, /*wait=*/ true);
ScopedObjectAccess soa(self);
- UpdateMethodsPreFirstForkVisitor visitor(self, class_linker_);
+ UpdateMethodsPreFirstForkVisitor visitor(class_linker_);
class_linker_->VisitClasses(&visitor);
}
heap_->PreZygoteFork();
diff --git a/test/dexpreopt/dexpreopt_test.cc b/test/dexpreopt/dexpreopt_test.cc
index 55593ea..9641e0a 100644
--- a/test/dexpreopt/dexpreopt_test.cc
+++ b/test/dexpreopt/dexpreopt_test.cc
@@ -46,7 +46,8 @@
namespace art {
-using ::testing::IsSubsetOf;
+using ::android::base::Error;
+using ::testing::IsSupersetOf;
constexpr const char* kZygote32 = "zygote";
constexpr const char* kZygote64 = "zygote64";
@@ -99,6 +100,12 @@
if (jars.empty()) {
return Errorf("Environment variable `DEX2OATBOOTCLASSPATH` is not defined or empty");
}
+ std::string error_msg;
+ std::string first_mainline_jar = GetFirstMainlineFrameworkLibraryFilename(&error_msg);
+ if (first_mainline_jar.empty()) {
+ return Error() << error_msg;
+ }
+ jars.push_back(std::move(first_mainline_jar));
std::string art_root = GetArtRoot();
std::string android_root = GetAndroidRoot();
std::vector<std::string> artifacts;
@@ -218,7 +225,7 @@
GetZygoteMappedOatFiles(zygote_name);
ASSERT_RESULT_OK(mapped_oat_files);
- EXPECT_THAT(expected_artifacts.value(), IsSubsetOf(mapped_oat_files.value()));
+ EXPECT_THAT(mapped_oat_files.value(), IsSupersetOf(expected_artifacts.value()));
}
}
@@ -236,7 +243,7 @@
GetSystemServerArtifactsMappedOdexes();
ASSERT_RESULT_OK(mapped_odexes);
- EXPECT_THAT(expected_artifacts.value(), IsSubsetOf(mapped_odexes.value()));
+ EXPECT_THAT(mapped_odexes.value(), IsSupersetOf(expected_artifacts.value()));
}
} // namespace art
diff --git a/test/generate-boot-image/generate-boot-image.cc b/test/generate-boot-image/generate-boot-image.cc
index 475bfb1..f22bad4 100644
--- a/test/generate-boot-image/generate-boot-image.cc
+++ b/test/generate-boot-image/generate-boot-image.cc
@@ -109,8 +109,9 @@
android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
std::string dir = "";
- // Set the compiler filter to `verify` by default to make test preparation faster.
- std::string compiler_filter = "verify";
+ // Set the compiler filter to `speed-profile` by default to make test preparation
+ // faster and behave like normal boot image generation.
+ std::string compiler_filter = "speed-profile";
for (int i = 1; i < argc; i++) {
std::string_view arg{argv[i]};
if (android::base::ConsumePrefix(&arg, "--output-dir=")) {