diff options
| -rw-r--r-- | compiler/optimizing/inliner.cc | 10 | ||||
| -rw-r--r-- | dex2oat/dex2oat.cc | 3 | ||||
| -rw-r--r-- | libartbase/base/file_utils.cc | 6 | ||||
| -rw-r--r-- | libartbase/base/file_utils.h | 3 | ||||
| -rw-r--r-- | runtime/jit/jit.cc | 101 | ||||
| -rw-r--r-- | runtime/jit/jit.h | 4 | ||||
| -rw-r--r-- | runtime/native/dalvik_system_ZygoteHooks.cc | 2 | ||||
| -rw-r--r-- | runtime/oat_file_assistant.cc | 3 | ||||
| -rw-r--r-- | runtime/parsed_options.cc | 3 | ||||
| -rw-r--r-- | runtime/runtime.h | 1 | ||||
| -rw-r--r-- | runtime/vdex_file.cc | 1 |
11 files changed, 125 insertions, 12 deletions
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 96d6d2a1ae..021d2cfac8 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -589,9 +589,12 @@ bool HInliner::TryInlineFromInlineCache(const DexFile& caller_dex_file, StackHandleScope<1> hs(Thread::Current()); Handle<mirror::ObjectArray<mirror::Class>> inline_cache; - InlineCacheType inline_cache_type = Runtime::Current()->IsAotCompiler() - ? GetInlineCacheAOT(caller_dex_file, invoke_instruction, &hs, &inline_cache) - : GetInlineCacheJIT(invoke_instruction, &hs, &inline_cache); + // The Zygote JIT compiles based on a profile, so we shouldn't use runtime inline caches + // for it. + InlineCacheType inline_cache_type = + (Runtime::Current()->IsAotCompiler() || Runtime::Current()->IsZygote()) + ? GetInlineCacheAOT(caller_dex_file, invoke_instruction, &hs, &inline_cache) + : GetInlineCacheJIT(invoke_instruction, &hs, &inline_cache); switch (inline_cache_type) { case kInlineCacheNoData: { @@ -679,7 +682,6 @@ HInliner::InlineCacheType HInliner::GetInlineCacheAOT( StackHandleScope<1>* hs, /*out*/Handle<mirror::ObjectArray<mirror::Class>>* inline_cache) REQUIRES_SHARED(Locks::mutator_lock_) { - DCHECK(Runtime::Current()->IsAotCompiler()); const ProfileCompilationInfo* pci = codegen_->GetCompilerOptions().GetProfileCompilationInfo(); if (pci == nullptr) { return kInlineCacheNoData; diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index edefd0a80f..71f71d11e4 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -808,8 +808,7 @@ class Dex2Oat final { } if (!IsBootImage() && parser_options->boot_image_filename.empty()) { - parser_options->boot_image_filename += android_root_; - parser_options->boot_image_filename += "/framework/boot.art"; + parser_options->boot_image_filename = GetDefaultBootImageLocation(android_root_); } if (!parser_options->boot_image_filename.empty()) { boot_image_filename_ = parser_options->boot_image_filename; diff --git a/libartbase/base/file_utils.cc b/libartbase/base/file_utils.cc index 4953bab624..2436e4528a 100644 --- a/libartbase/base/file_utils.cc +++ b/libartbase/base/file_utils.cc @@ -176,12 +176,16 @@ const char* GetAndroidDataSafe(std::string* error_msg) { return GetAndroidDirSafe("ANDROID_DATA", "/data", error_msg); } +std::string GetDefaultBootImageLocation(const std::string& android_root) { + return StringPrintf("%s/framework/boot.art", android_root.c_str()); +} + std::string GetDefaultBootImageLocation(std::string* error_msg) { std::string android_root = GetAndroidRootSafe(error_msg); if (android_root.empty()) { return ""; } - return StringPrintf("%s/framework/boot.art", android_root.c_str()); + return GetDefaultBootImageLocation(android_root); } void GetDalvikCache(const char* subdir, const bool create_if_absent, std::string* dalvik_cache, diff --git a/libartbase/base/file_utils.h b/libartbase/base/file_utils.h index bddfaa1faf..c8eca59c12 100644 --- a/libartbase/base/file_utils.h +++ b/libartbase/base/file_utils.h @@ -43,6 +43,9 @@ const char* GetAndroidDataSafe(std::string* error_msg); // Returns an empty string if ANDROID_ROOT is not set. std::string GetDefaultBootImageLocation(std::string* error_msg); +// Returns the default boot image location, based on the passed android root. +std::string GetDefaultBootImageLocation(const std::string& android_root); + // Returns the dalvik-cache location, with subdir appended. Returns the empty string if the cache // could not be found. std::string GetDalvikCache(const char* subdir); diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc index d44bd5988e..69139cd57e 100644 --- a/runtime/jit/jit.cc +++ b/runtime/jit/jit.cc @@ -20,9 +20,11 @@ #include "art_method-inl.h" #include "base/enums.h" +#include "base/file_utils.h" #include "base/logging.h" // For VLOG. #include "base/memory_tool.h" #include "base/runtime_debug.h" +#include "base/scoped_flock.h" #include "base/utils.h" #include "class_root.h" #include "debugger.h" @@ -559,7 +561,7 @@ class JitCompileTask final : public Task { kCompileOsr, }; - JitCompileTask(ArtMethod* method, TaskKind kind) : method_(method), kind_(kind) { + JitCompileTask(ArtMethod* method, TaskKind kind) : method_(method), kind_(kind), klass_(nullptr) { ScopedObjectAccess soa(Thread::Current()); // Add a global ref to the class to prevent class unloading until compilation is done. klass_ = soa.Vm()->AddGlobalRef(soa.Self(), method_->GetDeclaringClass()); @@ -606,6 +608,18 @@ class JitCompileTask final : public Task { DISALLOW_IMPLICIT_CONSTRUCTORS(JitCompileTask); }; +class ZygoteTask final : public Task { + public: + ZygoteTask() {} + + void Run(Thread* self) override { + Runtime::Current()->GetJit()->AddNonAotBootMethodsToQueue(self); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ZygoteTask); +}; + void Jit::CreateThreadPool() { // There is a DCHECK in the 'AddSamples' method to ensure the tread pool // is not null when we instrument. @@ -616,6 +630,91 @@ void Jit::CreateThreadPool() { thread_pool_->SetPthreadPriority(options_->GetThreadPoolPthreadPriority()); Start(); + + // If we're not using the default boot image location, request a JIT task to + // compile all methods in the boot image profile. + Runtime* runtime = Runtime::Current(); + if (runtime->IsZygote() && !runtime->IsUsingDefaultBootImageLocation()) { + thread_pool_->AddTask(Thread::Current(), new ZygoteTask()); + } +} + +void Jit::AddNonAotBootMethodsToQueue(Thread* self) { + Runtime* runtime = Runtime::Current(); + std::string profile_location; + for (const std::string& option : runtime->GetImageCompilerOptions()) { + if (android::base::StartsWith(option, "--profile-file=")) { + profile_location = option.substr(strlen("--profile-file=")); + break; + } + } + if (profile_location.empty()) { + LOG(WARNING) << "Expected a profile location in JIT zygote mode"; + return; + } + + std::string error_msg; + ScopedFlock profile_file = LockedFile::Open( + profile_location.c_str(), O_RDONLY, true, &error_msg); + + // Return early if we're unable to obtain a lock on the profile. + if (profile_file.get() == nullptr) { + LOG(ERROR) << "Cannot lock profile: " << error_msg; + return; + } + + ProfileCompilationInfo profile_info; + if (!profile_info.Load(profile_file->Fd())) { + LOG(ERROR) << "Could not load profile file"; + return; + } + + const std::vector<const DexFile*>& boot_class_path = + runtime->GetClassLinker()->GetBootClassPath(); + ScopedObjectAccess soa(self); + StackHandleScope<1> hs(self); + MutableHandle<mirror::DexCache> dex_cache = hs.NewHandle<mirror::DexCache>(nullptr); + ScopedNullHandle<mirror::ClassLoader> null_handle; + ClassLinker* class_linker = runtime->GetClassLinker(); + + for (const DexFile* dex_file : boot_class_path) { + std::set<dex::TypeIndex> class_types; + std::set<uint16_t> hot_methods; + std::set<uint16_t> startup_methods; + std::set<uint16_t> post_startup_methods; + std::set<uint16_t> combined_methods; + if (!profile_info.GetClassesAndMethods(*dex_file, + &class_types, + &hot_methods, + &startup_methods, + &post_startup_methods)) { + LOG(ERROR) << "Unable to get classes and methods for " << dex_file->GetLocation(); + continue; + } + dex_cache.Assign(class_linker->FindDexCache(self, *dex_file)); + CHECK(dex_cache != nullptr) << "Could not find dex cache for " << dex_file->GetLocation(); + for (uint16_t method_idx : startup_methods) { + ArtMethod* method = class_linker->ResolveMethodWithoutInvokeType( + method_idx, dex_cache, null_handle); + if (method == nullptr) { + self->ClearException(); + continue; + } + if (!method->IsCompilable() || !method->IsInvokable()) { + continue; + } + const void* entry_point = method->GetEntryPointFromQuickCompiledCode(); + if (class_linker->IsQuickToInterpreterBridge(entry_point) || + class_linker->IsQuickGenericJniStub(entry_point)) { + if (!method->IsNative()) { + // The compiler requires a ProfilingInfo object for non-native methods. + ProfilingInfo::Create(self, method, /* retry_allocation= */ true); + } + thread_pool_->AddTask(self, + new JitCompileTask(method, JitCompileTask::TaskKind::kCompile)); + } + } + } } static bool IgnoreSamplesForMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) { diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h index 714db3a66e..f709de3921 100644 --- a/runtime/jit/jit.h +++ b/runtime/jit/jit.h @@ -303,6 +303,10 @@ class Jit { // Adjust state after forking. void PostZygoteFork(); + // In case the boot classpath is not fully AOTed, add methods from the boot profile to the + // compilation queue. + void AddNonAotBootMethodsToQueue(Thread* self); + private: Jit(JitCodeCache* code_cache, JitOptions* options); diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc index 891ecef124..da0e048213 100644 --- a/runtime/native/dalvik_system_ZygoteHooks.cc +++ b/runtime/native/dalvik_system_ZygoteHooks.cc @@ -287,7 +287,7 @@ static void ZygoteHooks_nativePostForkChild(JNIEnv* env, runtime_flags &= ~DISABLE_VERIFIER; } - if ((runtime_flags & ONLY_USE_SYSTEM_OAT_FILES) != 0) { + if ((runtime_flags & ONLY_USE_SYSTEM_OAT_FILES) != 0 || is_system_server) { Runtime::Current()->GetOatFileManager().SetOnlyUseSystemOatFiles(); runtime_flags &= ~ONLY_USE_SYSTEM_OAT_FILES; } diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index 80ac01f41a..f1708b46a9 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -783,6 +783,7 @@ const OatFile* OatFileAssistant::OatFileInfo::GetFile() { if (executable && oat_file_assistant_->only_load_system_executable_) { executable = LocationIsOnSystem(filename_.c_str()); } + VLOG(oat) << "Loading " << filename_ << " with executable: " << executable; std::string error_msg; if (use_fd_) { if (oat_fd_ >= 0 && vdex_fd_ >= 0) { @@ -809,6 +810,8 @@ const OatFile* OatFileAssistant::OatFileInfo::GetFile() { if (file_.get() == nullptr) { VLOG(oat) << "OatFileAssistant test for existing oat file " << filename_ << ": " << error_msg; + } else { + VLOG(oat) << "Successfully loaded " << filename_ << " with executable: " << executable; } } } diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index b78c152416..6423f3b21b 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -606,8 +606,7 @@ bool ParsedOptions::DoParse(const RuntimeOptions& options, } if (!args.Exists(M::CompilerCallbacksPtr) && !args.Exists(M::Image)) { - std::string image = GetAndroidRoot(); - image += "/framework/boot.art"; + std::string image = GetDefaultBootImageLocation(GetAndroidRoot()); args.Set(M::Image, image); } diff --git a/runtime/runtime.h b/runtime/runtime.h index ed6ee45b2f..ace0eea139 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -27,6 +27,7 @@ #include <memory> #include <vector> +#include "base/file_utils.h" #include "base/locks.h" #include "base/macros.h" #include "base/mem_map.h" diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc index 72c42b9ee4..61cd982e19 100644 --- a/runtime/vdex_file.cc +++ b/runtime/vdex_file.cc @@ -178,7 +178,6 @@ std::unique_ptr<VdexFile> VdexFile::OpenAtAddress(uint8_t* mmap_addr, reinterpret_cast<DexSectionHeader*>(vdex->mmap_.Begin() + offset)->quickening_info_size_ = 0; } - *error_msg = "Success"; return vdex; } |