• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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