blob: ed0847c9560c52b1a0ba2939cb9896cf848f2e1c [file] [log] [blame]
Nicolas Geoffray5550ca82015-08-21 18:38:30 +01001/*
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"
Nicolas Geoffray095dc462020-08-17 16:40:28 +010023#include "base/value_object.h"
Nicolas Geoffray5550ca82015-08-21 18:38:30 +010024#include "gc_root.h"
Nicolas Geoffray9e598902021-11-19 14:53:07 +000025#include "interpreter/mterp/nterp.h"
Nicolas Geoffraye2a3aa92019-11-25 17:52:58 +000026#include "offsets.h"
Nicolas Geoffray5550ca82015-08-21 18:38:30 +010027
28namespace art {
29
30class ArtMethod;
Nicolas Geoffray73be1e82015-09-17 15:22:56 +010031class ProfilingInfo;
Nicolas Geoffray5550ca82015-08-21 18:38:30 +010032
Nicolas Geoffray26705e22015-10-28 12:50:11 +000033namespace jit {
Nicolas Geoffray095dc462020-08-17 16:40:28 +010034class Jit;
Nicolas Geoffray26705e22015-10-28 12:50:11 +000035class JitCodeCache;
Andreas Gampedeae7db2017-05-30 09:56:41 -070036} // namespace jit
Nicolas Geoffray26705e22015-10-28 12:50:11 +000037
Nicolas Geoffray5550ca82015-08-21 18:38:30 +010038namespace mirror {
39class Class;
Andreas Gampedeae7db2017-05-30 09:56:41 -070040} // namespace mirror
Nicolas Geoffray5550ca82015-08-21 18:38:30 +010041
Nicolas Geoffray73be1e82015-09-17 15:22:56 +010042// 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.
44class InlineCache {
45 public:
Nicolas Geoffraye2a3aa92019-11-25 17:52:58 +000046 // This is hard coded in the assembly stub art_quick_update_inline_cache.
Calin Juravle940eb0c2017-01-30 19:30:44 -080047 static constexpr uint8_t kIndividualCacheSize = 5;
Nicolas Geoffraya42363f2015-12-17 14:57:09 +000048
Nicolas Geoffraye2a3aa92019-11-25 17:52:58 +000049 static constexpr MemberOffset ClassesOffset() {
50 return MemberOffset(OFFSETOF_MEMBER(InlineCache, classes_));
51 }
52
Nicolas Geoffraya42363f2015-12-17 14:57:09 +000053 private:
Nicolas Geoffray73be1e82015-09-17 15:22:56 +010054 uint32_t dex_pc_;
55 GcRoot<mirror::Class> classes_[kIndividualCacheSize];
56
Nicolas Geoffraye51ca8b2016-11-22 14:49:31 +000057 friend class jit::JitCodeCache;
Nicolas Geoffray73be1e82015-09-17 15:22:56 +010058 friend class ProfilingInfo;
59
60 DISALLOW_COPY_AND_ASSIGN(InlineCache);
61};
62
Nicolas Geoffray5550ca82015-08-21 18:38:30 +010063/**
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 */
67class ProfilingInfo {
68 public:
Nicolas Geoffray60ef3992020-08-07 07:49:57 +000069 // Create a ProfilingInfo for 'method'.
70 static ProfilingInfo* Create(Thread* self, ArtMethod* method)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070071 REQUIRES_SHARED(Locks::mutator_lock_);
Nicolas Geoffray5550ca82015-08-21 18:38:30 +010072
73 // Add information from an executed INVOKE instruction to the profile.
Nicolas Geoffray26705e22015-10-28 12:50:11 +000074 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_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070078 REQUIRES_SHARED(Locks::mutator_lock_);
Nicolas Geoffray5550ca82015-08-21 18:38:30 +010079
Nicolas Geoffray26705e22015-10-28 12:50:11 +000080 ArtMethod* GetMethod() const {
81 return method_;
82 }
83
Nicolas Geoffray095dc462020-08-17 16:40:28 +010084 InlineCache* GetInlineCache(uint32_t dex_pc);
Nicolas Geoffray73be1e82015-09-17 15:22:56 +010085
Nicolas Geoffrayf6d46682017-02-28 17:41:45 +000086 // 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.
89 bool IncrementInlineUse() {
90 if (current_inline_uses_ == std::numeric_limits<uint16_t>::max()) {
91 return false;
92 }
Nicolas Geoffrayb6e20ae2016-03-07 14:29:04 +000093 current_inline_uses_++;
Nicolas Geoffrayf6d46682017-02-28 17:41:45 +000094 return true;
Nicolas Geoffrayb6e20ae2016-03-07 14:29:04 +000095 }
96
97 void DecrementInlineUse() {
98 DCHECK_GT(current_inline_uses_, 0);
99 current_inline_uses_--;
100 }
101
102 bool IsInUseByCompiler() const {
Nicolas Geoffrayf8cc26e2020-06-10 15:37:37 +0100103 return current_inline_uses_ > 0;
Nicolas Geoffray511e41b2016-03-02 17:09:35 +0000104 }
105
Nicolas Geoffraya59af8a2019-11-27 17:42:32 +0000106 static constexpr MemberOffset BaselineHotnessCountOffset() {
107 return MemberOffset(OFFSETOF_MEMBER(ProfilingInfo, baseline_hotness_count_));
108 }
109
Nicolas Geoffray9e598902021-11-19 14:53:07 +0000110 void ResetCounter() {
Nicolas Geoffray80f93a82021-12-01 17:53:14 +0000111 baseline_hotness_count_ = GetOptimizeThreshold();
Nicolas Geoffray9e598902021-11-19 14:53:07 +0000112 }
113
114 bool CounterHasChanged() const {
Nicolas Geoffray80f93a82021-12-01 17:53:14 +0000115 return baseline_hotness_count_ != GetOptimizeThreshold();
Nicolas Geoffrayb0a97472019-12-05 15:17:46 +0000116 }
117
118 uint16_t GetBaselineHotnessCount() const {
119 return baseline_hotness_count_;
120 }
121
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100122 private:
Mathieu Chartier65975772016-08-05 10:46:36 -0700123 ProfilingInfo(ArtMethod* method, const std::vector<uint32_t>& entries);
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100124
Nicolas Geoffray80f93a82021-12-01 17:53:14 +0000125 static uint16_t GetOptimizeThreshold();
126
Nicolas Geoffraya59af8a2019-11-27 17:42:32 +0000127 // 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
Nicolas Geoffray26705e22015-10-28 12:50:11 +0000132 // Method this profiling info is for.
Alex Lightdba61482016-12-21 08:20:29 -0800133 // Not 'const' as JVMTI introduces obsolete methods that we implement by creating new ArtMethods.
134 // See JitCodeCache::MoveObsoleteMethod.
135 ArtMethod* method_;
Nicolas Geoffray26705e22015-10-28 12:50:11 +0000136
Andreas Gampee40f65f2018-05-07 17:02:22 -0700137 // 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
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100144 // Dynamically allocated array of size `number_of_inline_caches_`.
145 InlineCache cache_[0];
146
Nicolas Geoffray26705e22015-10-28 12:50:11 +0000147 friend class jit::JitCodeCache;
148
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100149 DISALLOW_COPY_AND_ASSIGN(ProfilingInfo);
150};
151
Nicolas Geoffray095dc462020-08-17 16:40:28 +0100152class ScopedProfilingInfoUse : public ValueObject {
153 public:
154 ScopedProfilingInfoUse(jit::Jit* jit, ArtMethod* method, Thread* self);
155 ~ScopedProfilingInfoUse();
156
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
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100168} // namespace art
169
170#endif // ART_RUNTIME_JIT_PROFILING_INFO_H_