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