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/ic/mega_ic_cache.h"
20 #include "ecmascript/js_function.h"
21 #include "ecmascript/js_tagged_value.h"
22 #include "ecmascript/tagged_array.h"
23 #include "ecmascript/tagged_dictionary.h"
24
25 namespace panda::ecmascript {
26 enum class ICKind : uint32_t {
27 NamedLoadIC,
28 NamedStoreIC,
29 LoadIC,
30 StoreIC,
31 NamedGlobalLoadIC,
32 NamedGlobalStoreIC,
33 NamedGlobalTryLoadIC,
34 NamedGlobalTryStoreIC,
35 GlobalLoadIC,
36 GlobalStoreIC,
37 };
38
IsNamedGlobalIC(ICKind kind)39 static inline bool IsNamedGlobalIC(ICKind kind)
40 {
41 return (kind == ICKind::NamedGlobalLoadIC) || (kind == ICKind::NamedGlobalStoreIC) ||
42 (kind == ICKind::NamedGlobalTryLoadIC) || (kind == ICKind::NamedGlobalTryStoreIC);
43 }
44
IsValueGlobalIC(ICKind kind)45 static inline bool IsValueGlobalIC(ICKind kind)
46 {
47 return (kind == ICKind::GlobalLoadIC) || (kind == ICKind::GlobalStoreIC);
48 }
49
IsValueNormalIC(ICKind kind)50 static inline bool IsValueNormalIC(ICKind kind)
51 {
52 return (kind == ICKind::LoadIC) || (kind == ICKind::StoreIC);
53 }
54
IsValueIC(ICKind kind)55 static inline bool IsValueIC(ICKind kind)
56 {
57 return IsValueNormalIC(kind) || IsValueGlobalIC(kind);
58 }
59
IsNamedNormalIC(ICKind kind)60 static inline bool IsNamedNormalIC(ICKind kind)
61 {
62 return (kind == ICKind::NamedLoadIC) || (kind == ICKind::NamedStoreIC);
63 }
64
IsNamedIC(ICKind kind)65 static inline bool IsNamedIC(ICKind kind)
66 {
67 return IsNamedNormalIC(kind) || IsNamedGlobalIC(kind);
68 }
69
IsGlobalLoadIC(ICKind kind)70 static inline bool IsGlobalLoadIC(ICKind kind)
71 {
72 return (kind == ICKind::NamedGlobalLoadIC) || (kind == ICKind::GlobalLoadIC) ||
73 (kind == ICKind::NamedGlobalTryLoadIC);
74 }
75
IsGlobalStoreIC(ICKind kind)76 static inline bool IsGlobalStoreIC(ICKind kind)
77 {
78 return (kind == ICKind::NamedGlobalStoreIC) || (kind == ICKind::GlobalStoreIC) ||
79 (kind == ICKind::NamedGlobalTryStoreIC);
80 }
81
IsGlobalIC(ICKind kind)82 static inline bool IsGlobalIC(ICKind kind)
83 {
84 return IsValueGlobalIC(kind) || IsNamedGlobalIC(kind);
85 }
86
87 std::string ICKindToString(ICKind kind);
88
89 class ProfileTypeAccessorLockScope {
90 public:
ProfileTypeAccessorLockScope(JSThread * thread)91 ProfileTypeAccessorLockScope(JSThread *thread)
92 {
93 if (thread->GetEcmaVM()->IsEnableFastJit() || thread->GetEcmaVM()->IsEnableBaselineJit()) {
94 lockHolder_.emplace(thread->GetProfileTypeAccessorLock());
95 }
96 }
97
98 private:
99 std::optional<LockHolder> lockHolder_;
100 };
101
102 /**
103 * ProfileTypeInfo
104 * +--------------------------------+
105 * | ic slot |
106 * | ..... |
107 * +--------------------------------+
108 * | 64 bits jit osr |
109 * | tagged array address |
110 * +--------------------------------+
111 * | low 32 bits(PeriodCount) |
112 * | hight 32 bits(jit hotness) |
113 * +--------------------------------+
114 * | low 32 bits(osr hotness) |
115 * | hight 32 bits(baseline hotness)|
116 * +--------------------------------+
117 */
118 class ProfileTypeInfo : public TaggedArray {
119 public:
120 static const uint32_t MAX_FUNC_CACHE_INDEX = std::numeric_limits<uint32_t>::max();
121 static constexpr uint32_t INVALID_SLOT_INDEX = 0xFF;
122 static constexpr uint32_t MAX_SLOT_INDEX = 0xFFFF;
123 static constexpr size_t BIT_FIELD_INDEX = 2;
124 static constexpr size_t JIT_OSR_INDEX = 3;
125 static constexpr size_t EXTRA_INFO_MAP_INDEX = 4;
126 static constexpr size_t RESERVED_LENGTH = EXTRA_INFO_MAP_INDEX;
127 static constexpr size_t INITIAL_PERIOD_INDEX = 0;
128 static constexpr size_t PRE_DUMP_PERIOD_INDEX = 1;
129 static constexpr size_t DUMP_PERIOD_INDEX = 2;
130 static constexpr size_t BIG_METHOD_PERIOD_INDEX = 3;
131 static constexpr size_t INITIAL_OSR_HOTNESS_THRESHOLD = 0;
132 static constexpr size_t INITIAL_OSR_HOTNESS_CNT = 0;
133 static constexpr size_t INITIAL_JIT_CALL_THRESHOLD = 0;
134 static constexpr size_t INITIAL_JIT_CALL_CNT = 0;
135 static constexpr uint16_t JIT_DISABLE_FLAG = 0xFFFF;
136 static constexpr size_t JIT_HOTNESS_THRESHOLD_OFFSET_FROM_BITFIELD = 4; // 4 : 4 byte offset from bitfield
137 static constexpr size_t JIT_CNT_OFFSET_FROM_THRESHOLD = 2; // 2 : 2 byte offset from jit hotness threshold
138 static constexpr size_t OSR_HOTNESS_THRESHOLD_OFFSET_FROM_BITFIELD = 8; // 8 : 8 byte offset from bitfield
139 static constexpr size_t OSR_CNT_OFFSET_FROM_OSR_THRESHOLD = 2; // 2 : 2 byte offset from osr hotness threshold
140 static constexpr size_t BASELINEJIT_HOTNESS_THRESHOLD_OFFSET_FROM_BITFIELD = 12; // 12: bytes offset from bitfield
141 static constexpr size_t JIT_CALL_CNT_OFFSET_FROM_BITFIELD = 14; // 14 : 14 byte offset from bitfield
142
Cast(TaggedObject * object)143 static ProfileTypeInfo *Cast(TaggedObject *object)
144 {
145 ASSERT(JSTaggedValue(object).IsTaggedArray());
146 return static_cast<ProfileTypeInfo *>(object);
147 }
148
ComputeSize(uint32_t icSlotSize)149 static size_t ComputeSize(uint32_t icSlotSize)
150 {
151 return TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), AdjustSlotSize(icSlotSize) + RESERVED_LENGTH);
152 }
153
GetIcSlotLength()154 inline uint32_t GetIcSlotLength() const
155 {
156 return GetLength() - RESERVED_LENGTH;
157 }
158
GetIcSlotToOsrLength()159 inline uint32_t GetIcSlotToOsrLength() const
160 {
161 return GetLength() - BIT_FIELD_INDEX;
162 }
163
AdjustSlotSize(uint32_t icSlotSize)164 static inline uint32_t AdjustSlotSize(uint32_t icSlotSize)
165 {
166 // if ic slot size is 0xff comes from frontend, it means the actual size is 0x100.
167 // 0xff is a invalid slot index, which value is hole.
168 if (icSlotSize == INVALID_SLOT_INDEX) {
169 ++icSlotSize;
170 }
171 return icSlotSize;
172 }
173
SetPrimitiveOfSlot(JSTaggedValue initValue,uint32_t icSlotSize)174 inline void SetPrimitiveOfSlot(JSTaggedValue initValue, uint32_t icSlotSize)
175 {
176 for (uint32_t i = 0; i < icSlotSize; i++) {
177 size_t offset = JSTaggedValue::TaggedTypeSize() * i;
178 if (i == INVALID_SLOT_INDEX) {
179 Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, JSTaggedValue::Hole().GetRawData());
180 } else {
181 Barriers::SetPrimitive<JSTaggedType>(GetData(), offset, initValue.GetRawData());
182 }
183 }
184 }
185
SetSpecialValue()186 inline void SetSpecialValue()
187 {
188 SetPeriodIndex(INITIAL_PERIOD_INDEX);
189 SetJitHotnessThreshold(JIT_DISABLE_FLAG);
190 SetJitHotnessCnt(0);
191 SetBaselineJitHotnessThreshold(JIT_DISABLE_FLAG);
192 SetOsrHotnessThreshold(INITIAL_OSR_HOTNESS_THRESHOLD);
193 SetOsrHotnessCnt(INITIAL_OSR_HOTNESS_CNT);
194 SetJitCallThreshold(INITIAL_JIT_CALL_THRESHOLD);
195 }
196
InitializeExtraInfoMap()197 inline void InitializeExtraInfoMap()
198 {
199 // the last-1 of the cache is used to save extra info map
200 Barriers::SetPrimitive<JSTaggedType>(
201 GetData(), GetIcSlotLength() * JSTaggedValue::TaggedTypeSize(),
202 JSTaggedValue::Undefined().GetRawData());
203 }
204
InitializeJitOsr()205 inline void InitializeJitOsr()
206 {
207 // the last of the cache is used to save osr jit tagged array
208 Barriers::SetPrimitive<JSTaggedType>(
209 GetData(), (GetIcSlotLength() + 1) * JSTaggedValue::TaggedTypeSize(),
210 JSTaggedValue::Undefined().GetRawData());
211 }
212
213 inline void InitializeWithSpecialValue(JSTaggedValue initValue, uint32_t icSlotSize, uint32_t extraLength = 0)
214 {
215 ASSERT(initValue.IsSpecial());
216 icSlotSize = AdjustSlotSize(icSlotSize);
217 SetLength(icSlotSize + RESERVED_LENGTH);
218 SetExtraLength(extraLength);
219 SetPrimitiveOfSlot(initValue, icSlotSize);
220 InitializeExtraInfoMap();
221 InitializeJitOsr();
222 SetSpecialValue();
223 }
224
SetPreDumpPeriodIndex()225 void SetPreDumpPeriodIndex()
226 {
227 SetPeriodIndex(PRE_DUMP_PERIOD_INDEX);
228 }
229
IsProfileTypeInfoPreDumped()230 bool IsProfileTypeInfoPreDumped() const
231 {
232 return GetPeriodIndex() == PRE_DUMP_PERIOD_INDEX;
233 }
234
SetBigMethodPeriodIndex()235 void SetBigMethodPeriodIndex()
236 {
237 SetPeriodIndex(BIG_METHOD_PERIOD_INDEX);
238 }
239
IsProfileTypeInfoWithBigMethod()240 bool IsProfileTypeInfoWithBigMethod() const
241 {
242 return GetPeriodIndex() == BIG_METHOD_PERIOD_INDEX;
243 }
244
GetExtraInfoMap(const JSThread * thread)245 JSTaggedValue GetExtraInfoMap(const JSThread *thread) const
246 {
247 return JSTaggedValue(Barriers::GetTaggedValue(thread, GetData(), GetExtraInfoMapOffset()));
248 }
249
SetExtraInfoMap(const JSThread * thread,JSHandle<NumberDictionary> extraInfoMap)250 void SetExtraInfoMap(const JSThread *thread, JSHandle<NumberDictionary> extraInfoMap)
251 {
252 Barriers::SetObject<true>(thread, reinterpret_cast<void*>(this),
253 TaggedArray::DATA_OFFSET + GetExtraInfoMapOffset(),
254 extraInfoMap.GetTaggedValue().GetRawData());
255 }
256
GetJitHotnessThreshold()257 uint16_t GetJitHotnessThreshold() const
258 {
259 return Barriers::GetPrimitive<uint16_t>(GetData(), GetJitHotnessThresholdBitfieldOffset());
260 }
261
SetJitHotnessThreshold(uint16_t count)262 void SetJitHotnessThreshold(uint16_t count)
263 {
264 Barriers::SetPrimitive(GetData(), GetJitHotnessThresholdBitfieldOffset(), count);
265 }
266
GetOsrHotnessThreshold()267 uint16_t GetOsrHotnessThreshold() const
268 {
269 return Barriers::GetPrimitive<uint16_t>(GetData(), GetOsrHotnessThresholdBitfieldOffset());
270 }
271
SetOsrHotnessThreshold(uint16_t count)272 void SetOsrHotnessThreshold(uint16_t count)
273 {
274 Barriers::SetPrimitive(GetData(), GetOsrHotnessThresholdBitfieldOffset(), count);
275 }
276
GetBaselineJitHotnessThreshold()277 uint16_t GetBaselineJitHotnessThreshold() const
278 {
279 return Barriers::GetPrimitive<uint16_t>(GetData(), GetBaselineJitHotnessThresholdBitfieldOffset());
280 }
281
SetBaselineJitHotnessThreshold(uint16_t count)282 void SetBaselineJitHotnessThreshold(uint16_t count)
283 {
284 Barriers::SetPrimitive(GetData(), GetBaselineJitHotnessThresholdBitfieldOffset(), count);
285 }
286
SetJitCallThreshold(uint16_t count)287 void SetJitCallThreshold(uint16_t count)
288 {
289 Barriers::SetPrimitive(GetData(), GetJitCallCntBitfieldOffset(), count);
290 }
291
GetJitHotnessCnt()292 uint16_t GetJitHotnessCnt() const
293 {
294 return Barriers::GetPrimitive<uint16_t>(GetData(), GetJitHotnessCntBitfieldOffset());
295 }
296
SetJitHotnessCnt(uint16_t count)297 void SetJitHotnessCnt(uint16_t count)
298 {
299 Barriers::SetPrimitive(GetData(), GetJitHotnessCntBitfieldOffset(), count);
300 }
301
SetOsrHotnessCnt(uint16_t count)302 void SetOsrHotnessCnt(uint16_t count)
303 {
304 Barriers::SetPrimitive(GetData(), GetOsrHotnessCntBitfieldOffset(), count);
305 }
306
GetIcSlot(const JSThread * thread,uint32_t idx)307 inline JSTaggedValue GetIcSlot(const JSThread* thread, uint32_t idx) const
308 {
309 ASSERT(idx < GetIcSlotLength());
310 return TaggedArray::Get(thread, idx);
311 }
312
SetIcSlot(const JSThread * thread,uint32_t idx,const JSTaggedValue & value)313 inline void SetIcSlot(const JSThread* thread, uint32_t idx, const JSTaggedValue& value)
314 {
315 ASSERT(idx < GetIcSlotLength());
316 TaggedArray::Set(thread, idx, value);
317 }
318
SetMultiIcSlotLocked(JSThread * thread,uint32_t firstIdx,const JSTaggedValue & firstValue,uint32_t secondIdx,const JSTaggedValue & secondValue)319 inline void SetMultiIcSlotLocked(JSThread* thread, uint32_t firstIdx, const JSTaggedValue& firstValue,
320 uint32_t secondIdx, const JSTaggedValue& secondValue)
321 {
322 ProfileTypeAccessorLockScope accessorLockScope(thread);
323 ASSERT(firstIdx < GetIcSlotLength());
324 ASSERT(secondIdx < GetIcSlotLength());
325 TaggedArray::Set(thread, firstIdx, firstValue);
326 TaggedArray::Set(thread, secondIdx, secondValue);
327 }
328
CreateOrGetExtraInfoMap(const JSThread * thread,JSHandle<ProfileTypeInfo> profileTypeInfo)329 static JSHandle<NumberDictionary> CreateOrGetExtraInfoMap(const JSThread *thread,
330 JSHandle<ProfileTypeInfo> profileTypeInfo)
331 {
332 if (profileTypeInfo->GetExtraInfoMap(thread).IsUndefined()) {
333 JSHandle<NumberDictionary> dictJShandle = NumberDictionary::Create(thread);
334 profileTypeInfo->SetExtraInfoMap(thread, dictJShandle);
335 return dictJShandle;
336 }
337 JSHandle<NumberDictionary> dictJShandle(thread, profileTypeInfo->GetExtraInfoMap(thread));
338 return dictJShandle;
339 }
340
UpdateExtraInfoMap(const JSThread * thread,JSHandle<NumberDictionary> dictJShandle,JSHandle<JSTaggedValue> key,JSHandle<JSTaggedValue> receiverHClassHandle,JSHandle<JSTaggedValue> holderHClassHandle,JSHandle<ProfileTypeInfo> profileTypeInfo)341 static void UpdateExtraInfoMap(const JSThread *thread, JSHandle<NumberDictionary> dictJShandle,
342 JSHandle<JSTaggedValue> key, JSHandle<JSTaggedValue> receiverHClassHandle,
343 JSHandle<JSTaggedValue> holderHClassHandle,
344 JSHandle<ProfileTypeInfo> profileTypeInfo)
345 {
346 JSHandle<JSTaggedValue> info(thread->GetEcmaVM()->GetFactory()->NewExtraProfileTypeInfo());
347 JSHandle<ExtraProfileTypeInfo> infoHandle(info);
348 infoHandle->SetReceiver(thread, receiverHClassHandle.GetTaggedValue().CreateAndGetWeakRef());
349 infoHandle->SetHolder(thread, holderHClassHandle.GetTaggedValue());
350 JSHandle<NumberDictionary> dict = NumberDictionary::PutIfAbsent(thread,
351 dictJShandle,
352 key,
353 info,
354 PropertyAttributes::Default());
355 profileTypeInfo->SetExtraInfoMap(thread, dict);
356 }
357
358 DECL_VISIT_ARRAY(DATA_OFFSET, GetIcSlotToOsrLength(), GetIcSlotToOsrLength());
359
DECL_DUMP()360 DECL_DUMP()
361
362 private:
363 uint32_t GetPeriodIndex() const
364 {
365 return Barriers::GetPrimitive<uint32_t>(GetData(), GetBitfieldOffset());
366 }
367
SetPeriodIndex(uint32_t count)368 void SetPeriodIndex(uint32_t count)
369 {
370 Barriers::SetPrimitive(GetData(), GetBitfieldOffset(), count);
371 }
372
GetBitfieldOffset()373 inline size_t GetBitfieldOffset() const
374 {
375 return JSTaggedValue::TaggedTypeSize() * (GetLength() - BIT_FIELD_INDEX);
376 }
377
GetExtraInfoMapOffset()378 inline size_t GetExtraInfoMapOffset() const
379 {
380 return JSTaggedValue::TaggedTypeSize() * (GetLength() - EXTRA_INFO_MAP_INDEX);
381 }
382
383 // jit hotness(16bits) + count(16bits)
GetJitHotnessThresholdBitfieldOffset()384 inline size_t GetJitHotnessThresholdBitfieldOffset() const
385 {
386 return GetBitfieldOffset() + JIT_HOTNESS_THRESHOLD_OFFSET_FROM_BITFIELD;
387 }
388
GetJitHotnessCntBitfieldOffset()389 inline size_t GetJitHotnessCntBitfieldOffset() const
390 {
391 return GetJitHotnessThresholdBitfieldOffset() + JIT_CNT_OFFSET_FROM_THRESHOLD;
392 }
393
394 // osr hotness(16bits) + count(16bits)
GetOsrHotnessThresholdBitfieldOffset()395 inline size_t GetOsrHotnessThresholdBitfieldOffset() const
396 {
397 return GetBitfieldOffset() + OSR_HOTNESS_THRESHOLD_OFFSET_FROM_BITFIELD;
398 }
399
400 // baselinejit hotness(16bits)
GetBaselineJitHotnessThresholdBitfieldOffset()401 inline size_t GetBaselineJitHotnessThresholdBitfieldOffset() const
402 {
403 return GetBitfieldOffset() + BASELINEJIT_HOTNESS_THRESHOLD_OFFSET_FROM_BITFIELD;
404 }
405
GetOsrHotnessCntBitfieldOffset()406 inline size_t GetOsrHotnessCntBitfieldOffset() const
407 {
408 return GetOsrHotnessThresholdBitfieldOffset() + OSR_CNT_OFFSET_FROM_OSR_THRESHOLD;
409 }
410
411 // jit call count(16bits)
GetJitCallCntBitfieldOffset()412 inline size_t GetJitCallCntBitfieldOffset() const
413 {
414 return GetBitfieldOffset() + JIT_CALL_CNT_OFFSET_FROM_BITFIELD;
415 }
416 };
417
418 class ProfileTypeAccessor {
419 public:
420 static constexpr size_t CACHE_MAX_LEN = 8;
421 static constexpr size_t MONO_CASE_NUM = 2;
422 static constexpr size_t POLY_CASE_NUM = 4;
423
424 enum ICState {
425 UNINIT,
426 MONO,
427 POLY,
428 IC_MEGA,
429 MEGA,
430 };
431
432 #if ECMASCRIPT_ENABLE_TRACE_LOAD
433 enum MegaState {
434 NONE,
435 NOTFOUND_MEGA,
436 DICT_MEGA,
437 };
438 #endif
439
ProfileTypeAccessor(JSThread * thread,JSHandle<ProfileTypeInfo> profileTypeInfo,uint32_t slotId,ICKind kind)440 ProfileTypeAccessor(JSThread* thread, JSHandle<ProfileTypeInfo> profileTypeInfo, uint32_t slotId, ICKind kind)
441 : thread_(thread), profileTypeInfo_(profileTypeInfo), slotId_(slotId), kind_(kind)
442 {
443 enableICMega_ = thread_->GetEcmaVM()->GetJSOptions().IsEnableMegaIC();
444 }
445 ~ProfileTypeAccessor() = default;
446 ICState GetMegaState() const;
447 ICState GetICState() const;
448 static std::string ICStateToString(ICState state);
449 void AddHandlerWithoutKey(JSHandle<JSTaggedValue> hclass, JSHandle<JSTaggedValue> handler,
450 JSHandle<JSTaggedValue> keyForMegaIC = JSHandle<JSTaggedValue>(),
451 MegaICCache::MegaICKind kind = MegaICCache::MegaICKind::None) const;
452 void AddWithoutKeyPoly(JSHandle<JSTaggedValue> hclass, JSHandle<JSTaggedValue> handler, uint32_t index,
453 JSTaggedValue profileData, JSHandle<JSTaggedValue> keyForMegaIC = JSHandle<JSTaggedValue>(),
454 MegaICCache::MegaICKind kind = MegaICCache::MegaICKind::None) const;
455
456 void AddElementHandler(JSHandle<JSTaggedValue> hclass, JSHandle<JSTaggedValue> handler) const;
457 void AddHandlerWithKey(JSHandle<JSTaggedValue> key, JSHandle<JSTaggedValue> hclass,
458 JSHandle<JSTaggedValue> handler) const;
459 void AddGlobalHandlerKey(JSHandle<JSTaggedValue> key, JSHandle<JSTaggedValue> handler) const;
460 void AddGlobalRecordHandler(JSHandle<JSTaggedValue> handler) const;
461
GetWeakRef(JSTaggedValue value)462 JSTaggedValue GetWeakRef(JSTaggedValue value) const
463 {
464 return JSTaggedValue(value.CreateAndGetWeakRef());
465 }
466
GetRefFromWeak(const JSTaggedValue & value)467 JSTaggedValue GetRefFromWeak(const JSTaggedValue &value) const
468 {
469 return JSTaggedValue(value.GetWeakReferent());
470 }
471 void SetAsMega() const;
472 void SetAsMegaIfUndefined() const;
473 void SetAsMegaForTraceSlowMode(ObjectOperator& op) const;
474 void SetAsMegaForTrace(JSTaggedValue value) const;
475
GetKind()476 ICKind GetKind() const
477 {
478 return kind_;
479 }
480
GetSlotId()481 uint32_t GetSlotId() const
482 {
483 return slotId_;
484 }
485
486 private:
487 JSThread* thread_;
488 JSHandle<ProfileTypeInfo> profileTypeInfo_;
489 uint32_t slotId_;
490 ICKind kind_;
491 bool enableICMega_;
492 };
493 } // namespace panda::ecmascript
494
495 #endif // ECMASCRIPT_IC_PROFILE_TYPE_INFO_H
496