• 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 "handle.h"
25 #include "jit/profile_saver_options.h"
26 #include "obj_ptr.h"
27 #include "thread_pool.h"
28 
29 namespace art {
30 
31 class ArtMethod;
32 class ClassLinker;
33 class DexFile;
34 class OatDexFile;
35 struct RuntimeArgumentMap;
36 union JValue;
37 
38 namespace mirror {
39 class Object;
40 class Class;
41 class ClassLoader;
42 }   // namespace mirror
43 
44 namespace jit {
45 
46 class JitCodeCache;
47 class JitOptions;
48 
49 static constexpr int16_t kJitCheckForOSR = -1;
50 static constexpr int16_t kJitHotnessDisabled = -2;
51 // At what priority to schedule jit threads. 9 is the lowest foreground priority on device.
52 // See android/os/Process.java.
53 static constexpr int kJitPoolThreadPthreadDefaultPriority = 9;
54 static constexpr uint32_t kJitSamplesBatchSize = 32;  // Must be power of 2.
55 
56 class JitOptions {
57  public:
58   static JitOptions* CreateFromRuntimeArguments(const RuntimeArgumentMap& options);
59 
GetCompileThreshold()60   uint16_t GetCompileThreshold() const {
61     return compile_threshold_;
62   }
63 
GetWarmupThreshold()64   uint16_t GetWarmupThreshold() const {
65     return warmup_threshold_;
66   }
67 
GetOsrThreshold()68   uint16_t GetOsrThreshold() const {
69     return osr_threshold_;
70   }
71 
GetPriorityThreadWeight()72   uint16_t GetPriorityThreadWeight() const {
73     return priority_thread_weight_;
74   }
75 
GetInvokeTransitionWeight()76   uint16_t GetInvokeTransitionWeight() const {
77     return invoke_transition_weight_;
78   }
79 
GetCodeCacheInitialCapacity()80   size_t GetCodeCacheInitialCapacity() const {
81     return code_cache_initial_capacity_;
82   }
83 
GetCodeCacheMaxCapacity()84   size_t GetCodeCacheMaxCapacity() const {
85     return code_cache_max_capacity_;
86   }
87 
DumpJitInfoOnShutdown()88   bool DumpJitInfoOnShutdown() const {
89     return dump_info_on_shutdown_;
90   }
91 
GetProfileSaverOptions()92   const ProfileSaverOptions& GetProfileSaverOptions() const {
93     return profile_saver_options_;
94   }
95 
GetSaveProfilingInfo()96   bool GetSaveProfilingInfo() const {
97     return profile_saver_options_.IsEnabled();
98   }
99 
GetThreadPoolPthreadPriority()100   int GetThreadPoolPthreadPriority() const {
101     return thread_pool_pthread_priority_;
102   }
103 
UseJitCompilation()104   bool UseJitCompilation() const {
105     return use_jit_compilation_;
106   }
107 
SetUseJitCompilation(bool b)108   void SetUseJitCompilation(bool b) {
109     use_jit_compilation_ = b;
110   }
111 
SetSaveProfilingInfo(bool save_profiling_info)112   void SetSaveProfilingInfo(bool save_profiling_info) {
113     profile_saver_options_.SetEnabled(save_profiling_info);
114   }
115 
SetWaitForJitNotificationsToSaveProfile(bool value)116   void SetWaitForJitNotificationsToSaveProfile(bool value) {
117     profile_saver_options_.SetWaitForJitNotificationsToSave(value);
118   }
119 
SetProfileAOTCode(bool value)120   void SetProfileAOTCode(bool value) {
121     profile_saver_options_.SetProfileAOTCode(value);
122   }
123 
SetJitAtFirstUse()124   void SetJitAtFirstUse() {
125     use_jit_compilation_ = true;
126     compile_threshold_ = 0;
127   }
128 
129  private:
130   // We add the sample in batches of size kJitSamplesBatchSize.
131   // This method rounds the threshold so that it is multiple of the batch size.
132   static uint32_t RoundUpThreshold(uint32_t threshold);
133 
134   bool use_jit_compilation_;
135   size_t code_cache_initial_capacity_;
136   size_t code_cache_max_capacity_;
137   uint32_t compile_threshold_;
138   uint32_t warmup_threshold_;
139   uint32_t osr_threshold_;
140   uint16_t priority_thread_weight_;
141   uint16_t invoke_transition_weight_;
142   bool dump_info_on_shutdown_;
143   int thread_pool_pthread_priority_;
144   ProfileSaverOptions profile_saver_options_;
145 
JitOptions()146   JitOptions()
147       : use_jit_compilation_(false),
148         code_cache_initial_capacity_(0),
149         code_cache_max_capacity_(0),
150         compile_threshold_(0),
151         warmup_threshold_(0),
152         osr_threshold_(0),
153         priority_thread_weight_(0),
154         invoke_transition_weight_(0),
155         dump_info_on_shutdown_(false),
156         thread_pool_pthread_priority_(kJitPoolThreadPthreadDefaultPriority) {}
157 
158   DISALLOW_COPY_AND_ASSIGN(JitOptions);
159 };
160 
161 class Jit {
162  public:
163   static constexpr size_t kDefaultPriorityThreadWeightRatio = 1000;
164   static constexpr size_t kDefaultInvokeTransitionWeightRatio = 500;
165   // How frequently should the interpreter check to see if OSR compilation is ready.
166   static constexpr int16_t kJitRecheckOSRThreshold = 101;  // Prime number to avoid patterns.
167 
168   virtual ~Jit();
169 
170   // Create JIT itself.
171   static Jit* Create(JitCodeCache* code_cache, JitOptions* options);
172 
173   bool CompileMethod(ArtMethod* method, Thread* self, bool baseline, bool osr)
174       REQUIRES_SHARED(Locks::mutator_lock_);
175 
GetCodeCache()176   const JitCodeCache* GetCodeCache() const {
177     return code_cache_;
178   }
179 
GetCodeCache()180   JitCodeCache* GetCodeCache() {
181     return code_cache_;
182   }
183 
184   void CreateThreadPool();
185   void DeleteThreadPool();
186   void WaitForWorkersToBeCreated();
187 
188   // Dump interesting info: #methods compiled, code vs data size, compile / verify cumulative
189   // loggers.
190   void DumpInfo(std::ostream& os) REQUIRES(!lock_);
191   // Add a timing logger to cumulative_timings_.
192   void AddTimingLogger(const TimingLogger& logger);
193 
194   void AddMemoryUsage(ArtMethod* method, size_t bytes)
195       REQUIRES(!lock_)
196       REQUIRES_SHARED(Locks::mutator_lock_);
197 
OSRMethodThreshold()198   uint16_t OSRMethodThreshold() const {
199     return options_->GetOsrThreshold();
200   }
201 
HotMethodThreshold()202   uint16_t HotMethodThreshold() const {
203     return options_->GetCompileThreshold();
204   }
205 
WarmMethodThreshold()206   uint16_t WarmMethodThreshold() const {
207     return options_->GetWarmupThreshold();
208   }
209 
PriorityThreadWeight()210   uint16_t PriorityThreadWeight() const {
211     return options_->GetPriorityThreadWeight();
212   }
213 
214   // Returns false if we only need to save profile information and not compile methods.
UseJitCompilation()215   bool UseJitCompilation() const {
216     return options_->UseJitCompilation();
217   }
218 
GetSaveProfilingInfo()219   bool GetSaveProfilingInfo() const {
220     return options_->GetSaveProfilingInfo();
221   }
222 
223   // Wait until there is no more pending compilation tasks.
224   void WaitForCompilationToFinish(Thread* self);
225 
226   // Profiling methods.
227   void MethodEntered(Thread* thread, ArtMethod* method)
228       REQUIRES_SHARED(Locks::mutator_lock_);
229 
230   ALWAYS_INLINE void AddSamples(Thread* self,
231                                 ArtMethod* method,
232                                 uint16_t samples,
233                                 bool with_backedges)
234       REQUIRES_SHARED(Locks::mutator_lock_);
235 
236   void InvokeVirtualOrInterface(ObjPtr<mirror::Object> this_object,
237                                 ArtMethod* caller,
238                                 uint32_t dex_pc,
239                                 ArtMethod* callee)
240       REQUIRES_SHARED(Locks::mutator_lock_);
241 
NotifyInterpreterToCompiledCodeTransition(Thread * self,ArtMethod * caller)242   void NotifyInterpreterToCompiledCodeTransition(Thread* self, ArtMethod* caller)
243       REQUIRES_SHARED(Locks::mutator_lock_) {
244     AddSamples(self, caller, options_->GetInvokeTransitionWeight(), false);
245   }
246 
NotifyCompiledCodeToInterpreterTransition(Thread * self,ArtMethod * callee)247   void NotifyCompiledCodeToInterpreterTransition(Thread* self, ArtMethod* callee)
248       REQUIRES_SHARED(Locks::mutator_lock_) {
249     AddSamples(self, callee, options_->GetInvokeTransitionWeight(), false);
250   }
251 
252   // Starts the profile saver if the config options allow profile recording.
253   // The profile will be stored in the specified `filename` and will contain
254   // information collected from the given `code_paths` (a set of dex locations).
255   void StartProfileSaver(const std::string& filename,
256                          const std::vector<std::string>& code_paths);
257   void StopProfileSaver();
258 
259   void DumpForSigQuit(std::ostream& os) REQUIRES(!lock_);
260 
261   static void NewTypeLoadedIfUsingJit(mirror::Class* type)
262       REQUIRES_SHARED(Locks::mutator_lock_);
263 
264   // If debug info generation is turned on then write the type information for types already loaded
265   // into the specified class linker to the jit debug interface,
266   void DumpTypeInfoForLoadedTypes(ClassLinker* linker);
267 
268   // Return whether we should try to JIT compiled code as soon as an ArtMethod is invoked.
269   bool JitAtFirstUse();
270 
271   // Return whether we can invoke JIT code for `method`.
272   bool CanInvokeCompiledCode(ArtMethod* method);
273 
274   // Return whether the runtime should use a priority thread weight when sampling.
275   static bool ShouldUsePriorityThreadWeight(Thread* self);
276 
277   // If an OSR compiled version is available for `method`,
278   // and `dex_pc + dex_pc_offset` is an entry point of that compiled
279   // version, this method will jump to the compiled code, let it run,
280   // and return true afterwards. Return false otherwise.
281   static bool MaybeDoOnStackReplacement(Thread* thread,
282                                         ArtMethod* method,
283                                         uint32_t dex_pc,
284                                         int32_t dex_pc_offset,
285                                         JValue* result)
286       REQUIRES_SHARED(Locks::mutator_lock_);
287 
288   // Load the compiler library.
289   static bool LoadCompilerLibrary(std::string* error_msg);
290 
GetThreadPool()291   ThreadPool* GetThreadPool() const {
292     return thread_pool_.get();
293   }
294 
295   // Stop the JIT by waiting for all current compilations and enqueued compilations to finish.
296   void Stop();
297 
298   // Start JIT threads.
299   void Start();
300 
301   // Transition to a child state.
302   void PostForkChildAction(bool is_system_server, bool is_zygote);
303 
304   // Prepare for forking.
305   void PreZygoteFork();
306 
307   // Adjust state after forking.
308   void PostZygoteFork();
309 
310   // Compile methods from the given profile. If `add_to_queue` is true, methods
311   // in the profile are added to the JIT queue. Otherwise they are compiled
312   // directly.
313   void CompileMethodsFromProfile(Thread* self,
314                                  const std::vector<const DexFile*>& dex_files,
315                                  const std::string& profile_path,
316                                  Handle<mirror::ClassLoader> class_loader,
317                                  bool add_to_queue);
318 
319   // Register the dex files to the JIT. This is to perform any compilation/optimization
320   // at the point of loading the dex files.
321   void RegisterDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
322                         ObjPtr<mirror::ClassLoader> class_loader);
323 
324  private:
325   Jit(JitCodeCache* code_cache, JitOptions* options);
326 
327   // Compile the method if the number of samples passes a threshold.
328   // Returns false if we can not compile now - don't increment the counter and retry later.
329   bool MaybeCompileMethod(Thread* self,
330                           ArtMethod* method,
331                           uint32_t old_count,
332                           uint32_t new_count,
333                           bool with_backedges)
334       REQUIRES_SHARED(Locks::mutator_lock_);
335 
336   static bool BindCompilerMethods(std::string* error_msg);
337 
338   // JIT compiler
339   static void* jit_library_handle_;
340   static void* jit_compiler_handle_;
341   static void* (*jit_load_)(void);
342   static void (*jit_unload_)(void*);
343   static bool (*jit_compile_method_)(void*, ArtMethod*, Thread*, bool, bool);
344   static void (*jit_types_loaded_)(void*, mirror::Class**, size_t count);
345   static void (*jit_update_options_)(void*);
346   static bool (*jit_generate_debug_info_)(void*);
347   template <typename T> static bool LoadSymbol(T*, const char* symbol, std::string* error_msg);
348 
349   // JIT resources owned by runtime.
350   jit::JitCodeCache* const code_cache_;
351   const JitOptions* const options_;
352 
353   std::unique_ptr<ThreadPool> thread_pool_;
354   std::vector<std::unique_ptr<OatDexFile>> type_lookup_tables_;
355 
356   // Performance monitoring.
357   CumulativeLogger cumulative_timings_;
358   Histogram<uint64_t> memory_use_ GUARDED_BY(lock_);
359   Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
360 
361   DISALLOW_COPY_AND_ASSIGN(Jit);
362 };
363 
364 // Helper class to stop the JIT for a given scope. This will wait for the JIT to quiesce.
365 class ScopedJitSuspend {
366  public:
367   ScopedJitSuspend();
368   ~ScopedJitSuspend();
369 
370  private:
371   bool was_on_;
372 };
373 
374 }  // namespace jit
375 }  // namespace art
376 
377 #endif  // ART_RUNTIME_JIT_JIT_H_
378