diff options
Diffstat (limited to 'dex2oat/dex2oat.cc')
| -rw-r--r-- | dex2oat/dex2oat.cc | 136 |
1 files changed, 86 insertions, 50 deletions
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 9e6103b424..6c713721d8 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -20,6 +20,7 @@ #include <stdlib.h> #include <sys/stat.h> +#include <algorithm> #include <forward_list> #include <fstream> #include <iostream> @@ -39,6 +40,7 @@ #endif #include "android-base/parseint.h" +#include "android-base/properties.h" #include "android-base/scopeguard.h" #include "android-base/stringprintf.h" #include "android-base/strings.h" @@ -65,6 +67,7 @@ #include "base/zip_archive.h" #include "class_linker.h" #include "class_loader_context.h" +#include "class_root-inl.h" #include "cmdline_parser.h" #include "compiler.h" #include "compiler_callbacks.h" @@ -108,7 +111,6 @@ #include "stream/file_output_stream.h" #include "vdex_file.h" #include "verifier/verifier_deps.h" -#include "well_known_classes.h" namespace art { @@ -607,8 +609,13 @@ class Dex2Oat final { } void ParseInstructionSetVariant(const std::string& option, ParserOptions* parser_options) { - compiler_options_->instruction_set_features_ = InstructionSetFeatures::FromVariant( - compiler_options_->instruction_set_, option, &parser_options->error_msg); + if (kIsTargetBuild) { + compiler_options_->instruction_set_features_ = InstructionSetFeatures::FromVariantAndHwcap( + compiler_options_->instruction_set_, option, &parser_options->error_msg); + } else { + compiler_options_->instruction_set_features_ = InstructionSetFeatures::FromVariant( + compiler_options_->instruction_set_, option, &parser_options->error_msg); + } if (compiler_options_->instruction_set_features_ == nullptr) { Usage("%s", parser_options->error_msg.c_str()); } @@ -718,8 +725,15 @@ class Dex2Oat final { if (!IsBootImage() && boot_image_filename_.empty()) { DCHECK(!IsBootImageExtension()); - boot_image_filename_ = - GetDefaultBootImageLocation(android_root_, /*deny_art_apex_data_files=*/false); + if (std::any_of(runtime_args_.begin(), runtime_args_.end(), [](const char* arg) { + return android::base::StartsWith(arg, "-Xbootclasspath:"); + })) { + LOG(WARNING) << "--boot-image is not specified while -Xbootclasspath is specified. Running " + "dex2oat in imageless mode"; + } else { + boot_image_filename_ = + GetDefaultBootImageLocation(android_root_, /*deny_art_apex_data_files=*/false); + } } if (dex_filenames_.empty() && zip_fd_ == -1) { @@ -774,9 +788,12 @@ class Dex2Oat final { compiler_options_->multi_image_ = IsBootImage() || IsBootImageExtension(); } // On target we support generating a single image for the primary boot image. - if (!kIsTargetBuild) { + if (!kIsTargetBuild && !force_allow_oj_inlines_) { if (IsBootImage() && !compiler_options_->multi_image_) { - Usage("--single-image specified for primary boot image on host"); + Usage( + "--single-image specified for primary boot image on host. Please " + "use the flag --force-allow-oj-inlines and do not distribute " + "binaries."); } } if (IsAppImage() && compiler_options_->multi_image_) { @@ -839,9 +856,7 @@ class Dex2Oat final { // Set the compilation target's implicit checks options. switch (compiler_options_->GetInstructionSet()) { case InstructionSet::kArm64: - // TODO: Implicit suspend checks are currently disabled to facilitate search - // for unrelated memory use regressions. Bug: 213757852. - compiler_options_->implicit_suspend_checks_ = false; + compiler_options_->implicit_suspend_checks_ = true; FALLTHROUGH_INTENDED; case InstructionSet::kArm: case InstructionSet::kThumb2: @@ -957,7 +972,7 @@ class Dex2Oat final { compiler_options_->GetNativeDebuggable()); key_value_store_->Put(OatHeader::kCompilerFilter, CompilerFilter::NameOfFilter(compiler_options_->GetCompilerFilter())); - key_value_store_->Put(OatHeader::kConcurrentCopying, kUseReadBarrier); + key_value_store_->Put(OatHeader::kConcurrentCopying, gUseReadBarrier); if (invocation_file_.get() != -1) { std::ostringstream oss; for (int i = 0; i < argc; ++i) { @@ -1029,7 +1044,13 @@ class Dex2Oat final { original_argv = argv; Locks::Init(); - InitLogging(argv, Runtime::Abort); + + // Microdroid doesn't support logd logging, so don't override there. + if (android::base::GetProperty("ro.hardware", "") == "microdroid") { + android::base::SetAborter(Runtime::Abort); + } else { + InitLogging(argv, Runtime::Abort); + } compiler_options_.reset(new CompilerOptions()); @@ -1095,6 +1116,19 @@ class Dex2Oat final { AssignIfExists(args, M::PublicSdk, &public_sdk_); AssignIfExists(args, M::ApexVersions, &apex_versions_argument_); + // Check for phenotype flag to override compact_dex_level_, if it isn't "none" already. + // TODO(b/256664509): Clean this up. + if (compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone) { + std::string ph_disable_compact_dex = + android::base::GetProperty(kPhDisableCompactDex, "false"); + if (ph_disable_compact_dex == "true") { + LOG(WARNING) + << "Overriding --compact-dex-level due to " + "persist.device_config.runtime_native_boot.disable_compact_dex set to `true`"; + compact_dex_level_ = CompactDexLevel::kCompactDexLevelNone; + } + } + AssignIfExists(args, M::Backend, &compiler_kind_); parser_options->requested_specific_compiler = args.Exists(M::Backend); @@ -1187,7 +1221,7 @@ class Dex2Oat final { if (!parser_options->boot_image_filename.empty()) { Usage("Option --boot-image and --force-jit-zygote cannot be specified together"); } - parser_options->boot_image_filename = "boot.art:/nonx/boot-framework.art"; + parser_options->boot_image_filename = GetJitZygoteBootImageLocation(); } // If we have a profile, change the default compiler filter to speed-profile @@ -1400,24 +1434,36 @@ class Dex2Oat final { } } - void LoadClassProfileDescriptors() { + void LoadImageClassDescriptors() { if (!IsImage()) { return; } + HashSet<std::string> image_classes; if (DoProfileGuidedOptimizations()) { // TODO: The following comment looks outdated or misplaced. // Filter out class path classes since we don't want to include these in the image. - HashSet<std::string> image_classes = profile_compilation_info_->GetClassDescriptors( + image_classes = profile_compilation_info_->GetClassDescriptors( compiler_options_->dex_files_for_oat_file_); VLOG(compiler) << "Loaded " << image_classes.size() << " image class descriptors from profile"; - if (VLOG_IS_ON(compiler)) { - for (const std::string& s : image_classes) { - LOG(INFO) << "Image class " << s; + } else if (compiler_options_->IsBootImage() || compiler_options_->IsBootImageExtension()) { + // If we are compiling a boot image but no profile is provided, include all classes in the + // image. This is to match pre-boot image extension work where we would load all boot image + // extension classes at startup. + for (const DexFile* dex_file : compiler_options_->dex_files_for_oat_file_) { + for (uint32_t i = 0; i < dex_file->NumClassDefs(); i++) { + const dex::ClassDef& class_def = dex_file->GetClassDef(i); + const char* descriptor = dex_file->GetClassDescriptor(class_def); + image_classes.insert(descriptor); } } - compiler_options_->image_classes_.swap(image_classes); } + if (VLOG_IS_ON(compiler)) { + for (const std::string& s : image_classes) { + LOG(INFO) << "Image class " << s; + } + } + compiler_options_->image_classes_ = std::move(image_classes); } // Set up the environment for compilation. Includes starting the runtime and loading/opening the @@ -1469,16 +1515,12 @@ class Dex2Oat final { return dex2oat::ReturnCode::kOther; } dex_files_per_oat_file_.push_back(MakeNonOwningPointerVector(opened_dex_files)); - if (opened_dex_files_map.empty()) { - DCHECK(opened_dex_files.empty()); - } else { - for (MemMap& map : opened_dex_files_map) { - opened_dex_files_maps_.push_back(std::move(map)); - } - for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files) { - dex_file_oat_index_map_.insert(std::make_pair(dex_file.get(), i)); - opened_dex_files_.push_back(std::move(dex_file)); - } + for (MemMap& map : opened_dex_files_map) { + opened_dex_files_maps_.push_back(std::move(map)); + } + for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files) { + dex_file_oat_index_map_.insert(std::make_pair(dex_file.get(), i)); + opened_dex_files_.push_back(std::move(dex_file)); } } } @@ -1798,7 +1840,7 @@ class Dex2Oat final { // 2. not verifying a vdex file, and // 3. using multidex, and // 4. not doing any AOT compilation. - // This means extract, no-vdex verify, and quicken, will use the individual compilation + // This means no-vdex verify will use the individual compilation // mode (to reduce RAM used by the compiler). return compile_individually_ && (!IsImage() && !use_existing_vdex_ && @@ -1815,7 +1857,7 @@ class Dex2Oat final { } // Set up and create the compiler driver and then invoke it to compile all the dex files. - jobject Compile() { + jobject Compile() REQUIRES(!Locks::mutator_lock_) { ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); TimingLogger::ScopedTiming t("dex2oat Compile", timings_); @@ -1864,7 +1906,7 @@ class Dex2Oat final { } } - if (android::base::StartsWith(dex_location, filter.c_str())) { + if (android::base::StartsWith(dex_location, filter)) { VLOG(compiler) << "Disabling inlining from " << dex_file->GetLocation(); no_inline_from_dex_files.push_back(dex_file); break; @@ -1879,6 +1921,7 @@ class Dex2Oat final { compiler_options_->profile_compilation_info_ = profile_compilation_info_.get(); driver_.reset(new CompilerDriver(compiler_options_.get(), + verification_results_.get(), compiler_kind_, thread_count_, swap_fd_)); @@ -1891,9 +1934,7 @@ class Dex2Oat final { const bool compile_individually = ShouldCompileDexFilesIndividually(); if (compile_individually) { - // Set the compiler driver in the callbacks so that we can avoid re-verification. This not - // only helps performance but also prevents reverifying quickened bytecodes. Attempting - // verify quickened bytecode causes verification failures. + // Set the compiler driver in the callbacks so that we can avoid re-verification. // Only set the compiler filter if we are doing separate compilation since there is a bit // of overhead when checking if a class was previously verified. callbacks_->SetDoesClassUnloading(true, driver_.get()); @@ -1964,7 +2005,6 @@ class Dex2Oat final { timings_, &compiler_options_->image_classes_); callbacks_->SetVerificationResults(nullptr); // Should not be needed anymore. - compiler_options_->verification_results_ = verification_results_.get(); driver_->CompileAll(class_loader, dex_files, timings_); driver_->FreeThreadPools(); return class_loader; @@ -2538,16 +2578,16 @@ class Dex2Oat final { } bool PreparePreloadedClasses() { - preloaded_classes_ = std::make_unique<HashSet<std::string>>(); if (!preloaded_classes_fds_.empty()) { for (int fd : preloaded_classes_fds_) { - if (!ReadCommentedInputFromFd(fd, nullptr, preloaded_classes_.get())) { + if (!ReadCommentedInputFromFd(fd, nullptr, &compiler_options_->preloaded_classes_)) { return false; } } } else { for (const std::string& file : preloaded_classes_files_) { - if (!ReadCommentedInputFromFile(file.c_str(), nullptr, preloaded_classes_.get())) { + if (!ReadCommentedInputFromFile( + file.c_str(), nullptr, &compiler_options_->preloaded_classes_)) { return false; } } @@ -2633,6 +2673,7 @@ class Dex2Oat final { bool do_oat_writer_layout = DoDexLayoutOptimizations() || DoOatLayoutOptimizations(); oat_writers_.emplace_back(new linker::OatWriter( *compiler_options_, + verification_results_.get(), timings_, do_oat_writer_layout ? profile_compilation_info_.get() : nullptr, compact_dex_level_)); @@ -2731,19 +2772,14 @@ class Dex2Oat final { interpreter::UnstartedRuntime::Initialize(); Thread* self = Thread::Current(); + runtime_->GetClassLinker()->RunEarlyRootClinits(self); + InitializeIntrinsics(); runtime_->RunRootClinits(self); // Runtime::Create acquired the mutator_lock_ that is normally given away when we // Runtime::Start, give it away now so that we don't starve GC. self->TransitionFromRunnableToSuspended(ThreadState::kNative); - // Now that we are in native state, initialize well known classes and - // intrinsics if we don't have a boot image. - WellKnownClasses::Init(self->GetJniEnv()); - if (IsBootImage() || runtime_->GetHeap()->GetBootImageSpaces().empty()) { - InitializeIntrinsics(); - } - WatchDog::SetRuntime(runtime_.get()); return true; @@ -2786,7 +2822,7 @@ class Dex2Oat final { template <typename T> static bool 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}; + auto input_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(input_filename, "re"), fclose}; if (!input_file) { LOG(ERROR) << "Failed to open input file " << input_filename; return false; @@ -2942,7 +2978,6 @@ class Dex2Oat final { 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_; @@ -3054,8 +3089,9 @@ class ScopedGlobalRef { jobject obj_; }; -static dex2oat::ReturnCode DoCompilation(Dex2Oat& dex2oat) { - dex2oat.LoadClassProfileDescriptors(); +static dex2oat::ReturnCode DoCompilation(Dex2Oat& dex2oat) REQUIRES(!Locks::mutator_lock_) { + Locks::mutator_lock_->AssertNotHeld(Thread::Current()); + dex2oat.LoadImageClassDescriptors(); jobject class_loader = dex2oat.Compile(); // Keep the class loader that was used for compilation live for the rest of the compilation // process. |