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/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 "thread_pool.h"
     27 
     28 namespace art {
     29 
     30 class ArtMethod;
     31 class ClassLinker;
     32 struct RuntimeArgumentMap;
     33 union JValue;
     34 
     35 namespace mirror {
     36 class Object;
     37 class Class;
     38 }   // namespace mirror
     39 
     40 namespace jit {
     41 
     42 class JitCodeCache;
     43 class JitOptions;
     44 
     45 static constexpr int16_t kJitCheckForOSR = -1;
     46 static constexpr int16_t kJitHotnessDisabled = -2;
     47 
     48 class Jit {
     49  public:
     50   static constexpr size_t kDefaultPriorityThreadWeightRatio = 1000;
     51   static constexpr size_t kDefaultInvokeTransitionWeightRatio = 500;
     52   // How frequently should the interpreter check to see if OSR compilation is ready.
     53   static constexpr int16_t kJitRecheckOSRThreshold = 100;
     54 
     55   virtual ~Jit();
     56   static Jit* Create(JitOptions* options, std::string* error_msg);
     57   bool CompileMethod(ArtMethod* method, Thread* self, bool osr)
     58       REQUIRES_SHARED(Locks::mutator_lock_);
     59   void CreateThreadPool();
     60 
     61   const JitCodeCache* GetCodeCache() const {
     62     return code_cache_.get();
     63   }
     64 
     65   JitCodeCache* GetCodeCache() {
     66     return code_cache_.get();
     67   }
     68 
     69   void DeleteThreadPool();
     70   // Dump interesting info: #methods compiled, code vs data size, compile / verify cumulative
     71   // loggers.
     72   void DumpInfo(std::ostream& os) REQUIRES(!lock_);
     73   // Add a timing logger to cumulative_timings_.
     74   void AddTimingLogger(const TimingLogger& logger);
     75 
     76   void AddMemoryUsage(ArtMethod* method, size_t bytes)
     77       REQUIRES(!lock_)
     78       REQUIRES_SHARED(Locks::mutator_lock_);
     79 
     80   size_t OSRMethodThreshold() const {
     81     return osr_method_threshold_;
     82   }
     83 
     84   size_t HotMethodThreshold() const {
     85     return hot_method_threshold_;
     86   }
     87 
     88   size_t WarmMethodThreshold() const {
     89     return warm_method_threshold_;
     90   }
     91 
     92   uint16_t PriorityThreadWeight() const {
     93     return priority_thread_weight_;
     94   }
     95 
     96   // Returns false if we only need to save profile information and not compile methods.
     97   bool UseJitCompilation() const {
     98     return use_jit_compilation_;
     99   }
    100 
    101   bool GetSaveProfilingInfo() const {
    102     return profile_saver_options_.IsEnabled();
    103   }
    104 
    105   // Wait until there is no more pending compilation tasks.
    106   void WaitForCompilationToFinish(Thread* self);
    107 
    108   // Profiling methods.
    109   void MethodEntered(Thread* thread, ArtMethod* method)
    110       REQUIRES_SHARED(Locks::mutator_lock_);
    111 
    112   void AddSamples(Thread* self, ArtMethod* method, uint16_t samples, bool with_backedges)
    113       REQUIRES_SHARED(Locks::mutator_lock_);
    114 
    115   void InvokeVirtualOrInterface(ObjPtr<mirror::Object> this_object,
    116                                 ArtMethod* caller,
    117                                 uint32_t dex_pc,
    118                                 ArtMethod* callee)
    119       REQUIRES_SHARED(Locks::mutator_lock_);
    120 
    121   void NotifyInterpreterToCompiledCodeTransition(Thread* self, ArtMethod* caller)
    122       REQUIRES_SHARED(Locks::mutator_lock_) {
    123     AddSamples(self, caller, invoke_transition_weight_, false);
    124   }
    125 
    126   void NotifyCompiledCodeToInterpreterTransition(Thread* self, ArtMethod* callee)
    127       REQUIRES_SHARED(Locks::mutator_lock_) {
    128     AddSamples(self, callee, invoke_transition_weight_, false);
    129   }
    130 
    131   // Starts the profile saver if the config options allow profile recording.
    132   // The profile will be stored in the specified `filename` and will contain
    133   // information collected from the given `code_paths` (a set of dex locations).
    134   void StartProfileSaver(const std::string& filename,
    135                          const std::vector<std::string>& code_paths);
    136   void StopProfileSaver();
    137 
    138   void DumpForSigQuit(std::ostream& os) REQUIRES(!lock_);
    139 
    140   static void NewTypeLoadedIfUsingJit(mirror::Class* type)
    141       REQUIRES_SHARED(Locks::mutator_lock_);
    142 
    143   // If debug info generation is turned on then write the type information for types already loaded
    144   // into the specified class linker to the jit debug interface,
    145   void DumpTypeInfoForLoadedTypes(ClassLinker* linker);
    146 
    147   // Return whether we should try to JIT compiled code as soon as an ArtMethod is invoked.
    148   bool JitAtFirstUse();
    149 
    150   // Return whether we can invoke JIT code for `method`.
    151   bool CanInvokeCompiledCode(ArtMethod* method);
    152 
    153   // Return whether the runtime should use a priority thread weight when sampling.
    154   static bool ShouldUsePriorityThreadWeight(Thread* self);
    155 
    156   // If an OSR compiled version is available for `method`,
    157   // and `dex_pc + dex_pc_offset` is an entry point of that compiled
    158   // version, this method will jump to the compiled code, let it run,
    159   // and return true afterwards. Return false otherwise.
    160   static bool MaybeDoOnStackReplacement(Thread* thread,
    161                                         ArtMethod* method,
    162                                         uint32_t dex_pc,
    163                                         int32_t dex_pc_offset,
    164                                         JValue* result)
    165       REQUIRES_SHARED(Locks::mutator_lock_);
    166 
    167   static bool LoadCompilerLibrary(std::string* error_msg);
    168 
    169   ThreadPool* GetThreadPool() const {
    170     return thread_pool_.get();
    171   }
    172 
    173   // Stop the JIT by waiting for all current compilations and enqueued compilations to finish.
    174   void Stop();
    175 
    176   // Start JIT threads.
    177   void Start();
    178 
    179  private:
    180   Jit();
    181 
    182   static bool LoadCompiler(std::string* error_msg);
    183 
    184   // JIT compiler
    185   static void* jit_library_handle_;
    186   static void* jit_compiler_handle_;
    187   static void* (*jit_load_)(bool*);
    188   static void (*jit_unload_)(void*);
    189   static bool (*jit_compile_method_)(void*, ArtMethod*, Thread*, bool);
    190   static void (*jit_types_loaded_)(void*, mirror::Class**, size_t count);
    191 
    192   // Performance monitoring.
    193   bool dump_info_on_shutdown_;
    194   CumulativeLogger cumulative_timings_;
    195   Histogram<uint64_t> memory_use_ GUARDED_BY(lock_);
    196   Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
    197 
    198   std::unique_ptr<jit::JitCodeCache> code_cache_;
    199 
    200   bool use_jit_compilation_;
    201   ProfileSaverOptions profile_saver_options_;
    202   static bool generate_debug_info_;
    203   uint16_t hot_method_threshold_;
    204   uint16_t warm_method_threshold_;
    205   uint16_t osr_method_threshold_;
    206   uint16_t priority_thread_weight_;
    207   uint16_t invoke_transition_weight_;
    208   std::unique_ptr<ThreadPool> thread_pool_;
    209 
    210   DISALLOW_COPY_AND_ASSIGN(Jit);
    211 };
    212 
    213 class JitOptions {
    214  public:
    215   static JitOptions* CreateFromRuntimeArguments(const RuntimeArgumentMap& options);
    216   size_t GetCompileThreshold() const {
    217     return compile_threshold_;
    218   }
    219   size_t GetWarmupThreshold() const {
    220     return warmup_threshold_;
    221   }
    222   size_t GetOsrThreshold() const {
    223     return osr_threshold_;
    224   }
    225   uint16_t GetPriorityThreadWeight() const {
    226     return priority_thread_weight_;
    227   }
    228   size_t GetInvokeTransitionWeight() const {
    229     return invoke_transition_weight_;
    230   }
    231   size_t GetCodeCacheInitialCapacity() const {
    232     return code_cache_initial_capacity_;
    233   }
    234   size_t GetCodeCacheMaxCapacity() const {
    235     return code_cache_max_capacity_;
    236   }
    237   bool DumpJitInfoOnShutdown() const {
    238     return dump_info_on_shutdown_;
    239   }
    240   const ProfileSaverOptions& GetProfileSaverOptions() const {
    241     return profile_saver_options_;
    242   }
    243   bool GetSaveProfilingInfo() const {
    244     return profile_saver_options_.IsEnabled();
    245   }
    246   bool UseJitCompilation() const {
    247     return use_jit_compilation_;
    248   }
    249   void SetUseJitCompilation(bool b) {
    250     use_jit_compilation_ = b;
    251   }
    252   void SetSaveProfilingInfo(bool save_profiling_info) {
    253     profile_saver_options_.SetEnabled(save_profiling_info);
    254   }
    255   void SetWaitForJitNotificationsToSaveProfile(bool value) {
    256     profile_saver_options_.SetWaitForJitNotificationsToSave(value);
    257   }
    258   void SetProfileAOTCode(bool value) {
    259     profile_saver_options_.SetProfileAOTCode(value);
    260   }
    261 
    262   void SetJitAtFirstUse() {
    263     use_jit_compilation_ = true;
    264     compile_threshold_ = 0;
    265   }
    266 
    267  private:
    268   bool use_jit_compilation_;
    269   size_t code_cache_initial_capacity_;
    270   size_t code_cache_max_capacity_;
    271   size_t compile_threshold_;
    272   size_t warmup_threshold_;
    273   size_t osr_threshold_;
    274   uint16_t priority_thread_weight_;
    275   size_t invoke_transition_weight_;
    276   bool dump_info_on_shutdown_;
    277   ProfileSaverOptions profile_saver_options_;
    278 
    279   JitOptions()
    280       : use_jit_compilation_(false),
    281         code_cache_initial_capacity_(0),
    282         code_cache_max_capacity_(0),
    283         compile_threshold_(0),
    284         warmup_threshold_(0),
    285         osr_threshold_(0),
    286         priority_thread_weight_(0),
    287         invoke_transition_weight_(0),
    288         dump_info_on_shutdown_(false) {}
    289 
    290   DISALLOW_COPY_AND_ASSIGN(JitOptions);
    291 };
    292 
    293 // Helper class to stop the JIT for a given scope. This will wait for the JIT to quiesce.
    294 class ScopedJitSuspend {
    295  public:
    296   ScopedJitSuspend();
    297   ~ScopedJitSuspend();
    298 
    299  private:
    300   bool was_on_;
    301 };
    302 
    303 }  // namespace jit
    304 }  // namespace art
    305 
    306 #endif  // ART_RUNTIME_JIT_JIT_H_
    307