1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef ECMASCRIPT_IC_PROFILE_TYPE_INFO_H
17 #define ECMASCRIPT_IC_PROFILE_TYPE_INFO_H
18
19 #include "ecmascript/js_function.h"
20 #include "ecmascript/tagged_array.h"
21
22 namespace panda::ecmascript {
23 enum class ICKind : uint32_t {
24 NamedLoadIC,
25 NamedStoreIC,
26 LoadIC,
27 StoreIC,
28 NamedGlobalLoadIC,
29 NamedGlobalStoreIC,
30 NamedGlobalTryLoadIC,
31 NamedGlobalTryStoreIC,
32 GlobalLoadIC,
33 GlobalStoreIC,
34 };
35
IsNamedGlobalIC(ICKind kind)36 static inline bool IsNamedGlobalIC(ICKind kind)
37 {
38 return (kind == ICKind::NamedGlobalLoadIC) || (kind == ICKind::NamedGlobalStoreIC) ||
39 (kind == ICKind::NamedGlobalTryLoadIC) || (kind == ICKind::NamedGlobalTryStoreIC);
40 }
41
IsValueGlobalIC(ICKind kind)42 static inline bool IsValueGlobalIC(ICKind kind)
43 {
44 return (kind == ICKind::GlobalLoadIC) || (kind == ICKind::GlobalStoreIC);
45 }
46
IsValueNormalIC(ICKind kind)47 static inline bool IsValueNormalIC(ICKind kind)
48 {
49 return (kind == ICKind::LoadIC) || (kind == ICKind::StoreIC);
50 }
51
IsValueIC(ICKind kind)52 static inline bool IsValueIC(ICKind kind)
53 {
54 return IsValueNormalIC(kind) || IsValueGlobalIC(kind);
55 }
56
IsNamedNormalIC(ICKind kind)57 static inline bool IsNamedNormalIC(ICKind kind)
58 {
59 return (kind == ICKind::NamedLoadIC) || (kind == ICKind::NamedStoreIC);
60 }
61
IsNamedIC(ICKind kind)62 static inline bool IsNamedIC(ICKind kind)
63 {
64 return IsNamedNormalIC(kind) || IsNamedGlobalIC(kind);
65 }
66
IsGlobalLoadIC(ICKind kind)67 static inline bool IsGlobalLoadIC(ICKind kind)
68 {
69 return (kind == ICKind::NamedGlobalLoadIC) || (kind == ICKind::GlobalLoadIC) ||
70 (kind == ICKind::NamedGlobalTryLoadIC);
71 }
72
IsGlobalStoreIC(ICKind kind)73 static inline bool IsGlobalStoreIC(ICKind kind)
74 {
75 return (kind == ICKind::NamedGlobalStoreIC) || (kind == ICKind::GlobalStoreIC) ||
76 (kind == ICKind::NamedGlobalTryStoreIC);
77 }
78
IsGlobalIC(ICKind kind)79 static inline bool IsGlobalIC(ICKind kind)
80 {
81 return IsValueGlobalIC(kind) || IsNamedGlobalIC(kind);
82 }
83
84 std::string ICKindToString(ICKind kind);
85
86 /* ProfileTypeInfo
87 * +--------------------------------+----
88 * | cache |
89 * | ..... |
90 * +--------------------------------+----
91 * | low 32bits(PeriodCount) |
92 * | hight 32bits(jit hotness) |
93 * +--------------------------------+
94 */
95 class ProfileTypeInfo : public TaggedArray {
96 public:
97 static const uint32_t MAX_FUNC_CACHE_INDEX = std::numeric_limits<uint32_t>::max();
98 static constexpr uint32_t INVALID_SLOT_INDEX = 0xFF;
99 static constexpr uint32_t MAX_SLOT_INDEX = 0xFFFF;
100 static constexpr size_t BIT_FIELD_INDEX = 1;
101 static constexpr size_t RESERVED_LENGTH = BIT_FIELD_INDEX;
102 static constexpr size_t INITIAL_PEROID_INDEX = 0;
103 static constexpr size_t PRE_DUMP_PEROID_INDEX = 1;
104 static constexpr size_t DUMP_PEROID_INDEX = 2;
105 static constexpr size_t JIT_HOTNESS_THRESHOLD_OFFSET_FROM_BITFIELD = 4; // 4 : 4 byte offset from bitfield
106 static constexpr size_t JIT_CNT_OFFSET_FROM_THRESHOLD = 2; // 2 : 2 byte offset from jit hotness threshold
107
Cast(TaggedObject * object)108 static ProfileTypeInfo *Cast(TaggedObject *object)
109 {
110 ASSERT(JSTaggedValue(object).IsTaggedArray());
111 return static_cast<ProfileTypeInfo *>(object);
112 }
113
ComputeSize(uint32_t cacheSize)114 static size_t ComputeSize(uint32_t cacheSize)
115 {
116 return TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), cacheSize + RESERVED_LENGTH);
117 }
118
GetCacheLength()119 inline uint32_t GetCacheLength() const
120 {
121 return GetLength() - RESERVED_LENGTH;
122 }
123
124 inline void InitializeWithSpecialValue(JSTaggedValue initValue, uint32_t capacity, uint32_t extraLength = 0)
125 {
126 ASSERT(initValue.IsSpecial());
127 SetLength(capacity + RESERVED_LENGTH);
128 SetExtraLength(extraLength);
129 for (uint32_t i = 0; i < capacity; i++) {
130 size_t offset = JSTaggedValue::TaggedTypeSize() * i;
131 Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, initValue.GetRawData());
132 }
133 SetPeriodIndex(INITIAL_PEROID_INDEX);
134 }
135
SetPreDumpPeriodIndex()136 void SetPreDumpPeriodIndex()
137 {
138 SetPeriodIndex(PRE_DUMP_PEROID_INDEX);
139 }
140
IsProfileTypeInfoPreDumped()141 bool IsProfileTypeInfoPreDumped() const
142 {
143 return GetPeroidIndex() == PRE_DUMP_PEROID_INDEX;
144 }
145
GetJitHotnessThreshold()146 uint16_t GetJitHotnessThreshold() const
147 {
148 return Barriers::GetValue<uint16_t>(GetData(), GetJitHotnessThresholdBitfieldOffset());
149 }
150
SetJitHotnessThreshold(uint16_t count)151 void SetJitHotnessThreshold(uint16_t count)
152 {
153 Barriers::SetPrimitive(GetData(), GetJitHotnessThresholdBitfieldOffset(), count);
154 }
155
GetJitHotnessCnt()156 uint16_t GetJitHotnessCnt() const
157 {
158 return Barriers::GetValue<uint16_t>(GetData(), GetJitHotnessCntBitfieldOffset());
159 }
160
SetJitHotnessCnt(uint16_t count)161 void SetJitHotnessCnt(uint16_t count)
162 {
163 Barriers::SetPrimitive(GetData(), GetJitHotnessCntBitfieldOffset(), count);
164 }
165
166 DECL_VISIT_ARRAY(DATA_OFFSET, GetCacheLength(), GetCacheLength());
167
DECL_DUMP()168 DECL_DUMP()
169
170 private:
171 uint32_t GetPeroidIndex() const
172 {
173 return Barriers::GetValue<uint32_t>(GetData(), GetBitfieldOffset());
174 }
175
SetPeriodIndex(uint32_t count)176 void SetPeriodIndex(uint32_t count)
177 {
178 Barriers::SetPrimitive(GetData(), GetBitfieldOffset(), count);
179 }
180
GetBitfieldOffset()181 inline size_t GetBitfieldOffset() const
182 {
183 return JSTaggedValue::TaggedTypeSize() * (GetLength() - BIT_FIELD_INDEX);
184 }
185
186 // jit hotness(16bits) + count(16bits)
GetJitHotnessThresholdBitfieldOffset()187 inline size_t GetJitHotnessThresholdBitfieldOffset() const
188 {
189 return GetBitfieldOffset() + JIT_HOTNESS_THRESHOLD_OFFSET_FROM_BITFIELD;
190 }
191
GetJitHotnessCntBitfieldOffset()192 inline size_t GetJitHotnessCntBitfieldOffset() const
193 {
194 return GetJitHotnessThresholdBitfieldOffset() + JIT_CNT_OFFSET_FROM_THRESHOLD;
195 }
196 };
197
198 class ProfileTypeAccessor {
199 public:
200 static constexpr size_t CACHE_MAX_LEN = 8;
201 static constexpr size_t MONO_CASE_NUM = 2;
202 static constexpr size_t POLY_CASE_NUM = 4;
203
204 enum ICState {
205 UNINIT,
206 MONO,
207 POLY,
208 MEGA,
209 };
210
ProfileTypeAccessor(JSThread * thread,JSHandle<ProfileTypeInfo> profileTypeInfo,uint32_t slotId,ICKind kind)211 ProfileTypeAccessor(JSThread* thread, JSHandle<ProfileTypeInfo> profileTypeInfo, uint32_t slotId, ICKind kind)
212 : thread_(thread), profileTypeInfo_(profileTypeInfo), slotId_(slotId), kind_(kind)
213 {
214 }
215 ~ProfileTypeAccessor() = default;
216
217 ICState GetICState() const;
218 static std::string ICStateToString(ICState state);
219 void AddHandlerWithoutKey(JSHandle<JSTaggedValue> hclass, JSHandle<JSTaggedValue> handler) const;
220 void AddElementHandler(JSHandle<JSTaggedValue> hclass, JSHandle<JSTaggedValue> handler) const;
221 void AddHandlerWithKey(JSHandle<JSTaggedValue> key, JSHandle<JSTaggedValue> hclass,
222 JSHandle<JSTaggedValue> handler) const;
223 void AddGlobalHandlerKey(JSHandle<JSTaggedValue> key, JSHandle<JSTaggedValue> handler) const;
224 void AddGlobalRecordHandler(JSHandle<JSTaggedValue> handler) const;
225
GetWeakRef(JSTaggedValue value)226 JSTaggedValue GetWeakRef(JSTaggedValue value) const
227 {
228 return JSTaggedValue(value.CreateAndGetWeakRef());
229 }
230
GetRefFromWeak(const JSTaggedValue & value)231 JSTaggedValue GetRefFromWeak(const JSTaggedValue &value) const
232 {
233 return JSTaggedValue(value.GetWeakReferent());
234 }
235 void SetAsMega() const;
236
GetKind()237 ICKind GetKind() const
238 {
239 return kind_;
240 }
241
242 private:
243 JSThread* thread_;
244 JSHandle<ProfileTypeInfo> profileTypeInfo_;
245 uint32_t slotId_;
246 ICKind kind_;
247 };
248 } // namespace panda::ecmascript
249
250 #endif // ECMASCRIPT_IC_PROFILE_TYPE_INFO_H
251