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 "object_callbacks.h" 26 #include "offline_profiling_info.h" 27 #include "thread_pool.h" 28 29 namespace art { 30 31 class ArtMethod; 32 struct RuntimeArgumentMap; 33 34 namespace jit { 35 36 class JitCodeCache; 37 class JitOptions; 38 39 static constexpr int16_t kJitCheckForOSR = -1; 40 static constexpr int16_t kJitHotnessDisabled = -2; 41 42 class Jit { 43 public: 44 static constexpr bool kStressMode = kIsDebugBuild; 45 static constexpr size_t kDefaultCompileThreshold = kStressMode ? 2 : 10000; 46 static constexpr size_t kDefaultPriorityThreadWeightRatio = 1000; 47 static constexpr size_t kDefaultInvokeTransitionWeightRatio = 500; 48 49 virtual ~Jit(); 50 static Jit* Create(JitOptions* options, std::string* error_msg); 51 bool CompileMethod(ArtMethod* method, Thread* self, bool osr) 52 SHARED_REQUIRES(Locks::mutator_lock_); 53 void CreateThreadPool(); 54 GetCodeCache()55 const JitCodeCache* GetCodeCache() const { 56 return code_cache_.get(); 57 } 58 GetCodeCache()59 JitCodeCache* GetCodeCache() { 60 return code_cache_.get(); 61 } 62 63 void DeleteThreadPool(); 64 // Dump interesting info: #methods compiled, code vs data size, compile / verify cumulative 65 // loggers. 66 void DumpInfo(std::ostream& os) REQUIRES(!lock_); 67 // Add a timing logger to cumulative_timings_. 68 void AddTimingLogger(const TimingLogger& logger); 69 70 void AddMemoryUsage(ArtMethod* method, size_t bytes) 71 REQUIRES(!lock_) 72 SHARED_REQUIRES(Locks::mutator_lock_); 73 OSRMethodThreshold()74 size_t OSRMethodThreshold() const { 75 return osr_method_threshold_; 76 } 77 HotMethodThreshold()78 size_t HotMethodThreshold() const { 79 return hot_method_threshold_; 80 } 81 WarmMethodThreshold()82 size_t WarmMethodThreshold() const { 83 return warm_method_threshold_; 84 } 85 PriorityThreadWeight()86 uint16_t PriorityThreadWeight() const { 87 return priority_thread_weight_; 88 } 89 90 // Returns false if we only need to save profile information and not compile methods. UseJitCompilation()91 bool UseJitCompilation() const { 92 return use_jit_compilation_; 93 } 94 SaveProfilingInfo()95 bool SaveProfilingInfo() const { 96 return save_profiling_info_; 97 } 98 99 // Wait until there is no more pending compilation tasks. 100 void WaitForCompilationToFinish(Thread* self); 101 102 // Profiling methods. 103 void MethodEntered(Thread* thread, ArtMethod* method) 104 SHARED_REQUIRES(Locks::mutator_lock_); 105 106 void AddSamples(Thread* self, ArtMethod* method, uint16_t samples, bool with_backedges) 107 SHARED_REQUIRES(Locks::mutator_lock_); 108 109 void InvokeVirtualOrInterface(Thread* thread, 110 mirror::Object* this_object, 111 ArtMethod* caller, 112 uint32_t dex_pc, 113 ArtMethod* callee) 114 SHARED_REQUIRES(Locks::mutator_lock_); 115 NotifyInterpreterToCompiledCodeTransition(Thread * self,ArtMethod * caller)116 void NotifyInterpreterToCompiledCodeTransition(Thread* self, ArtMethod* caller) 117 SHARED_REQUIRES(Locks::mutator_lock_) { 118 AddSamples(self, caller, invoke_transition_weight_, false); 119 } 120 NotifyCompiledCodeToInterpreterTransition(Thread * self,ArtMethod * callee)121 void NotifyCompiledCodeToInterpreterTransition(Thread* self, ArtMethod* callee) 122 SHARED_REQUIRES(Locks::mutator_lock_) { 123 AddSamples(self, callee, invoke_transition_weight_, false); 124 } 125 126 // Starts the profile saver if the config options allow profile recording. 127 // The profile will be stored in the specified `filename` and will contain 128 // information collected from the given `code_paths` (a set of dex locations). 129 // The `foreign_dex_profile_path` is the path where the saver will put the 130 // profile markers for loaded dex files which are not owned by the application. 131 // The `app_dir` is the application directory and is used to decide which 132 // dex files belong to the application. 133 void StartProfileSaver(const std::string& filename, 134 const std::vector<std::string>& code_paths, 135 const std::string& foreign_dex_profile_path, 136 const std::string& app_dir); 137 void StopProfileSaver(); 138 139 void DumpForSigQuit(std::ostream& os) REQUIRES(!lock_); 140 141 static void NewTypeLoadedIfUsingJit(mirror::Class* type) 142 SHARED_REQUIRES(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 SHARED_REQUIRES(Locks::mutator_lock_); 167 168 static bool LoadCompilerLibrary(std::string* error_msg); 169 170 private: 171 Jit(); 172 173 static bool LoadCompiler(std::string* error_msg); 174 175 // JIT compiler 176 static void* jit_library_handle_; 177 static void* jit_compiler_handle_; 178 static void* (*jit_load_)(bool*); 179 static void (*jit_unload_)(void*); 180 static bool (*jit_compile_method_)(void*, ArtMethod*, Thread*, bool); 181 static void (*jit_types_loaded_)(void*, mirror::Class**, size_t count); 182 183 // Performance monitoring. 184 bool dump_info_on_shutdown_; 185 CumulativeLogger cumulative_timings_; 186 Histogram<uint64_t> memory_use_ GUARDED_BY(lock_); 187 Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; 188 189 std::unique_ptr<jit::JitCodeCache> code_cache_; 190 191 bool use_jit_compilation_; 192 bool save_profiling_info_; 193 static bool generate_debug_info_; 194 uint16_t hot_method_threshold_; 195 uint16_t warm_method_threshold_; 196 uint16_t osr_method_threshold_; 197 uint16_t priority_thread_weight_; 198 uint16_t invoke_transition_weight_; 199 std::unique_ptr<ThreadPool> thread_pool_; 200 201 DISALLOW_COPY_AND_ASSIGN(Jit); 202 }; 203 204 class JitOptions { 205 public: 206 static JitOptions* CreateFromRuntimeArguments(const RuntimeArgumentMap& options); GetCompileThreshold()207 size_t GetCompileThreshold() const { 208 return compile_threshold_; 209 } GetWarmupThreshold()210 size_t GetWarmupThreshold() const { 211 return warmup_threshold_; 212 } GetOsrThreshold()213 size_t GetOsrThreshold() const { 214 return osr_threshold_; 215 } GetPriorityThreadWeight()216 uint16_t GetPriorityThreadWeight() const { 217 return priority_thread_weight_; 218 } GetInvokeTransitionWeight()219 size_t GetInvokeTransitionWeight() const { 220 return invoke_transition_weight_; 221 } GetCodeCacheInitialCapacity()222 size_t GetCodeCacheInitialCapacity() const { 223 return code_cache_initial_capacity_; 224 } GetCodeCacheMaxCapacity()225 size_t GetCodeCacheMaxCapacity() const { 226 return code_cache_max_capacity_; 227 } DumpJitInfoOnShutdown()228 bool DumpJitInfoOnShutdown() const { 229 return dump_info_on_shutdown_; 230 } GetSaveProfilingInfo()231 bool GetSaveProfilingInfo() const { 232 return save_profiling_info_; 233 } UseJitCompilation()234 bool UseJitCompilation() const { 235 return use_jit_compilation_; 236 } SetUseJitCompilation(bool b)237 void SetUseJitCompilation(bool b) { 238 use_jit_compilation_ = b; 239 } SetSaveProfilingInfo(bool b)240 void SetSaveProfilingInfo(bool b) { 241 save_profiling_info_ = b; 242 } SetJitAtFirstUse()243 void SetJitAtFirstUse() { 244 use_jit_compilation_ = true; 245 compile_threshold_ = 0; 246 } 247 248 private: 249 bool use_jit_compilation_; 250 size_t code_cache_initial_capacity_; 251 size_t code_cache_max_capacity_; 252 size_t compile_threshold_; 253 size_t warmup_threshold_; 254 size_t osr_threshold_; 255 uint16_t priority_thread_weight_; 256 size_t invoke_transition_weight_; 257 bool dump_info_on_shutdown_; 258 bool save_profiling_info_; 259 JitOptions()260 JitOptions() 261 : use_jit_compilation_(false), 262 code_cache_initial_capacity_(0), 263 code_cache_max_capacity_(0), 264 compile_threshold_(0), 265 dump_info_on_shutdown_(false), 266 save_profiling_info_(false) { } 267 268 DISALLOW_COPY_AND_ASSIGN(JitOptions); 269 }; 270 271 } // namespace jit 272 } // namespace art 273 274 #endif // ART_RUNTIME_JIT_JIT_H_ 275