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