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