diff options
author | 2023-03-06 19:16:48 +0000 | |
---|---|---|
committer | 2023-03-16 16:07:43 +0000 | |
commit | 7da3956e3ff5c96ffd56d5e52057a230536a2d46 (patch) | |
tree | 5750407a3ef6e15a304ff5294fcdd200df030faa | |
parent | bbb7177a0b9a82a330a03966d708538d2768ffa1 (diff) |
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
-rw-r--r-- | dex2oat/driver/compiler_driver.cc | 6 | ||||
-rw-r--r-- | dexoptanalyzer/dexoptanalyzer.cc | 11 | ||||
-rw-r--r-- | libartbase/base/file_utils.cc | 128 | ||||
-rw-r--r-- | libartbase/base/file_utils.h | 13 | ||||
-rw-r--r-- | runtime/runtime.cc | 27 | ||||
-rw-r--r-- | test/dexpreopt/dexpreopt_test.cc | 13 | ||||
-rw-r--r-- | test/generate-boot-image/generate-boot-image.cc | 5 |
7 files changed, 145 insertions, 58 deletions
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc index 4f851408d1..3ad696b125 100644 --- a/dex2oat/driver/compiler_driver.cc +++ b/dex2oat/driver/compiler_driver.cc @@ -2183,9 +2183,9 @@ class InitializeClassVisitor : public CompilationVisitor { // 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 ef4315739b..b182f68a7f 100644 --- a/dexoptanalyzer/dexoptanalyzer.cc +++ b/dexoptanalyzer/dexoptanalyzer.cc @@ -239,11 +239,16 @@ class DexoptAnalyzer final { // 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 239628978e..d2afbcc009 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* kAndroidConscryptRootEnvVar = "ANDROID_CONSCRYPT_RO 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 @@ std::string GetPrebuiltPrimaryBootImageDir() { 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 @@ std::string GetDefaultBootImageLocation(const std::string& android_root, PLOG(ERROR) << "Minimal boot image check failed, could not stat: " << boot_image_filename; } } - // Boot image consists of two parts: + + // Boot image consists of three 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()) { + // - 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 f539f5fd55..faec95eabf 100644 --- a/libartbase/base/file_utils.h +++ b/libartbase/base/file_utils.h @@ -78,11 +78,18 @@ std::string GetArtApexData(); // 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 5994410d29..092d65212a 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -714,35 +714,20 @@ void Runtime::Abort(const char* msg) { } /** - * 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 @@ class UpdateMethodsPreFirstForkVisitor : public ClassVisitor { } private: - JavaVMExt* const vm_; - Thread* const self_; ClassLinker* const class_linker_; const bool can_use_nterp_; @@ -775,7 +758,7 @@ void Runtime::PreZygoteFork() { 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 55593eae66..9641e0adf1 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 @@ android::base::Result<std::vector<std::string>> GetZygoteExpectedArtifacts(Instr 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 @@ TEST(DexpreoptTest, ForZygote) { 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 @@ TEST(DexpreoptTest, ForSystemServer) { 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 475bfb1528..f22bad4587 100644 --- a/test/generate-boot-image/generate-boot-image.cc +++ b/test/generate-boot-image/generate-boot-image.cc @@ -109,8 +109,9 @@ int main(int argc, char** argv) { 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=")) { |