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 
GetCodeCache()66   const JitCodeCache* GetCodeCache() const {
67     return code_cache_.get();
68   }
69 
GetCodeCache()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 
OSRMethodThreshold()85   size_t OSRMethodThreshold() const {
86     return osr_method_threshold_;
87   }
88 
HotMethodThreshold()89   size_t HotMethodThreshold() const {
90     return hot_method_threshold_;
91   }
92 
WarmMethodThreshold()93   size_t WarmMethodThreshold() const {
94     return warm_method_threshold_;
95   }
96 
PriorityThreadWeight()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.
UseJitCompilation()102   bool UseJitCompilation() const {
103     return use_jit_compilation_;
104   }
105 
GetSaveProfilingInfo()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 
NotifyInterpreterToCompiledCodeTransition(Thread * self,ArtMethod * caller)126   void NotifyInterpreterToCompiledCodeTransition(Thread* self, ArtMethod* caller)
127       REQUIRES_SHARED(Locks::mutator_lock_) {
128     AddSamples(self, caller, invoke_transition_weight_, false);
129   }
130 
NotifyCompiledCodeToInterpreterTransition(Thread * self,ArtMethod * callee)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 
GetThreadPool()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);
GetCompileThreshold()221   size_t GetCompileThreshold() const {
222     return compile_threshold_;
223   }
GetWarmupThreshold()224   size_t GetWarmupThreshold() const {
225     return warmup_threshold_;
226   }
GetOsrThreshold()227   size_t GetOsrThreshold() const {
228     return osr_threshold_;
229   }
GetPriorityThreadWeight()230   uint16_t GetPriorityThreadWeight() const {
231     return priority_thread_weight_;
232   }
GetInvokeTransitionWeight()233   size_t GetInvokeTransitionWeight() const {
234     return invoke_transition_weight_;
235   }
GetCodeCacheInitialCapacity()236   size_t GetCodeCacheInitialCapacity() const {
237     return code_cache_initial_capacity_;
238   }
GetCodeCacheMaxCapacity()239   size_t GetCodeCacheMaxCapacity() const {
240     return code_cache_max_capacity_;
241   }
DumpJitInfoOnShutdown()242   bool DumpJitInfoOnShutdown() const {
243     return dump_info_on_shutdown_;
244   }
GetProfileSaverOptions()245   const ProfileSaverOptions& GetProfileSaverOptions() const {
246     return profile_saver_options_;
247   }
GetSaveProfilingInfo()248   bool GetSaveProfilingInfo() const {
249     return profile_saver_options_.IsEnabled();
250   }
UseJitCompilation()251   bool UseJitCompilation() const {
252     return use_jit_compilation_;
253   }
SetUseJitCompilation(bool b)254   void SetUseJitCompilation(bool b) {
255     use_jit_compilation_ = b;
256   }
SetSaveProfilingInfo(bool save_profiling_info)257   void SetSaveProfilingInfo(bool save_profiling_info) {
258     profile_saver_options_.SetEnabled(save_profiling_info);
259   }
SetJitAtFirstUse()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 
JitOptions()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