1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_JIT_PROFILING_INFO_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_JIT_PROFILING_INFO_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <vector> 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 23*795d594fSAndroid Build Coastguard Worker #include "base/value_object.h" 24*795d594fSAndroid Build Coastguard Worker #include "gc_root.h" 25*795d594fSAndroid Build Coastguard Worker #include "interpreter/mterp/nterp.h" 26*795d594fSAndroid Build Coastguard Worker #include "offsets.h" 27*795d594fSAndroid Build Coastguard Worker 28*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN { 29*795d594fSAndroid Build Coastguard Worker 30*795d594fSAndroid Build Coastguard Worker class ArtMethod; 31*795d594fSAndroid Build Coastguard Worker class CompilerOptions; 32*795d594fSAndroid Build Coastguard Worker class ProfilingInfo; 33*795d594fSAndroid Build Coastguard Worker 34*795d594fSAndroid Build Coastguard Worker namespace jit { 35*795d594fSAndroid Build Coastguard Worker class Jit; 36*795d594fSAndroid Build Coastguard Worker class JitCodeCache; 37*795d594fSAndroid Build Coastguard Worker } // namespace jit 38*795d594fSAndroid Build Coastguard Worker 39*795d594fSAndroid Build Coastguard Worker namespace mirror { 40*795d594fSAndroid Build Coastguard Worker class Class; 41*795d594fSAndroid Build Coastguard Worker } // namespace mirror 42*795d594fSAndroid Build Coastguard Worker 43*795d594fSAndroid Build Coastguard Worker // Structure to store the classes seen at runtime for a specific instruction. 44*795d594fSAndroid Build Coastguard Worker // Once the classes_ array is full, we consider the INVOKE to be megamorphic. 45*795d594fSAndroid Build Coastguard Worker class InlineCache { 46*795d594fSAndroid Build Coastguard Worker public: 47*795d594fSAndroid Build Coastguard Worker // This is hard coded in the assembly stub art_quick_update_inline_cache. 48*795d594fSAndroid Build Coastguard Worker static constexpr uint8_t kIndividualCacheSize = 5; 49*795d594fSAndroid Build Coastguard Worker ClassesOffset()50*795d594fSAndroid Build Coastguard Worker static constexpr MemberOffset ClassesOffset() { 51*795d594fSAndroid Build Coastguard Worker return MemberOffset(OFFSETOF_MEMBER(InlineCache, classes_)); 52*795d594fSAndroid Build Coastguard Worker } 53*795d594fSAndroid Build Coastguard Worker 54*795d594fSAndroid Build Coastguard Worker // Encode the list of `dex_pcs` to fit into an uint32_t. 55*795d594fSAndroid Build Coastguard Worker static uint32_t EncodeDexPc(ArtMethod* method, 56*795d594fSAndroid Build Coastguard Worker const std::vector<uint32_t>& dex_pcs, 57*795d594fSAndroid Build Coastguard Worker uint32_t inline_max_code_units) 58*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 59*795d594fSAndroid Build Coastguard Worker 60*795d594fSAndroid Build Coastguard Worker // Return the maximum inlining depth that we support to encode a list of dex 61*795d594fSAndroid Build Coastguard Worker // pcs. 62*795d594fSAndroid Build Coastguard Worker static uint32_t MaxDexPcEncodingDepth(ArtMethod* method, 63*795d594fSAndroid Build Coastguard Worker uint32_t inline_max_code_units) 64*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 65*795d594fSAndroid Build Coastguard Worker 66*795d594fSAndroid Build Coastguard Worker private: 67*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc_; 68*795d594fSAndroid Build Coastguard Worker GcRoot<mirror::Class> classes_[kIndividualCacheSize]; 69*795d594fSAndroid Build Coastguard Worker 70*795d594fSAndroid Build Coastguard Worker friend class jit::JitCodeCache; 71*795d594fSAndroid Build Coastguard Worker friend class ProfilingInfo; 72*795d594fSAndroid Build Coastguard Worker 73*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(InlineCache); 74*795d594fSAndroid Build Coastguard Worker }; 75*795d594fSAndroid Build Coastguard Worker 76*795d594fSAndroid Build Coastguard Worker class BranchCache { 77*795d594fSAndroid Build Coastguard Worker public: FalseOffset()78*795d594fSAndroid Build Coastguard Worker static constexpr MemberOffset FalseOffset() { 79*795d594fSAndroid Build Coastguard Worker return MemberOffset(OFFSETOF_MEMBER(BranchCache, false_)); 80*795d594fSAndroid Build Coastguard Worker } 81*795d594fSAndroid Build Coastguard Worker TrueOffset()82*795d594fSAndroid Build Coastguard Worker static constexpr MemberOffset TrueOffset() { 83*795d594fSAndroid Build Coastguard Worker return MemberOffset(OFFSETOF_MEMBER(BranchCache, true_)); 84*795d594fSAndroid Build Coastguard Worker } 85*795d594fSAndroid Build Coastguard Worker GetExecutionCount()86*795d594fSAndroid Build Coastguard Worker uint32_t GetExecutionCount() const { 87*795d594fSAndroid Build Coastguard Worker return true_ + false_; 88*795d594fSAndroid Build Coastguard Worker } 89*795d594fSAndroid Build Coastguard Worker GetTrue()90*795d594fSAndroid Build Coastguard Worker uint16_t GetTrue() const { 91*795d594fSAndroid Build Coastguard Worker return true_; 92*795d594fSAndroid Build Coastguard Worker } 93*795d594fSAndroid Build Coastguard Worker GetFalse()94*795d594fSAndroid Build Coastguard Worker uint16_t GetFalse() const { 95*795d594fSAndroid Build Coastguard Worker return false_; 96*795d594fSAndroid Build Coastguard Worker } 97*795d594fSAndroid Build Coastguard Worker 98*795d594fSAndroid Build Coastguard Worker private: 99*795d594fSAndroid Build Coastguard Worker uint32_t dex_pc_; 100*795d594fSAndroid Build Coastguard Worker uint16_t false_; 101*795d594fSAndroid Build Coastguard Worker uint16_t true_; 102*795d594fSAndroid Build Coastguard Worker 103*795d594fSAndroid Build Coastguard Worker friend class ProfilingInfo; 104*795d594fSAndroid Build Coastguard Worker 105*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(BranchCache); 106*795d594fSAndroid Build Coastguard Worker }; 107*795d594fSAndroid Build Coastguard Worker 108*795d594fSAndroid Build Coastguard Worker /** 109*795d594fSAndroid Build Coastguard Worker * Profiling info for a method, created and filled by the interpreter once the 110*795d594fSAndroid Build Coastguard Worker * method is warm, and used by the compiler to drive optimizations. 111*795d594fSAndroid Build Coastguard Worker */ 112*795d594fSAndroid Build Coastguard Worker class ProfilingInfo { 113*795d594fSAndroid Build Coastguard Worker public: 114*795d594fSAndroid Build Coastguard Worker // Create a ProfilingInfo for 'method'. 115*795d594fSAndroid Build Coastguard Worker EXPORT static ProfilingInfo* Create(Thread* self, 116*795d594fSAndroid Build Coastguard Worker ArtMethod* method, 117*795d594fSAndroid Build Coastguard Worker const std::vector<uint32_t>& inline_cache_entries) 118*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 119*795d594fSAndroid Build Coastguard Worker 120*795d594fSAndroid Build Coastguard Worker // Add information from an executed INVOKE instruction to the profile. 121*795d594fSAndroid Build Coastguard Worker void AddInvokeInfo(uint32_t dex_pc, mirror::Class* cls) 122*795d594fSAndroid Build Coastguard Worker // Method should not be interruptible, as it manipulates the ProfilingInfo 123*795d594fSAndroid Build Coastguard Worker // which can be concurrently collected. 124*795d594fSAndroid Build Coastguard Worker REQUIRES(Roles::uninterruptible_) 125*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_); 126*795d594fSAndroid Build Coastguard Worker GetMethod()127*795d594fSAndroid Build Coastguard Worker ArtMethod* GetMethod() const { 128*795d594fSAndroid Build Coastguard Worker return method_; 129*795d594fSAndroid Build Coastguard Worker } 130*795d594fSAndroid Build Coastguard Worker 131*795d594fSAndroid Build Coastguard Worker InlineCache* GetInlineCache(uint32_t dex_pc); 132*795d594fSAndroid Build Coastguard Worker BranchCache* GetBranchCache(uint32_t dex_pc); 133*795d594fSAndroid Build Coastguard Worker GetInlineCaches()134*795d594fSAndroid Build Coastguard Worker InlineCache* GetInlineCaches() { 135*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<InlineCache*>( 136*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(this) + sizeof(ProfilingInfo)); 137*795d594fSAndroid Build Coastguard Worker } GetBranchCaches()138*795d594fSAndroid Build Coastguard Worker BranchCache* GetBranchCaches() { 139*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<BranchCache*>( 140*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(this) + sizeof(ProfilingInfo) + 141*795d594fSAndroid Build Coastguard Worker number_of_inline_caches_ * sizeof(InlineCache)); 142*795d594fSAndroid Build Coastguard Worker } 143*795d594fSAndroid Build Coastguard Worker ComputeSize(uint32_t number_of_inline_caches,uint32_t number_of_branch_caches)144*795d594fSAndroid Build Coastguard Worker static size_t ComputeSize(uint32_t number_of_inline_caches, uint32_t number_of_branch_caches) { 145*795d594fSAndroid Build Coastguard Worker return sizeof(ProfilingInfo) + 146*795d594fSAndroid Build Coastguard Worker number_of_inline_caches * sizeof(InlineCache) + 147*795d594fSAndroid Build Coastguard Worker number_of_branch_caches * sizeof(BranchCache); 148*795d594fSAndroid Build Coastguard Worker } 149*795d594fSAndroid Build Coastguard Worker 150*795d594fSAndroid Build Coastguard Worker // Increments the number of times this method is currently being inlined. 151*795d594fSAndroid Build Coastguard Worker // Returns whether it was successful, that is it could increment without 152*795d594fSAndroid Build Coastguard Worker // overflowing. IncrementInlineUse()153*795d594fSAndroid Build Coastguard Worker bool IncrementInlineUse() { 154*795d594fSAndroid Build Coastguard Worker if (current_inline_uses_ == std::numeric_limits<uint16_t>::max()) { 155*795d594fSAndroid Build Coastguard Worker return false; 156*795d594fSAndroid Build Coastguard Worker } 157*795d594fSAndroid Build Coastguard Worker current_inline_uses_++; 158*795d594fSAndroid Build Coastguard Worker return true; 159*795d594fSAndroid Build Coastguard Worker } 160*795d594fSAndroid Build Coastguard Worker DecrementInlineUse()161*795d594fSAndroid Build Coastguard Worker void DecrementInlineUse() { 162*795d594fSAndroid Build Coastguard Worker DCHECK_GT(current_inline_uses_, 0); 163*795d594fSAndroid Build Coastguard Worker current_inline_uses_--; 164*795d594fSAndroid Build Coastguard Worker } 165*795d594fSAndroid Build Coastguard Worker IsInUseByCompiler()166*795d594fSAndroid Build Coastguard Worker bool IsInUseByCompiler() const { 167*795d594fSAndroid Build Coastguard Worker return current_inline_uses_ > 0; 168*795d594fSAndroid Build Coastguard Worker } 169*795d594fSAndroid Build Coastguard Worker BaselineHotnessCountOffset()170*795d594fSAndroid Build Coastguard Worker static constexpr MemberOffset BaselineHotnessCountOffset() { 171*795d594fSAndroid Build Coastguard Worker return MemberOffset(OFFSETOF_MEMBER(ProfilingInfo, baseline_hotness_count_)); 172*795d594fSAndroid Build Coastguard Worker } 173*795d594fSAndroid Build Coastguard Worker GetBaselineHotnessCount()174*795d594fSAndroid Build Coastguard Worker uint16_t GetBaselineHotnessCount() const { 175*795d594fSAndroid Build Coastguard Worker return baseline_hotness_count_; 176*795d594fSAndroid Build Coastguard Worker } 177*795d594fSAndroid Build Coastguard Worker 178*795d594fSAndroid Build Coastguard Worker static uint16_t GetOptimizeThreshold(); 179*795d594fSAndroid Build Coastguard Worker 180*795d594fSAndroid Build Coastguard Worker private: 181*795d594fSAndroid Build Coastguard Worker ProfilingInfo(ArtMethod* method, 182*795d594fSAndroid Build Coastguard Worker const std::vector<uint32_t>& inline_cache_entries, 183*795d594fSAndroid Build Coastguard Worker const std::vector<uint32_t>& branch_cache_entries); 184*795d594fSAndroid Build Coastguard Worker 185*795d594fSAndroid Build Coastguard Worker // Hotness count for methods compiled with the JIT baseline compiler. Once 186*795d594fSAndroid Build Coastguard Worker // a threshold is hit (currentily the maximum value of uint16_t), we will 187*795d594fSAndroid Build Coastguard Worker // JIT compile optimized the method. 188*795d594fSAndroid Build Coastguard Worker uint16_t baseline_hotness_count_; 189*795d594fSAndroid Build Coastguard Worker 190*795d594fSAndroid Build Coastguard Worker // Method this profiling info is for. 191*795d594fSAndroid Build Coastguard Worker // Not 'const' as JVMTI introduces obsolete methods that we implement by creating new ArtMethods. 192*795d594fSAndroid Build Coastguard Worker // See JitCodeCache::MoveObsoleteMethod. 193*795d594fSAndroid Build Coastguard Worker ArtMethod* method_; 194*795d594fSAndroid Build Coastguard Worker 195*795d594fSAndroid Build Coastguard Worker // Number of invokes we are profiling in the ArtMethod. 196*795d594fSAndroid Build Coastguard Worker const uint32_t number_of_inline_caches_; 197*795d594fSAndroid Build Coastguard Worker 198*795d594fSAndroid Build Coastguard Worker // Number of branches we are profiling in the ArtMethod. 199*795d594fSAndroid Build Coastguard Worker const uint32_t number_of_branch_caches_; 200*795d594fSAndroid Build Coastguard Worker 201*795d594fSAndroid Build Coastguard Worker // When the compiler inlines the method associated to this ProfilingInfo, 202*795d594fSAndroid Build Coastguard Worker // it updates this counter so that the GC does not try to clear the inline caches. 203*795d594fSAndroid Build Coastguard Worker uint16_t current_inline_uses_; 204*795d594fSAndroid Build Coastguard Worker 205*795d594fSAndroid Build Coastguard Worker // Memory following the object: 206*795d594fSAndroid Build Coastguard Worker // - Dynamically allocated array of `InlineCache` of size `number_of_inline_caches_`. 207*795d594fSAndroid Build Coastguard Worker // - Dynamically allocated array of `BranchCache of size `number_of_branch_caches_`. 208*795d594fSAndroid Build Coastguard Worker friend class jit::JitCodeCache; 209*795d594fSAndroid Build Coastguard Worker 210*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ProfilingInfo); 211*795d594fSAndroid Build Coastguard Worker }; 212*795d594fSAndroid Build Coastguard Worker 213*795d594fSAndroid Build Coastguard Worker class ScopedProfilingInfoUse : public ValueObject { 214*795d594fSAndroid Build Coastguard Worker public: 215*795d594fSAndroid Build Coastguard Worker ScopedProfilingInfoUse(jit::Jit* jit, ArtMethod* method, Thread* self); 216*795d594fSAndroid Build Coastguard Worker ~ScopedProfilingInfoUse(); 217*795d594fSAndroid Build Coastguard Worker GetProfilingInfo()218*795d594fSAndroid Build Coastguard Worker ProfilingInfo* GetProfilingInfo() const { return profiling_info_; } 219*795d594fSAndroid Build Coastguard Worker 220*795d594fSAndroid Build Coastguard Worker private: 221*795d594fSAndroid Build Coastguard Worker jit::Jit* const jit_; 222*795d594fSAndroid Build Coastguard Worker ArtMethod* const method_; 223*795d594fSAndroid Build Coastguard Worker Thread* const self_; 224*795d594fSAndroid Build Coastguard Worker ProfilingInfo* const profiling_info_; 225*795d594fSAndroid Build Coastguard Worker 226*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ScopedProfilingInfoUse); 227*795d594fSAndroid Build Coastguard Worker }; 228*795d594fSAndroid Build Coastguard Worker 229*795d594fSAndroid Build Coastguard Worker } // namespace art 230*795d594fSAndroid Build Coastguard Worker 231*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_JIT_PROFILING_INFO_H_ 232