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