diff options
| -rw-r--r-- | runtime/jit/jit.cc | 79 | ||||
| -rw-r--r-- | runtime/jit/jit.h | 229 | ||||
| -rw-r--r-- | runtime/parsed_options.cc | 3 | ||||
| -rw-r--r-- | runtime/runtime_options.def | 1 |
4 files changed, 160 insertions, 152 deletions
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc index 0684b461ae..86e69f49a4 100644 --- a/runtime/jit/jit.cc +++ b/runtime/jit/jit.cc @@ -46,8 +46,6 @@ namespace art { namespace jit { static constexpr bool kEnableOnStackReplacement = true; -// At what priority to schedule jit threads. 9 is the lowest foreground priority on device. -static constexpr int kJitPoolThreadPthreadPriority = 9; // Different compilation threshold constants. These can be overridden on the command line. static constexpr size_t kJitDefaultCompileThreshold = 10000; // Non-debug default. @@ -80,6 +78,8 @@ JitOptions* JitOptions::CreateFromRuntimeArguments(const RuntimeArgumentMap& opt options.Exists(RuntimeArgumentMap::DumpJITInfoOnShutdown); jit_options->profile_saver_options_ = options.GetOrDefault(RuntimeArgumentMap::ProfileSaverOpts); + jit_options->thread_pool_pthread_priority_ = + options.GetOrDefault(RuntimeArgumentMap::JITPoolThreadPthreadPriority); if (options.Exists(RuntimeArgumentMap::JITCompileThreshold)) { jit_options->compile_threshold_ = *options.Get(RuntimeArgumentMap::JITCompileThreshold); @@ -167,21 +167,14 @@ void Jit::AddTimingLogger(const TimingLogger& logger) { cumulative_timings_.AddLogger(logger); } -Jit::Jit() : dump_info_on_shutdown_(false), - cumulative_timings_("JIT timings"), - memory_use_("Memory used for compilation", 16), - lock_("JIT memory use lock"), - use_jit_compilation_(true), - hot_method_threshold_(0), - warm_method_threshold_(0), - osr_method_threshold_(0), - priority_thread_weight_(0), - invoke_transition_weight_(0) {} +Jit::Jit(JitOptions* options) : options_(options), + cumulative_timings_("JIT timings"), + memory_use_("Memory used for compilation", 16), + lock_("JIT memory use lock") {} Jit* Jit::Create(JitOptions* options, std::string* error_msg) { DCHECK(options->UseJitCompilation() || options->GetProfileSaverOptions().IsEnabled()); - std::unique_ptr<Jit> jit(new Jit); - jit->dump_info_on_shutdown_ = options->DumpJitInfoOnShutdown(); + std::unique_ptr<Jit> jit(new Jit(options)); if (jit_compiler_handle_ == nullptr && !LoadCompiler(error_msg)) { return nullptr; } @@ -195,8 +188,6 @@ Jit* Jit::Create(JitOptions* options, std::string* error_msg) { if (jit->GetCodeCache() == nullptr) { return nullptr; } - jit->use_jit_compilation_ = options->UseJitCompilation(); - jit->profile_saver_options_ = options->GetProfileSaverOptions(); VLOG(jit) << "JIT created with initial_capacity=" << PrettySize(options->GetCodeCacheInitialCapacity()) << ", max_capacity=" << PrettySize(options->GetCodeCacheMaxCapacity()) @@ -204,12 +195,6 @@ Jit* Jit::Create(JitOptions* options, std::string* error_msg) { << ", profile_saver_options=" << options->GetProfileSaverOptions(); - jit->hot_method_threshold_ = options->GetCompileThreshold(); - jit->warm_method_threshold_ = options->GetWarmupThreshold(); - jit->osr_method_threshold_ = options->GetOsrThreshold(); - jit->priority_thread_weight_ = options->GetPriorityThreadWeight(); - jit->invoke_transition_weight_ = options->GetInvokeTransitionWeight(); - jit->CreateThreadPool(); // Notify native debugger about the classes already loaded before the creation of the jit. @@ -330,7 +315,7 @@ void Jit::CreateThreadPool() { constexpr bool kJitPoolNeedsPeers = true; thread_pool_.reset(new ThreadPool("Jit thread pool", 1, kJitPoolNeedsPeers)); - thread_pool_->SetPthreadPriority(kJitPoolThreadPthreadPriority); + thread_pool_->SetPthreadPriority(options_->GetThreadPoolPthreadPriority()); Start(); } @@ -360,8 +345,8 @@ void Jit::DeleteThreadPool() { void Jit::StartProfileSaver(const std::string& filename, const std::vector<std::string>& code_paths) { - if (profile_saver_options_.IsEnabled()) { - ProfileSaver::Start(profile_saver_options_, + if (options_->GetSaveProfilingInfo()) { + ProfileSaver::Start(options_->GetProfileSaverOptions(), filename, code_cache_.get(), code_paths); @@ -369,8 +354,8 @@ void Jit::StartProfileSaver(const std::string& filename, } void Jit::StopProfileSaver() { - if (profile_saver_options_.IsEnabled() && ProfileSaver::IsStarted()) { - ProfileSaver::Stop(dump_info_on_shutdown_); + if (options_->GetSaveProfilingInfo() && ProfileSaver::IsStarted()) { + ProfileSaver::Stop(options_->DumpJitInfoOnShutdown()); } } @@ -383,8 +368,8 @@ bool Jit::CanInvokeCompiledCode(ArtMethod* method) { } Jit::~Jit() { - DCHECK(!profile_saver_options_.IsEnabled() || !ProfileSaver::IsStarted()); - if (dump_info_on_shutdown_) { + DCHECK(!options_->GetSaveProfilingInfo() || !ProfileSaver::IsStarted()); + if (options_->DumpJitInfoOnShutdown()) { DumpInfo(LOG_STREAM(INFO)); Runtime::Current()->DumpDeoptimizations(LOG_STREAM(INFO)); } @@ -671,25 +656,25 @@ void Jit::AddSamples(Thread* self, ArtMethod* method, uint16_t count, bool with_ if (IgnoreSamplesForMethod(method)) { return; } - if (hot_method_threshold_ == 0) { + if (HotMethodThreshold() == 0) { // Tests might request JIT on first use (compiled synchronously in the interpreter). return; } DCHECK(thread_pool_ != nullptr); - DCHECK_GT(warm_method_threshold_, 0); - DCHECK_GT(hot_method_threshold_, warm_method_threshold_); - DCHECK_GT(osr_method_threshold_, hot_method_threshold_); - DCHECK_GE(priority_thread_weight_, 1); - DCHECK_LE(priority_thread_weight_, hot_method_threshold_); + DCHECK_GT(WarmMethodThreshold(), 0); + DCHECK_GT(HotMethodThreshold(), WarmMethodThreshold()); + DCHECK_GT(OSRMethodThreshold(), HotMethodThreshold()); + DCHECK_GE(PriorityThreadWeight(), 1); + DCHECK_LE(PriorityThreadWeight(), HotMethodThreshold()); - int32_t starting_count = method->GetCounter(); + uint16_t starting_count = method->GetCounter(); if (Jit::ShouldUsePriorityThreadWeight(self)) { - count *= priority_thread_weight_; + count *= PriorityThreadWeight(); } - int32_t new_count = starting_count + count; // int32 here to avoid wrap-around; + uint32_t new_count = starting_count + count; // Note: Native method have no "warm" state or profiling info. - if (LIKELY(!method->IsNative()) && starting_count < warm_method_threshold_) { - if ((new_count >= warm_method_threshold_) && + if (LIKELY(!method->IsNative()) && starting_count < WarmMethodThreshold()) { + if ((new_count >= WarmMethodThreshold()) && (method->GetProfilingInfo(kRuntimePointerSize) == nullptr)) { bool success = ProfilingInfo::Create(self, method, /* retry_allocation */ false); if (success) { @@ -710,23 +695,23 @@ void Jit::AddSamples(Thread* self, ArtMethod* method, uint16_t count, bool with_ } } // Avoid jumping more than one state at a time. - new_count = std::min(new_count, hot_method_threshold_ - 1); - } else if (use_jit_compilation_) { - if (starting_count < hot_method_threshold_) { - if ((new_count >= hot_method_threshold_) && + new_count = std::min(new_count, static_cast<uint32_t>(HotMethodThreshold() - 1)); + } else if (UseJitCompilation()) { + if (starting_count < HotMethodThreshold()) { + if ((new_count >= HotMethodThreshold()) && !code_cache_->ContainsPc(method->GetEntryPointFromQuickCompiledCode())) { DCHECK(thread_pool_ != nullptr); thread_pool_->AddTask(self, new JitCompileTask(method, JitCompileTask::kCompile)); } // Avoid jumping more than one state at a time. - new_count = std::min(new_count, osr_method_threshold_ - 1); - } else if (starting_count < osr_method_threshold_) { + new_count = std::min(new_count, static_cast<uint32_t>(OSRMethodThreshold() - 1)); + } else if (starting_count < OSRMethodThreshold()) { if (!with_backedges) { // If the samples don't contain any back edge, we don't increment the hotness. return; } DCHECK(!method->IsNative()); // No back edges reported for native methods. - if ((new_count >= osr_method_threshold_) && !code_cache_->IsOsrCompiled(method)) { + if ((new_count >= OSRMethodThreshold()) && !code_cache_->IsOsrCompiled(method)) { DCHECK(thread_pool_ != nullptr); thread_pool_->AddTask(self, new JitCompileTask(method, JitCompileTask::kCompileOsr)); } diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h index 4b8b8919d1..edaf348cc4 100644 --- a/runtime/jit/jit.h +++ b/runtime/jit/jit.h @@ -44,6 +44,110 @@ class JitOptions; static constexpr int16_t kJitCheckForOSR = -1; static constexpr int16_t kJitHotnessDisabled = -2; +// At what priority to schedule jit threads. 9 is the lowest foreground priority on device. +// See android/os/Process.java. +static constexpr int kJitPoolThreadPthreadDefaultPriority = 9; + +class JitOptions { + public: + static JitOptions* CreateFromRuntimeArguments(const RuntimeArgumentMap& options); + + uint16_t GetCompileThreshold() const { + return compile_threshold_; + } + + uint16_t GetWarmupThreshold() const { + return warmup_threshold_; + } + + uint16_t GetOsrThreshold() const { + return osr_threshold_; + } + + uint16_t GetPriorityThreadWeight() const { + return priority_thread_weight_; + } + + uint16_t GetInvokeTransitionWeight() const { + return invoke_transition_weight_; + } + + size_t GetCodeCacheInitialCapacity() const { + return code_cache_initial_capacity_; + } + + size_t GetCodeCacheMaxCapacity() const { + return code_cache_max_capacity_; + } + + bool DumpJitInfoOnShutdown() const { + return dump_info_on_shutdown_; + } + + const ProfileSaverOptions& GetProfileSaverOptions() const { + return profile_saver_options_; + } + + bool GetSaveProfilingInfo() const { + return profile_saver_options_.IsEnabled(); + } + + int GetThreadPoolPthreadPriority() const { + return thread_pool_pthread_priority_; + } + + bool UseJitCompilation() const { + return use_jit_compilation_; + } + + void SetUseJitCompilation(bool b) { + use_jit_compilation_ = b; + } + + void SetSaveProfilingInfo(bool save_profiling_info) { + profile_saver_options_.SetEnabled(save_profiling_info); + } + + void SetWaitForJitNotificationsToSaveProfile(bool value) { + profile_saver_options_.SetWaitForJitNotificationsToSave(value); + } + + void SetProfileAOTCode(bool value) { + profile_saver_options_.SetProfileAOTCode(value); + } + + void SetJitAtFirstUse() { + use_jit_compilation_ = true; + compile_threshold_ = 0; + } + + private: + bool use_jit_compilation_; + size_t code_cache_initial_capacity_; + size_t code_cache_max_capacity_; + uint16_t compile_threshold_; + uint16_t warmup_threshold_; + uint16_t osr_threshold_; + uint16_t priority_thread_weight_; + uint16_t invoke_transition_weight_; + bool dump_info_on_shutdown_; + int thread_pool_pthread_priority_; + ProfileSaverOptions profile_saver_options_; + + JitOptions() + : use_jit_compilation_(false), + code_cache_initial_capacity_(0), + code_cache_max_capacity_(0), + compile_threshold_(0), + warmup_threshold_(0), + osr_threshold_(0), + priority_thread_weight_(0), + invoke_transition_weight_(0), + dump_info_on_shutdown_(false), + thread_pool_pthread_priority_(kJitPoolThreadPthreadDefaultPriority) {} + + DISALLOW_COPY_AND_ASSIGN(JitOptions); +}; class Jit { public: @@ -77,29 +181,29 @@ class Jit { REQUIRES(!lock_) REQUIRES_SHARED(Locks::mutator_lock_); - size_t OSRMethodThreshold() const { - return osr_method_threshold_; + uint16_t OSRMethodThreshold() const { + return options_->GetOsrThreshold(); } - size_t HotMethodThreshold() const { - return hot_method_threshold_; + uint16_t HotMethodThreshold() const { + return options_->GetCompileThreshold(); } - size_t WarmMethodThreshold() const { - return warm_method_threshold_; + uint16_t WarmMethodThreshold() const { + return options_->GetWarmupThreshold(); } uint16_t PriorityThreadWeight() const { - return priority_thread_weight_; + return options_->GetPriorityThreadWeight(); } // Returns false if we only need to save profile information and not compile methods. bool UseJitCompilation() const { - return use_jit_compilation_; + return options_->UseJitCompilation(); } bool GetSaveProfilingInfo() const { - return profile_saver_options_.IsEnabled(); + return options_->GetSaveProfilingInfo(); } // Wait until there is no more pending compilation tasks. @@ -120,12 +224,12 @@ class Jit { void NotifyInterpreterToCompiledCodeTransition(Thread* self, ArtMethod* caller) REQUIRES_SHARED(Locks::mutator_lock_) { - AddSamples(self, caller, invoke_transition_weight_, false); + AddSamples(self, caller, options_->GetInvokeTransitionWeight(), false); } void NotifyCompiledCodeToInterpreterTransition(Thread* self, ArtMethod* callee) REQUIRES_SHARED(Locks::mutator_lock_) { - AddSamples(self, callee, invoke_transition_weight_, false); + AddSamples(self, callee, options_->GetInvokeTransitionWeight(), false); } // Starts the profile saver if the config options allow profile recording. @@ -177,7 +281,7 @@ class Jit { void Start(); private: - Jit(); + explicit Jit(JitOptions* options); static bool LoadCompiler(std::string* error_msg); @@ -189,107 +293,22 @@ class Jit { static bool (*jit_compile_method_)(void*, ArtMethod*, Thread*, bool); static void (*jit_types_loaded_)(void*, mirror::Class**, size_t count); + // We make this static to simplify the interaction with libart-compiler.so. + static bool generate_debug_info_; + + const JitOptions* const options_; + + std::unique_ptr<jit::JitCodeCache> code_cache_; + std::unique_ptr<ThreadPool> thread_pool_; + // Performance monitoring. - bool dump_info_on_shutdown_; CumulativeLogger cumulative_timings_; Histogram<uint64_t> memory_use_ GUARDED_BY(lock_); Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; - std::unique_ptr<jit::JitCodeCache> code_cache_; - - bool use_jit_compilation_; - ProfileSaverOptions profile_saver_options_; - static bool generate_debug_info_; - uint16_t hot_method_threshold_; - uint16_t warm_method_threshold_; - uint16_t osr_method_threshold_; - uint16_t priority_thread_weight_; - uint16_t invoke_transition_weight_; - std::unique_ptr<ThreadPool> thread_pool_; - DISALLOW_COPY_AND_ASSIGN(Jit); }; -class JitOptions { - public: - static JitOptions* CreateFromRuntimeArguments(const RuntimeArgumentMap& options); - size_t GetCompileThreshold() const { - return compile_threshold_; - } - size_t GetWarmupThreshold() const { - return warmup_threshold_; - } - size_t GetOsrThreshold() const { - return osr_threshold_; - } - uint16_t GetPriorityThreadWeight() const { - return priority_thread_weight_; - } - size_t GetInvokeTransitionWeight() const { - return invoke_transition_weight_; - } - size_t GetCodeCacheInitialCapacity() const { - return code_cache_initial_capacity_; - } - size_t GetCodeCacheMaxCapacity() const { - return code_cache_max_capacity_; - } - bool DumpJitInfoOnShutdown() const { - return dump_info_on_shutdown_; - } - const ProfileSaverOptions& GetProfileSaverOptions() const { - return profile_saver_options_; - } - bool GetSaveProfilingInfo() const { - return profile_saver_options_.IsEnabled(); - } - bool UseJitCompilation() const { - return use_jit_compilation_; - } - void SetUseJitCompilation(bool b) { - use_jit_compilation_ = b; - } - void SetSaveProfilingInfo(bool save_profiling_info) { - profile_saver_options_.SetEnabled(save_profiling_info); - } - void SetWaitForJitNotificationsToSaveProfile(bool value) { - profile_saver_options_.SetWaitForJitNotificationsToSave(value); - } - void SetProfileAOTCode(bool value) { - profile_saver_options_.SetProfileAOTCode(value); - } - - void SetJitAtFirstUse() { - use_jit_compilation_ = true; - compile_threshold_ = 0; - } - - private: - bool use_jit_compilation_; - size_t code_cache_initial_capacity_; - size_t code_cache_max_capacity_; - size_t compile_threshold_; - size_t warmup_threshold_; - size_t osr_threshold_; - uint16_t priority_thread_weight_; - size_t invoke_transition_weight_; - bool dump_info_on_shutdown_; - ProfileSaverOptions profile_saver_options_; - - JitOptions() - : use_jit_compilation_(false), - code_cache_initial_capacity_(0), - code_cache_max_capacity_(0), - compile_threshold_(0), - warmup_threshold_(0), - osr_threshold_(0), - priority_thread_weight_(0), - invoke_transition_weight_(0), - dump_info_on_shutdown_(false) {} - - DISALLOW_COPY_AND_ASSIGN(JitOptions); -}; - // Helper class to stop the JIT for a given scope. This will wait for the JIT to quiesce. class ScopedJitSuspend { public: diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index 3aa481af8c..7383d477bb 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -194,6 +194,9 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize .Define("-Xjittransitionweight:_") .WithType<unsigned int>() .IntoKey(M::JITInvokeTransitionWeight) + .Define("-Xjitpthreadpriority:_") + .WithType<int>() + .IntoKey(M::JITPoolThreadPthreadPriority) .Define("-Xjitsaveprofilinginfo") .WithType<ProfileSaverOptions>() .AppendValues() diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def index 427385d914..e647423b9c 100644 --- a/runtime/runtime_options.def +++ b/runtime/runtime_options.def @@ -77,6 +77,7 @@ RUNTIME_OPTIONS_KEY (unsigned int, JITWarmupThreshold) RUNTIME_OPTIONS_KEY (unsigned int, JITOsrThreshold) RUNTIME_OPTIONS_KEY (unsigned int, JITPriorityThreadWeight) RUNTIME_OPTIONS_KEY (unsigned int, JITInvokeTransitionWeight) +RUNTIME_OPTIONS_KEY (int, JITPoolThreadPthreadPriority, jit::kJitPoolThreadPthreadDefaultPriority) RUNTIME_OPTIONS_KEY (MemoryKiB, JITCodeCacheInitialCapacity, jit::JitCodeCache::kInitialCapacity) RUNTIME_OPTIONS_KEY (MemoryKiB, JITCodeCacheMaxCapacity, jit::JitCodeCache::kMaxCapacity) RUNTIME_OPTIONS_KEY (MillisecondsToNanoseconds, \ |