xref: /aosp_15_r20/art/runtime/jit/jit.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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 <android-base/unique_fd.h>
21 
22 #include <unordered_set>
23 
24 #include "app_info.h"
25 #include "base/histogram-inl.h"
26 #include "base/macros.h"
27 #include "base/mutex.h"
28 #include "base/timing_logger.h"
29 #include "compilation_kind.h"
30 #include "handle.h"
31 #include "interpreter/mterp/nterp.h"
32 #include "jit/debugger_interface.h"
33 #include "jit_options.h"
34 #include "obj_ptr.h"
35 #include "offsets.h"
36 #include "thread_pool.h"
37 
38 namespace art HIDDEN {
39 
40 class ArtMethod;
41 class ClassLinker;
42 class DexFile;
43 class OatDexFile;
44 class RootVisitor;
45 struct RuntimeArgumentMap;
46 union JValue;
47 
48 namespace mirror {
49 class Object;
50 class Class;
51 class ClassLoader;
52 class DexCache;
53 class String;
54 }   // namespace mirror
55 
56 namespace jit {
57 
58 class JitCodeCache;
59 class JitCompileTask;
60 class JitMemoryRegion;
61 class JitOptions;
62 
63 static constexpr int16_t kJitCheckForOSR = -1;
64 static constexpr int16_t kJitHotnessDisabled = -2;
65 
66 // Implemented and provided by the compiler library.
67 class JitCompilerInterface {
68  public:
~JitCompilerInterface()69   virtual ~JitCompilerInterface() {}
70   virtual bool CompileMethod(
71       Thread* self, JitMemoryRegion* region, ArtMethod* method, CompilationKind compilation_kind)
72       REQUIRES_SHARED(Locks::mutator_lock_) = 0;
73   virtual void TypesLoaded(mirror::Class**, size_t count)
74       REQUIRES_SHARED(Locks::mutator_lock_) = 0;
75   virtual bool GenerateDebugInfo() = 0;
76   virtual void ParseCompilerOptions() = 0;
77   virtual bool IsBaselineCompiler() const = 0;
78   virtual void SetDebuggableCompilerOption(bool value) = 0;
79   virtual uint32_t GetInlineMaxCodeUnits() const = 0;
80 
81   virtual std::vector<uint8_t> PackElfFileForJIT(ArrayRef<const JITCodeEntry*> elf_files,
82                                                  ArrayRef<const void*> removed_symbols,
83                                                  bool compress,
84                                                  /*out*/ size_t* num_symbols) = 0;
85 };
86 
87 // Data structure holding information to perform an OSR.
88 struct OsrData {
89   // The native PC to jump to.
90   const uint8_t* native_pc;
91 
92   // The frame size of the compiled code to jump to.
93   size_t frame_size;
94 
95   // The dynamically allocated memory of size `frame_size` to copy to stack.
96   void* memory[0];
97 
NativePcOffsetOsrData98   static constexpr MemberOffset NativePcOffset() {
99     return MemberOffset(OFFSETOF_MEMBER(OsrData, native_pc));
100   }
101 
FrameSizeOffsetOsrData102   static constexpr MemberOffset FrameSizeOffset() {
103     return MemberOffset(OFFSETOF_MEMBER(OsrData, frame_size));
104   }
105 
MemoryOffsetOsrData106   static constexpr MemberOffset MemoryOffset() {
107     return MemberOffset(OFFSETOF_MEMBER(OsrData, memory));
108   }
109 };
110 
111 /**
112  * A customized thread pool for the JIT, to prioritize compilation kinds, and
113  * simplify root visiting.
114  */
115 class JitThreadPool : public AbstractThreadPool {
116  public:
117   static JitThreadPool* Create(const char* name,
118                                size_t num_threads,
119                                size_t worker_stack_size = ThreadPoolWorker::kDefaultStackSize) {
120     JitThreadPool* pool = new JitThreadPool(name, num_threads, worker_stack_size);
121     pool->CreateThreads();
122     return pool;
123   }
124 
125   // Add a task to the generic queue. This is for tasks like
126   // ZygoteVerificationTask, or JitCompileTask for precompile.
127   void AddTask(Thread* self, Task* task) REQUIRES(!task_queue_lock_) override;
128   size_t GetTaskCount(Thread* self) REQUIRES(!task_queue_lock_) override;
129   void RemoveAllTasks(Thread* self) REQUIRES(!task_queue_lock_) override;
130   ~JitThreadPool() override;
131 
132   // Remove the task from the list of compiling tasks.
133   void Remove(JitCompileTask* task) REQUIRES(!task_queue_lock_);
134 
135   // Add a custom compilation task in the right queue.
136   void AddTask(Thread* self, ArtMethod* method, CompilationKind kind) REQUIRES(!task_queue_lock_);
137 
138   // Visit the ArtMethods stored in the various queues.
139   void VisitRoots(RootVisitor* visitor);
140 
141  protected:
142   Task* TryGetTaskLocked() REQUIRES(task_queue_lock_) override;
143 
HasOutstandingTasks()144   bool HasOutstandingTasks() const REQUIRES(task_queue_lock_) override {
145     return started_ &&
146         (!generic_queue_.empty() ||
147          !baseline_queue_.empty() ||
148          !optimized_queue_.empty() ||
149          !osr_queue_.empty());
150   }
151 
152  private:
JitThreadPool(const char * name,size_t num_threads,size_t worker_stack_size)153   JitThreadPool(const char* name,
154                 size_t num_threads,
155                 size_t worker_stack_size)
156       // We need peers as we may report the JIT thread, e.g., in the debugger.
157       : AbstractThreadPool(name, num_threads, /* create_peers= */ true, worker_stack_size) {}
158 
159   // Try to fetch an entry from `methods`. Return null if `methods` is empty.
160   Task* FetchFrom(std::deque<ArtMethod*>& methods, CompilationKind kind) REQUIRES(task_queue_lock_);
161 
162   std::deque<Task*> generic_queue_ GUARDED_BY(task_queue_lock_);
163 
164   std::deque<ArtMethod*> osr_queue_ GUARDED_BY(task_queue_lock_);
165   std::deque<ArtMethod*> baseline_queue_ GUARDED_BY(task_queue_lock_);
166   std::deque<ArtMethod*> optimized_queue_ GUARDED_BY(task_queue_lock_);
167 
168   // We track the methods that are currently enqueued to avoid
169   // adding them to the queue multiple times, which could bloat the
170   // queues.
171   std::set<ArtMethod*> osr_enqueued_methods_ GUARDED_BY(task_queue_lock_);
172   std::set<ArtMethod*> baseline_enqueued_methods_ GUARDED_BY(task_queue_lock_);
173   std::set<ArtMethod*> optimized_enqueued_methods_ GUARDED_BY(task_queue_lock_);
174 
175   // A set to keep track of methods that are currently being compiled. Entries
176   // will be removed when JitCompileTask->Finalize is called.
177   std::unordered_set<JitCompileTask*> current_compilations_ GUARDED_BY(task_queue_lock_);
178 
179   DISALLOW_COPY_AND_ASSIGN(JitThreadPool);
180 };
181 
182 class Jit {
183  public:
184   // How frequently should the interpreter check to see if OSR compilation is ready.
185   static constexpr int16_t kJitRecheckOSRThreshold = 101;  // Prime number to avoid patterns.
186 
187   virtual ~Jit();
188 
189   // Create JIT itself.
190   static std::unique_ptr<Jit> Create(JitCodeCache* code_cache, JitOptions* options);
191 
192   EXPORT bool CompileMethod(ArtMethod* method,
193                             Thread* self,
194                             CompilationKind compilation_kind,
195                             bool prejit) REQUIRES_SHARED(Locks::mutator_lock_);
196 
197   void VisitRoots(RootVisitor* visitor);
198 
GetCodeCache()199   const JitCodeCache* GetCodeCache() const {
200     return code_cache_;
201   }
202 
GetCodeCache()203   JitCodeCache* GetCodeCache() {
204     return code_cache_;
205   }
206 
GetJitCompiler()207   JitCompilerInterface* GetJitCompiler() const {
208     return jit_compiler_;
209   }
210 
211   void CreateThreadPool();
212   void DeleteThreadPool();
213   void WaitForWorkersToBeCreated();
214 
215   // Dump interesting info: #methods compiled, code vs data size, compile / verify cumulative
216   // loggers.
217   void DumpInfo(std::ostream& os) REQUIRES(!lock_);
218   // Add a timing logger to cumulative_timings_.
219   void AddTimingLogger(const TimingLogger& logger);
220 
221   void AddMemoryUsage(ArtMethod* method, size_t bytes)
222       REQUIRES(!lock_)
223       REQUIRES_SHARED(Locks::mutator_lock_);
224 
GetThreadPoolPthreadPriority()225   int GetThreadPoolPthreadPriority() const {
226     return options_->GetThreadPoolPthreadPriority();
227   }
228 
GetZygoteThreadPoolPthreadPriority()229   int GetZygoteThreadPoolPthreadPriority() const {
230     return options_->GetZygoteThreadPoolPthreadPriority();
231   }
232 
HotMethodThreshold()233   uint16_t HotMethodThreshold() const {
234     return options_->GetOptimizeThreshold();
235   }
236 
WarmMethodThreshold()237   uint16_t WarmMethodThreshold() const {
238     return options_->GetWarmupThreshold();
239   }
240 
PriorityThreadWeight()241   uint16_t PriorityThreadWeight() const {
242     return options_->GetPriorityThreadWeight();
243   }
244 
245   // Return whether we should do JIT compilation. Note this will returns false
246   // if we only need to save profile information and not compile methods.
UseJitCompilation()247   bool UseJitCompilation() const {
248     return options_->UseJitCompilation();
249   }
250 
GetSaveProfilingInfo()251   bool GetSaveProfilingInfo() const {
252     return options_->GetSaveProfilingInfo();
253   }
254 
255   // Wait until there is no more pending compilation tasks.
256   EXPORT void WaitForCompilationToFinish(Thread* self);
257 
258   // Profiling methods.
259   void MethodEntered(Thread* thread, ArtMethod* method)
260       REQUIRES_SHARED(Locks::mutator_lock_);
261 
262   ALWAYS_INLINE void AddSamples(Thread* self, ArtMethod* method)
263       REQUIRES_SHARED(Locks::mutator_lock_);
264 
NotifyInterpreterToCompiledCodeTransition(Thread * self,ArtMethod * caller)265   void NotifyInterpreterToCompiledCodeTransition(Thread* self, ArtMethod* caller)
266       REQUIRES_SHARED(Locks::mutator_lock_) {
267     AddSamples(self, caller);
268   }
269 
NotifyCompiledCodeToInterpreterTransition(Thread * self,ArtMethod * callee)270   void NotifyCompiledCodeToInterpreterTransition(Thread* self, ArtMethod* callee)
271       REQUIRES_SHARED(Locks::mutator_lock_) {
272     AddSamples(self, callee);
273   }
274 
275   // Starts the profile saver if the config options allow profile recording.
276   // The profile will be stored in the specified `profile_filename` and will contain
277   // information collected from the given `code_paths` (a set of dex locations).
278   //
279   // The `ref_profile_filename` denotes the path to the reference profile which
280   // might be queried to determine if an initial save should be done earlier.
281   // It can be empty indicating there is no reference profile.
282   void StartProfileSaver(const std::string& profile_filename,
283                          const std::vector<std::string>& code_paths,
284                          const std::string& ref_profile_filename,
285                          AppInfo::CodeType code_type);
286   void StopProfileSaver();
287 
288   void DumpForSigQuit(std::ostream& os) REQUIRES(!lock_);
289 
290   static void NewTypeLoadedIfUsingJit(mirror::Class* type)
291       REQUIRES_SHARED(Locks::mutator_lock_);
292 
293   // If debug info generation is turned on then write the type information for types already loaded
294   // into the specified class linker to the jit debug interface,
295   void DumpTypeInfoForLoadedTypes(ClassLinker* linker);
296 
297   // Return whether we should try to JIT compiled code as soon as an ArtMethod is invoked.
298   EXPORT bool JitAtFirstUse();
299 
300   // Return whether we can invoke JIT code for `method`.
301   bool CanInvokeCompiledCode(ArtMethod* method);
302 
303   // Return the information required to do an OSR jump. Return null if the OSR
304   // cannot be done.
305   OsrData* PrepareForOsr(ArtMethod* method, uint32_t dex_pc, uint32_t* vregs)
306       REQUIRES_SHARED(Locks::mutator_lock_);
307 
308   // If an OSR compiled version is available for `method`,
309   // and `dex_pc + dex_pc_offset` is an entry point of that compiled
310   // version, this method will jump to the compiled code, let it run,
311   // and return true afterwards. Return false otherwise.
312   static bool MaybeDoOnStackReplacement(Thread* thread,
313                                         ArtMethod* method,
314                                         uint32_t dex_pc,
315                                         int32_t dex_pc_offset,
316                                         JValue* result)
317       REQUIRES_SHARED(Locks::mutator_lock_);
318 
GetThreadPool()319   JitThreadPool* GetThreadPool() const {
320     return thread_pool_.get();
321   }
322 
323   // Stop the JIT by waiting for all current compilations and enqueued compilations to finish.
324   EXPORT void Stop();
325 
326   // Start JIT threads.
327   EXPORT void Start();
328 
329   // Transition to a child state.
330   EXPORT void PostForkChildAction(bool is_system_server, bool is_zygote);
331 
332   // Prepare for forking.
333   EXPORT void PreZygoteFork();
334 
335   // Adjust state after forking.
336   void PostZygoteFork();
337 
338   // Add a task to the queue, ensuring it runs after boot is finished.
339   void AddPostBootTask(Thread* self, Task* task);
340 
341   // Called when system finishes booting.
342   void BootCompleted();
343 
344   // Are we in a zygote using JIT compilation?
345   static bool InZygoteUsingJit();
346 
347   // Compile methods from the given profile (.prof extension). If `add_to_queue`
348   // is true, methods in the profile are added to the JIT queue. Otherwise they are compiled
349   // directly.
350   // Return the number of methods added to the queue.
351   uint32_t CompileMethodsFromProfile(Thread* self,
352                                      const std::vector<const DexFile*>& dex_files,
353                                      const std::string& profile_path,
354                                      Handle<mirror::ClassLoader> class_loader,
355                                      bool add_to_queue);
356 
357   // Compile methods from the given boot profile (.bprof extension). If `add_to_queue`
358   // is true, methods in the profile are added to the JIT queue. Otherwise they are compiled
359   // directly.
360   // Return the number of methods added to the queue.
361   uint32_t CompileMethodsFromBootProfile(Thread* self,
362                                          const std::vector<const DexFile*>& dex_files,
363                                          const std::string& profile_path,
364                                          Handle<mirror::ClassLoader> class_loader,
365                                          bool add_to_queue);
366 
367   // Register the dex files to the JIT. This is to perform any compilation/optimization
368   // at the point of loading the dex files.
369   void RegisterDexFiles(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
370                         jobject class_loader);
371 
372   // Called by the compiler to know whether it can directly encode the
373   // method/class/string.
374   bool CanEncodeMethod(ArtMethod* method, bool is_for_shared_region) const
375       REQUIRES_SHARED(Locks::mutator_lock_);
376   bool CanEncodeClass(ObjPtr<mirror::Class> cls, bool is_for_shared_region) const
377       REQUIRES_SHARED(Locks::mutator_lock_);
378   bool CanEncodeString(ObjPtr<mirror::String> string, bool is_for_shared_region) const
379       REQUIRES_SHARED(Locks::mutator_lock_);
380   bool CanAssumeInitialized(ObjPtr<mirror::Class> cls, bool is_for_shared_region) const
381       REQUIRES_SHARED(Locks::mutator_lock_);
382 
383   // Map boot image methods after all compilation in zygote has been done.
384   void MapBootImageMethods() REQUIRES(Locks::mutator_lock_);
385 
386   // Notify to other processes that the zygote is done profile compiling boot
387   // class path methods.
388   void NotifyZygoteCompilationDone();
389 
390   EXPORT void EnqueueOptimizedCompilation(ArtMethod* method, Thread* self);
391 
392   EXPORT void MaybeEnqueueCompilation(ArtMethod* method, Thread* self)
393       REQUIRES_SHARED(Locks::mutator_lock_);
394 
395   EXPORT static bool TryPatternMatch(ArtMethod* method, CompilationKind compilation_kind)
396       REQUIRES_SHARED(Locks::mutator_lock_);
397 
398  private:
399   Jit(JitCodeCache* code_cache, JitOptions* options);
400 
401   // Whether we should not add hotness counts for the given method.
402   bool IgnoreSamplesForMethod(ArtMethod* method)
403       REQUIRES_SHARED(Locks::mutator_lock_);
404 
405   // Compile an individual method listed in a profile. If `add_to_queue` is
406   // true and the method was resolved, return true. Otherwise return false.
407   bool CompileMethodFromProfile(Thread* self,
408                                 ClassLinker* linker,
409                                 uint32_t method_idx,
410                                 Handle<mirror::DexCache> dex_cache,
411                                 Handle<mirror::ClassLoader> class_loader,
412                                 bool add_to_queue,
413                                 bool compile_after_boot)
414       REQUIRES_SHARED(Locks::mutator_lock_);
415 
416   static bool BindCompilerMethods(std::string* error_msg);
417 
418   void AddCompileTask(Thread* self,
419                       ArtMethod* method,
420                       CompilationKind compilation_kind);
421 
422   bool CompileMethodInternal(ArtMethod* method,
423                              Thread* self,
424                              CompilationKind compilation_kind,
425                              bool prejit)
426       REQUIRES_SHARED(Locks::mutator_lock_);
427 
428   // JIT compiler
429   EXPORT static JitCompilerInterface* jit_compiler_;
430 
431   // JIT resources owned by runtime.
432   jit::JitCodeCache* const code_cache_;
433   const JitOptions* const options_;
434 
435   std::unique_ptr<JitThreadPool> thread_pool_;
436   std::vector<std::unique_ptr<OatDexFile>> type_lookup_tables_;
437 
438   Mutex boot_completed_lock_;
439   bool boot_completed_ GUARDED_BY(boot_completed_lock_) = false;
440   std::deque<Task*> tasks_after_boot_ GUARDED_BY(boot_completed_lock_);
441 
442   // Performance monitoring.
443   CumulativeLogger cumulative_timings_;
444   Histogram<uint64_t> memory_use_ GUARDED_BY(lock_);
445   Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
446 
447   // In the JIT zygote configuration, after all compilation is done, the zygote
448   // will copy its contents of the boot image to the zygote_mapping_methods_,
449   // which will be picked up by processes that will map the memory
450   // in-place within the boot image mapping.
451   //
452   // zygote_mapping_methods_ is shared memory only usable by the zygote and not
453   // inherited by child processes. We create it eagerly to ensure other
454   // processes cannot seal writable the file.
455   MemMap zygote_mapping_methods_;
456 
457   // The file descriptor created through memfd_create pointing to memory holding
458   // boot image methods. Created by the zygote, and inherited by child
459   // processes. The descriptor will be closed in each process (including the
460   // zygote) once they don't need it.
461   android::base::unique_fd fd_methods_;
462 
463   // The size of the memory pointed by `fd_methods_`. Cached here to avoid
464   // recomputing it.
465   size_t fd_methods_size_;
466 
467   // Map of hotness counters for methods which we want to share the memory
468   // between the zygote and apps.
469   std::map<ArtMethod*, uint16_t> shared_method_counters_;
470 
471   friend class art::jit::JitCompileTask;
472 
473   DISALLOW_COPY_AND_ASSIGN(Jit);
474 };
475 
476 // Helper class to stop the JIT for a given scope. This will wait for the JIT to quiesce.
477 class EXPORT ScopedJitSuspend {
478  public:
479   ScopedJitSuspend();
480   ~ScopedJitSuspend();
481 
482  private:
483   bool was_on_;
484 };
485 
486 }  // namespace jit
487 }  // namespace art
488 
489 #endif  // ART_RUNTIME_JIT_JIT_H_
490