• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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_PROFILING_INFO_H_
18 #define ART_RUNTIME_JIT_PROFILING_INFO_H_
19 
20 #include <vector>
21 
22 #include "base/macros.h"
23 #include "base/value_object.h"
24 #include "gc_root.h"
25 #include "interpreter/mterp/nterp.h"
26 #include "offsets.h"
27 
28 namespace art {
29 
30 class ArtMethod;
31 class ProfilingInfo;
32 
33 namespace jit {
34 class Jit;
35 class JitCodeCache;
36 }  // namespace jit
37 
38 namespace mirror {
39 class Class;
40 }  // namespace mirror
41 
42 // Structure to store the classes seen at runtime for a specific instruction.
43 // Once the classes_ array is full, we consider the INVOKE to be megamorphic.
44 class InlineCache {
45  public:
46   // This is hard coded in the assembly stub art_quick_update_inline_cache.
47   static constexpr uint8_t kIndividualCacheSize = 5;
48 
ClassesOffset()49   static constexpr MemberOffset ClassesOffset() {
50     return MemberOffset(OFFSETOF_MEMBER(InlineCache, classes_));
51   }
52 
53  private:
54   uint32_t dex_pc_;
55   GcRoot<mirror::Class> classes_[kIndividualCacheSize];
56 
57   friend class jit::JitCodeCache;
58   friend class ProfilingInfo;
59 
60   DISALLOW_COPY_AND_ASSIGN(InlineCache);
61 };
62 
63 /**
64  * Profiling info for a method, created and filled by the interpreter once the
65  * method is warm, and used by the compiler to drive optimizations.
66  */
67 class ProfilingInfo {
68  public:
69   // Create a ProfilingInfo for 'method'.
70   static ProfilingInfo* Create(Thread* self, ArtMethod* method)
71       REQUIRES_SHARED(Locks::mutator_lock_);
72 
73   // Add information from an executed INVOKE instruction to the profile.
74   void AddInvokeInfo(uint32_t dex_pc, mirror::Class* cls)
75       // Method should not be interruptible, as it manipulates the ProfilingInfo
76       // which can be concurrently collected.
77       REQUIRES(Roles::uninterruptible_)
78       REQUIRES_SHARED(Locks::mutator_lock_);
79 
GetMethod()80   ArtMethod* GetMethod() const {
81     return method_;
82   }
83 
84   InlineCache* GetInlineCache(uint32_t dex_pc);
85 
86   // Increments the number of times this method is currently being inlined.
87   // Returns whether it was successful, that is it could increment without
88   // overflowing.
IncrementInlineUse()89   bool IncrementInlineUse() {
90     if (current_inline_uses_ == std::numeric_limits<uint16_t>::max()) {
91       return false;
92     }
93     current_inline_uses_++;
94     return true;
95   }
96 
DecrementInlineUse()97   void DecrementInlineUse() {
98     DCHECK_GT(current_inline_uses_, 0);
99     current_inline_uses_--;
100   }
101 
IsInUseByCompiler()102   bool IsInUseByCompiler() const {
103     return current_inline_uses_ > 0;
104   }
105 
BaselineHotnessCountOffset()106   static constexpr MemberOffset BaselineHotnessCountOffset() {
107     return MemberOffset(OFFSETOF_MEMBER(ProfilingInfo, baseline_hotness_count_));
108   }
109 
ResetCounter()110   void ResetCounter() {
111     baseline_hotness_count_ = GetOptimizeThreshold();
112   }
113 
CounterHasChanged()114   bool CounterHasChanged() const {
115     return baseline_hotness_count_ != GetOptimizeThreshold();
116   }
117 
GetBaselineHotnessCount()118   uint16_t GetBaselineHotnessCount() const {
119     return baseline_hotness_count_;
120   }
121 
122  private:
123   ProfilingInfo(ArtMethod* method, const std::vector<uint32_t>& entries);
124 
125   static uint16_t GetOptimizeThreshold();
126 
127   // Hotness count for methods compiled with the JIT baseline compiler. Once
128   // a threshold is hit (currentily the maximum value of uint16_t), we will
129   // JIT compile optimized the method.
130   uint16_t baseline_hotness_count_;
131 
132   // Method this profiling info is for.
133   // Not 'const' as JVMTI introduces obsolete methods that we implement by creating new ArtMethods.
134   // See JitCodeCache::MoveObsoleteMethod.
135   ArtMethod* method_;
136 
137   // Number of instructions we are profiling in the ArtMethod.
138   const uint32_t number_of_inline_caches_;
139 
140   // When the compiler inlines the method associated to this ProfilingInfo,
141   // it updates this counter so that the GC does not try to clear the inline caches.
142   uint16_t current_inline_uses_;
143 
144   // Dynamically allocated array of size `number_of_inline_caches_`.
145   InlineCache cache_[0];
146 
147   friend class jit::JitCodeCache;
148 
149   DISALLOW_COPY_AND_ASSIGN(ProfilingInfo);
150 };
151 
152 class ScopedProfilingInfoUse : public ValueObject {
153  public:
154   ScopedProfilingInfoUse(jit::Jit* jit, ArtMethod* method, Thread* self);
155   ~ScopedProfilingInfoUse();
156 
GetProfilingInfo()157   ProfilingInfo* GetProfilingInfo() const { return profiling_info_; }
158 
159  private:
160   jit::Jit* const jit_;
161   ArtMethod* const method_;
162   Thread* const self_;
163   ProfilingInfo* const profiling_info_;
164 
165   DISALLOW_COPY_AND_ASSIGN(ScopedProfilingInfoUse);
166 };
167 
168 }  // namespace art
169 
170 #endif  // ART_RUNTIME_JIT_PROFILING_INFO_H_
171