1 /* 2 * Copyright 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_JIT_JIT_H_ 18 #define ART_RUNTIME_JIT_JIT_H_ 19 20 #include "base/histogram-inl.h" 21 #include "base/macros.h" 22 #include "base/mutex.h" 23 #include "base/timing_logger.h" 24 #include "jit/profile_saver_options.h" 25 #include "obj_ptr.h" 26 #include "thread_pool.h" 27 28 namespace art { 29 30 class ArtMethod; 31 class ClassLinker; 32 struct RuntimeArgumentMap; 33 union JValue; 34 35 namespace mirror { 36 class Object; 37 class Class; 38 } // namespace mirror 39 40 namespace jit { 41 42 class JitCodeCache; 43 class JitOptions; 44 45 static constexpr int16_t kJitCheckForOSR = -1; 46 static constexpr int16_t kJitHotnessDisabled = -2; 47 48 class Jit { 49 public: 50 static constexpr size_t kDefaultPriorityThreadWeightRatio = 1000; 51 static constexpr size_t kDefaultInvokeTransitionWeightRatio = 500; 52 // How frequently should the interpreter check to see if OSR compilation is ready. 53 static constexpr int16_t kJitRecheckOSRThreshold = 100; 54 55 virtual ~Jit(); 56 static Jit* Create(JitOptions* options, std::string* error_msg); 57 bool CompileMethod(ArtMethod* method, Thread* self, bool osr) 58 REQUIRES_SHARED(Locks::mutator_lock_); 59 void CreateThreadPool(); 60 GetCodeCache()61 const JitCodeCache* GetCodeCache() const { 62 return code_cache_.get(); 63 } 64 GetCodeCache()65 JitCodeCache* GetCodeCache() { 66 return code_cache_.get(); 67 } 68 69 void DeleteThreadPool(); 70 // Dump interesting info: #methods compiled, code vs data size, compile / verify cumulative 71 // loggers. 72 void DumpInfo(std::ostream& os) REQUIRES(!lock_); 73 // Add a timing logger to cumulative_timings_. 74 void AddTimingLogger(const TimingLogger& logger); 75 76 void AddMemoryUsage(ArtMethod* method, size_t bytes) 77 REQUIRES(!lock_) 78 REQUIRES_SHARED(Locks::mutator_lock_); 79 OSRMethodThreshold()80 size_t OSRMethodThreshold() const { 81 return osr_method_threshold_; 82 } 83 HotMethodThreshold()84 size_t HotMethodThreshold() const { 85 return hot_method_threshold_; 86 } 87 WarmMethodThreshold()88 size_t WarmMethodThreshold() const { 89 return warm_method_threshold_; 90 } 91 PriorityThreadWeight()92 uint16_t PriorityThreadWeight() const { 93 return priority_thread_weight_; 94 } 95 96 // Returns false if we only need to save profile information and not compile methods. UseJitCompilation()97 bool UseJitCompilation() const { 98 return use_jit_compilation_; 99 } 100 GetSaveProfilingInfo()101 bool GetSaveProfilingInfo() const { 102 return profile_saver_options_.IsEnabled(); 103 } 104 105 // Wait until there is no more pending compilation tasks. 106 void WaitForCompilationToFinish(Thread* self); 107 108 // Profiling methods. 109 void MethodEntered(Thread* thread, ArtMethod* method) 110 REQUIRES_SHARED(Locks::mutator_lock_); 111 112 void AddSamples(Thread* self, ArtMethod* method, uint16_t samples, bool with_backedges) 113 REQUIRES_SHARED(Locks::mutator_lock_); 114 115 void InvokeVirtualOrInterface(ObjPtr<mirror::Object> this_object, 116 ArtMethod* caller, 117 uint32_t dex_pc, 118 ArtMethod* callee) 119 REQUIRES_SHARED(Locks::mutator_lock_); 120 NotifyInterpreterToCompiledCodeTransition(Thread * self,ArtMethod * caller)121 void NotifyInterpreterToCompiledCodeTransition(Thread* self, ArtMethod* caller) 122 REQUIRES_SHARED(Locks::mutator_lock_) { 123 AddSamples(self, caller, invoke_transition_weight_, false); 124 } 125 NotifyCompiledCodeToInterpreterTransition(Thread * self,ArtMethod * callee)126 void NotifyCompiledCodeToInterpreterTransition(Thread* self, ArtMethod* callee) 127 REQUIRES_SHARED(Locks::mutator_lock_) { 128 AddSamples(self, callee, invoke_transition_weight_, false); 129 } 130 131 // Starts the profile saver if the config options allow profile recording. 132 // The profile will be stored in the specified `filename` and will contain 133 // information collected from the given `code_paths` (a set of dex locations). 134 void StartProfileSaver(const std::string& filename, 135 const std::vector<std::string>& code_paths); 136 void StopProfileSaver(); 137 138 void DumpForSigQuit(std::ostream& os) REQUIRES(!lock_); 139 140 static void NewTypeLoadedIfUsingJit(mirror::Class* type) 141 REQUIRES_SHARED(Locks::mutator_lock_); 142 143 // If debug info generation is turned on then write the type information for types already loaded 144 // into the specified class linker to the jit debug interface, 145 void DumpTypeInfoForLoadedTypes(ClassLinker* linker); 146 147 // Return whether we should try to JIT compiled code as soon as an ArtMethod is invoked. 148 bool JitAtFirstUse(); 149 150 // Return whether we can invoke JIT code for `method`. 151 bool CanInvokeCompiledCode(ArtMethod* method); 152 153 // Return whether the runtime should use a priority thread weight when sampling. 154 static bool ShouldUsePriorityThreadWeight(Thread* self); 155 156 // If an OSR compiled version is available for `method`, 157 // and `dex_pc + dex_pc_offset` is an entry point of that compiled 158 // version, this method will jump to the compiled code, let it run, 159 // and return true afterwards. Return false otherwise. 160 static bool MaybeDoOnStackReplacement(Thread* thread, 161 ArtMethod* method, 162 uint32_t dex_pc, 163 int32_t dex_pc_offset, 164 JValue* result) 165 REQUIRES_SHARED(Locks::mutator_lock_); 166 167 static bool LoadCompilerLibrary(std::string* error_msg); 168 GetThreadPool()169 ThreadPool* GetThreadPool() const { 170 return thread_pool_.get(); 171 } 172 173 // Stop the JIT by waiting for all current compilations and enqueued compilations to finish. 174 void Stop(); 175 176 // Start JIT threads. 177 void Start(); 178 179 private: 180 Jit(); 181 182 static bool LoadCompiler(std::string* error_msg); 183 184 // JIT compiler 185 static void* jit_library_handle_; 186 static void* jit_compiler_handle_; 187 static void* (*jit_load_)(bool*); 188 static void (*jit_unload_)(void*); 189 static bool (*jit_compile_method_)(void*, ArtMethod*, Thread*, bool); 190 static void (*jit_types_loaded_)(void*, mirror::Class**, size_t count); 191 192 // Performance monitoring. 193 bool dump_info_on_shutdown_; 194 CumulativeLogger cumulative_timings_; 195 Histogram<uint64_t> memory_use_ GUARDED_BY(lock_); 196 Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; 197 198 std::unique_ptr<jit::JitCodeCache> code_cache_; 199 200 bool use_jit_compilation_; 201 ProfileSaverOptions profile_saver_options_; 202 static bool generate_debug_info_; 203 uint16_t hot_method_threshold_; 204 uint16_t warm_method_threshold_; 205 uint16_t osr_method_threshold_; 206 uint16_t priority_thread_weight_; 207 uint16_t invoke_transition_weight_; 208 std::unique_ptr<ThreadPool> thread_pool_; 209 210 DISALLOW_COPY_AND_ASSIGN(Jit); 211 }; 212 213 class JitOptions { 214 public: 215 static JitOptions* CreateFromRuntimeArguments(const RuntimeArgumentMap& options); GetCompileThreshold()216 size_t GetCompileThreshold() const { 217 return compile_threshold_; 218 } GetWarmupThreshold()219 size_t GetWarmupThreshold() const { 220 return warmup_threshold_; 221 } GetOsrThreshold()222 size_t GetOsrThreshold() const { 223 return osr_threshold_; 224 } GetPriorityThreadWeight()225 uint16_t GetPriorityThreadWeight() const { 226 return priority_thread_weight_; 227 } GetInvokeTransitionWeight()228 size_t GetInvokeTransitionWeight() const { 229 return invoke_transition_weight_; 230 } GetCodeCacheInitialCapacity()231 size_t GetCodeCacheInitialCapacity() const { 232 return code_cache_initial_capacity_; 233 } GetCodeCacheMaxCapacity()234 size_t GetCodeCacheMaxCapacity() const { 235 return code_cache_max_capacity_; 236 } DumpJitInfoOnShutdown()237 bool DumpJitInfoOnShutdown() const { 238 return dump_info_on_shutdown_; 239 } GetProfileSaverOptions()240 const ProfileSaverOptions& GetProfileSaverOptions() const { 241 return profile_saver_options_; 242 } GetSaveProfilingInfo()243 bool GetSaveProfilingInfo() const { 244 return profile_saver_options_.IsEnabled(); 245 } UseJitCompilation()246 bool UseJitCompilation() const { 247 return use_jit_compilation_; 248 } SetUseJitCompilation(bool b)249 void SetUseJitCompilation(bool b) { 250 use_jit_compilation_ = b; 251 } SetSaveProfilingInfo(bool save_profiling_info)252 void SetSaveProfilingInfo(bool save_profiling_info) { 253 profile_saver_options_.SetEnabled(save_profiling_info); 254 } SetWaitForJitNotificationsToSaveProfile(bool value)255 void SetWaitForJitNotificationsToSaveProfile(bool value) { 256 profile_saver_options_.SetWaitForJitNotificationsToSave(value); 257 } SetProfileAOTCode(bool value)258 void SetProfileAOTCode(bool value) { 259 profile_saver_options_.SetProfileAOTCode(value); 260 } 261 SetJitAtFirstUse()262 void SetJitAtFirstUse() { 263 use_jit_compilation_ = true; 264 compile_threshold_ = 0; 265 } 266 267 private: 268 bool use_jit_compilation_; 269 size_t code_cache_initial_capacity_; 270 size_t code_cache_max_capacity_; 271 size_t compile_threshold_; 272 size_t warmup_threshold_; 273 size_t osr_threshold_; 274 uint16_t priority_thread_weight_; 275 size_t invoke_transition_weight_; 276 bool dump_info_on_shutdown_; 277 ProfileSaverOptions profile_saver_options_; 278 JitOptions()279 JitOptions() 280 : use_jit_compilation_(false), 281 code_cache_initial_capacity_(0), 282 code_cache_max_capacity_(0), 283 compile_threshold_(0), 284 warmup_threshold_(0), 285 osr_threshold_(0), 286 priority_thread_weight_(0), 287 invoke_transition_weight_(0), 288 dump_info_on_shutdown_(false) {} 289 290 DISALLOW_COPY_AND_ASSIGN(JitOptions); 291 }; 292 293 // Helper class to stop the JIT for a given scope. This will wait for the JIT to quiesce. 294 class ScopedJitSuspend { 295 public: 296 ScopedJitSuspend(); 297 ~ScopedJitSuspend(); 298 299 private: 300 bool was_on_; 301 }; 302 303 } // namespace jit 304 } // namespace art 305 306 #endif // ART_RUNTIME_JIT_JIT_H_ 307