• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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