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