xref: /aosp_15_r20/art/runtime/jit/profiling_info.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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