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