• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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_PGO_PROFILER_LAYOUT_H
17 #define ECMASCRIPT_PGO_PROFILER_LAYOUT_H
18 
19 #include <cstdint>
20 #include <string>
21 
22 #include "ecmascript/ecma_vm.h"
23 #include "ecmascript/elements.h"
24 #include "ecmascript/js_hclass.h"
25 #include "ecmascript/js_object.h"
26 #include "ecmascript/log_wrapper.h"
27 #include "ecmascript/mem/c_containers.h"
28 #include "ecmascript/mem/region.h"
29 #include "ecmascript/pgo_profiler/pgo_context.h"
30 #include "ecmascript/pgo_profiler/pgo_utils.h"
31 #include "ecmascript/pgo_profiler/types/pgo_profile_type.h"
32 #include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
33 #include "ecmascript/property_attributes.h"
34 
35 namespace panda::ecmascript::pgo {
36 class PGOHandler {
37 public:
38     using TrackTypeField =
39         PropertyAttributes::PropertyMetaDataField::NextField<TrackType, PropertyAttributes::TRACK_TYPE_NUM>;
40     using IsSymbol = TrackTypeField::NextFlag;
41     using MaxPropsNumField = IsSymbol::NextField<uint32_t, PropertyAttributes::MAX_LITERAL_HCLASS_CACHE_BIT>;
42 
PGOHandler()43     PGOHandler()
44     {
45         SetTrackType(TrackType::NONE);
46         SetPropertyMeta(false);
47     }
48 
PGOHandler(TrackType type,int meta)49     PGOHandler(TrackType type, int meta)
50     {
51         SetTrackType(type);
52         SetPropertyMeta(meta);
53     }
54 
PGOHandler(TrackType type,int meta,bool isSymbol)55     PGOHandler(TrackType type, int meta, bool isSymbol)
56     {
57         SetTrackType(type);
58         SetPropertyMeta(meta);
59         SetIsSymbol(isSymbol);
60     }
61 
GetValue()62     uint32_t GetValue() const
63     {
64         return value_;
65     }
66 
67     bool SetAttribute(const JSThread *thread, PropertyAttributes &attr) const;
68 
SetIsSymbol(bool isSymbol)69     void SetIsSymbol(bool isSymbol)
70     {
71         IsSymbol::Set(isSymbol, &value_);
72     }
73 
SetMaxPropsNum(uint32_t maxChildNum)74     void SetMaxPropsNum(uint32_t maxChildNum) const
75     {
76         MaxPropsNumField::Set(maxChildNum, &value_);
77     }
78 
GetMaxPropsNum()79     uint32_t GetMaxPropsNum() const
80     {
81         return MaxPropsNumField::Get(value_);
82     }
83 
GetIsSymbol()84     bool GetIsSymbol() const
85     {
86         return IsSymbol::Get(value_);
87     }
88 
SetTrackType(TrackType type)89     void SetTrackType(TrackType type)
90     {
91         TrackTypeField::Set(type, &value_);
92     }
93 
GetTrackType()94     TrackType GetTrackType() const
95     {
96         return TrackTypeField::Get(value_);
97     }
98 
SetPropertyMeta(int meta)99     void SetPropertyMeta(int meta)
100     {
101         PropertyAttributes::PropertyMetaDataField::Set(meta, &value_);
102     }
103 
GetPropertyMeta()104     int GetPropertyMeta() const
105     {
106         return PropertyAttributes::PropertyMetaDataField::Get(value_);
107     }
108 
IsAccessor()109     bool IsAccessor() const
110     {
111         return PropertyAttributes::IsAccessorField::Get(value_);
112     }
113 
IsWritable()114     bool IsWritable() const
115     {
116         return PropertyAttributes::WritableField::Get(value_);
117     }
118 
IsEnumerable()119     bool IsEnumerable() const
120     {
121         return PropertyAttributes::EnumerableField::Get(value_);
122     }
123 
IsConfigurable()124     bool IsConfigurable() const
125     {
126         return PropertyAttributes::ConfigurableField::Get(value_);
127     }
128 
129     bool operator!=(const PGOHandler &right) const
130     {
131         return value_ != right.value_;
132     }
133 
134     bool operator==(const PGOHandler &right) const
135     {
136         return value_ == right.value_;
137     }
138 
139 private:
140     mutable uint32_t value_ { 0 };
141 };
142 
143 using PropertyDesc = std::pair<CString, PGOHandler>;
144 using LayoutDesc = CVector<PropertyDesc>;
145 class PGOHClassTreeDesc;
146 
147 class HClassLayoutDesc {
148 public:
HClassLayoutDesc(ProfileType type)149     explicit HClassLayoutDesc(ProfileType type) : type_(type) {}
HClassLayoutDesc(ProfileType type,const CSet<ProfileType> & childs)150     HClassLayoutDesc(ProfileType type, const CSet<ProfileType> &childs) : type_(type), childs_(childs) {}
151     virtual ~HClassLayoutDesc() = default;
152 
153     virtual void Merge(const HClassLayoutDesc *from);
154     virtual void InsertKeyAndDesc(const CString &key, const PGOHandler &handler) = 0;
155     virtual bool UpdateKeyAndDesc(const CString &key, const PGOHandler &handler) = 0;
156     virtual bool IsRoot() const = 0;
157 
GetProfileType()158     ProfileType GetProfileType() const
159     {
160         return type_;
161     }
162 
AddChildHClassLayoutDesc(const ProfileType & type)163     void AddChildHClassLayoutDesc(const ProfileType &type)
164     {
165         if (type_.GetRaw() == type.GetRaw()) {
166             return;
167         }
168         childs_.emplace(type);
169     }
170 
FindChild(const ProfileType & type)171     bool FindChild(const ProfileType &type)
172     {
173         return childs_.find(type) != childs_.end();
174     }
175 
GetChildSize()176     inline size_t GetChildSize() const
177     {
178         return childs_.size();
179     }
180 
181     template<typename Callback>
IterateChilds(Callback callback)182     void IterateChilds(Callback callback) const
183     {
184         for (const auto &type : childs_) {
185             if (!callback(type)) {
186                 break;
187             }
188         }
189     }
190 
191 protected:
192     void InsertKeyAndDesc(const PGOHandler &handler, PropertyDesc &desc);
193 
194     ProfileType type_;
195     CSet<ProfileType> childs_;
196 };
197 
198 class RootHClassLayoutDesc final : public HClassLayoutDesc {
199 public:
RootHClassLayoutDesc(ProfileType type)200     explicit RootHClassLayoutDesc(ProfileType type) : HClassLayoutDesc(type) {}
RootHClassLayoutDesc(ProfileType type,JSType objType,uint32_t objSize)201     RootHClassLayoutDesc(ProfileType type, JSType objType, uint32_t objSize)
202         : HClassLayoutDesc(type), objType_(objType), objSize_(objSize) {}
RootHClassLayoutDesc(const RootHClassLayoutDesc & desc)203     RootHClassLayoutDesc(const RootHClassLayoutDesc &desc)
204         : HClassLayoutDesc(desc.type_, desc.childs_), objType_(desc.objType_), objSize_(desc.objSize_),
205           layoutDesc_(desc.layoutDesc_) {}
206     RootHClassLayoutDesc& operator=(const RootHClassLayoutDesc &desc)
207     {
208         this->type_ = desc.type_;
209         this->childs_ = desc.childs_;
210         this->objType_ = desc.objType_;
211         this->objSize_ = desc.objSize_;
212         this->layoutDesc_ = desc.layoutDesc_;
213         return *this;
214     }
215 
216     void Merge(const HClassLayoutDesc *from) override;
217     void InsertKeyAndDesc(const CString &key, const PGOHandler &handler) override;
218     bool UpdateKeyAndDesc(const CString &key, const PGOHandler &handler) override;
219 
IsRoot()220     bool IsRoot() const override
221     {
222         return true;
223     }
224 
SetObjectSize(uint32_t objSize)225     void SetObjectSize(uint32_t objSize)
226     {
227         objSize_ = objSize;
228     }
229 
GetObjectSize()230     uint32_t GetObjectSize() const
231     {
232         return objSize_;
233     }
234 
SetObjectType(JSType objType)235     void SetObjectType(JSType objType)
236     {
237         objType_ = objType;
238     }
239 
GetObjectType()240     JSType GetObjectType() const
241     {
242         return objType_;
243     }
244 
NumOfProps()245     size_t NumOfProps() const
246     {
247         return layoutDesc_.size();
248     }
249 
250     template<typename Callback>
IterateProps(Callback callback)251     void IterateProps(Callback callback) const
252     {
253         for (const auto &iter : layoutDesc_) {
254             callback(iter);
255         }
256     }
257 
258 private:
259     JSType objType_;
260     uint32_t objSize_ {0};
261     LayoutDesc layoutDesc_;
262 };
263 
264 class ChildHClassLayoutDesc final : public HClassLayoutDesc {
265 public:
ChildHClassLayoutDesc(ProfileType type)266     explicit ChildHClassLayoutDesc(ProfileType type) : HClassLayoutDesc(type) {}
ChildHClassLayoutDesc(const ChildHClassLayoutDesc & desc)267     ChildHClassLayoutDesc(const ChildHClassLayoutDesc &desc)
268         : HClassLayoutDesc(desc.type_, desc.childs_), propertyDesc_(desc.propertyDesc_) {}
269     ChildHClassLayoutDesc& operator=(const ChildHClassLayoutDesc &desc)
270     {
271         this->type_ = desc.type_;
272         this->childs_ = desc.childs_;
273         this->propertyDesc_ = desc.propertyDesc_;
274         return *this;
275     }
276 
277     void Merge(const HClassLayoutDesc *from) override;
278     void InsertKeyAndDesc(const CString &key, const PGOHandler &handler) override;
279     bool UpdateKeyAndDesc(const CString &key, const PGOHandler &handler) override;
280 
IsRoot()281     bool IsRoot() const override
282     {
283         return false;
284     }
285 
GetPropertyDesc()286     PropertyDesc GetPropertyDesc() const
287     {
288         return propertyDesc_;
289     }
290 
291 private:
292     PropertyDesc propertyDesc_;
293 };
294 
295 class PGOHClassTreeDesc {
296 public:
297     PGOHClassTreeDesc() = default;
PGOHClassTreeDesc(ProfileType type)298     explicit PGOHClassTreeDesc(ProfileType type) : type_(type) {}
299 
300     void Clear();
301 
GetProfileType()302     ProfileType GetProfileType() const
303     {
304         return type_;
305     }
306 
SetProtoPt(ProfileType protoPt)307     void SetProtoPt(ProfileType protoPt)
308     {
309         protoPt_ = protoPt;
310     }
311 
GetProtoPt()312     ProfileType GetProtoPt() const
313     {
314         return protoPt_;
315     }
316 
317     void Merge(const PGOHClassTreeDesc &from);
318 
319     bool operator<(const PGOHClassTreeDesc &right) const
320     {
321         return type_ < right.type_;
322     }
323 
324     HClassLayoutDesc *GetHClassLayoutDesc(ProfileType type) const;
325     HClassLayoutDesc *GetOrInsertHClassLayoutDesc(ProfileType type, bool root = false);
326 
327     bool DumpForRoot(JSTaggedType root, ProfileType rootType);
328     bool DumpForChild(JSTaggedType child, ProfileType childType);
329     bool UpdateForTransition(JSTaggedType parent, ProfileType parentType, JSTaggedType child, ProfileType childType);
330     bool UpdateLayout(JSTaggedType curHClass, ProfileType curType);
331     bool IsDumped(ProfileType curType) const;
332 
333     template<typename Callback>
IterateChilds(Callback callback)334     void IterateChilds(Callback callback) const
335     {
336         IterateAll([&callback] (HClassLayoutDesc *desc) {
337             if (desc->GetProfileType().IsRootType()) {
338                 return;
339             }
340             callback(reinterpret_cast<ChildHClassLayoutDesc *>(desc));
341         });
342     }
343 
CheckHasInvalidType()344     bool CheckHasInvalidType() const
345     {
346         for (auto iter : transitionLayout_) {
347             if (iter.first.IsInvalidType()) {
348                 return true;
349             }
350         }
351         return false;
352     }
353 
354 private:
355     template<typename Callback>
IterateAll(Callback callback)356     void IterateAll(Callback callback) const
357     {
358         for (auto iter : transitionLayout_) {
359             callback(iter.second);
360         }
361     }
362 
363     ProfileType type_;
364     ProfileType protoPt_;
365     CMap<ProfileType, HClassLayoutDesc *> transitionLayout_;
366 };
367 
368 class PGOLayoutDescInfo {
369 public:
370     PGOLayoutDescInfo() = default;
PGOLayoutDescInfo(const CString & key,PGOHandler handler)371     PGOLayoutDescInfo(const CString &key, PGOHandler handler) : handler_(handler)
372     {
373         size_t len = key.size();
374         size_ = Size(len);
375         if (len > 0 && memcpy_s(&key_, len, key.c_str(), len) != EOK) {
376             LOG_ECMA(ERROR) << "SetMethodName memcpy_s failed" << key << ", len = " << len;
377             UNREACHABLE();
378         }
379         *(&key_ + len) = '\0';
380     }
381 
Size(size_t len)382     static int32_t Size(size_t len)
383     {
384         return sizeof(PGOLayoutDescInfo) + AlignUp(len, GetAlignmentInBytes(ALIGN_SIZE));
385     }
386 
Size()387     int32_t Size() const
388     {
389         return size_;
390     }
391 
GetKey()392     const char *GetKey() const
393     {
394         return &key_;
395     }
396 
GetHandler()397     PGOHandler GetHandler() const
398     {
399         return handler_;
400     }
401 
402 private:
403     int32_t size_ {0};
404     PGOHandler handler_;
405     char key_ {'\0'};
406 };
407 
408 class HClassLayoutDescInner {
409 public:
410     virtual ~HClassLayoutDescInner() = default;
Size()411     int32_t Size() const
412     {
413         return size_;
414     }
415 
GetProfileType()416     ProfileType GetProfileType() const
417     {
418         return type_;
419     }
420 
421 protected:
422     int32_t size_ { 0 };
423     ProfileType type_;
424 };
425 
426 class RootHClassLayoutDescInner : public HClassLayoutDescInner {
427 public:
CaculateSize(const RootHClassLayoutDesc & desc)428     static size_t CaculateSize(const RootHClassLayoutDesc &desc)
429     {
430         size_t size = sizeof(RootHClassLayoutDescInner);
431         size += desc.GetChildSize() * sizeof(ProfileType);
432         desc.IterateProps([&size] (const PropertyDesc &propDesc) {
433             auto keyLen = propDesc.first.size();
434             size += static_cast<size_t>(PGOLayoutDescInfo::Size(keyLen));
435         });
436         return size;
437     }
438 
Merge(const RootHClassLayoutDesc & desc)439     void Merge(const RootHClassLayoutDesc &desc)
440     {
441         size_ = static_cast<int32_t>(RootHClassLayoutDescInner::CaculateSize(desc));
442         type_ = desc.GetProfileType();
443         childCount_ = 0;
444         desc.IterateChilds([this] (const ProfileType &childType) -> bool {
445             auto newChildType = const_cast<ProfileType *>(GetChildType(childCount_++));
446             new (newChildType) ProfileType(childType);
447             return true;
448         });
449 
450         auto current = const_cast<PGOLayoutDescInfo *>(GetFirstProperty());
451         desc.IterateProps([this, &current] (const PropertyDesc &propDesc) {
452             auto key = propDesc.first;
453             auto type = propDesc.second;
454             new (current) PGOLayoutDescInfo(key, type);
455             current = const_cast<PGOLayoutDescInfo *>(GetNextProperty(current));
456             propCount_++;
457         });
458     }
459 
Convert(PGOContext & context,RootHClassLayoutDesc * desc)460     void Convert(PGOContext& context, RootHClassLayoutDesc *desc) const
461     {
462         auto descInfo = GetFirstProperty();
463         for (uint32_t i = 0; i < propCount_; i++) {
464             desc->InsertKeyAndDesc(descInfo->GetKey(), descInfo->GetHandler());
465             descInfo = GetNextProperty(descInfo);
466         }
467         for (uint32_t i = 0; i < childCount_; i++) {
468             auto profileType(*GetChildType(i));
469             desc->AddChildHClassLayoutDesc(profileType.Remap(context));
470         }
471     }
472 
SetObjectType(JSType objType)473     void SetObjectType(JSType objType)
474     {
475         objType_ = objType;
476     }
477 
GetObjectType()478     JSType GetObjectType() const
479     {
480         return objType_;
481     }
482 
SetObjectSize(uint32_t size)483     void SetObjectSize(uint32_t size)
484     {
485         objSize_ = size;
486     }
487 
GetObjectSize()488     uint32_t GetObjectSize() const
489     {
490         return objSize_;
491     }
492 
493 private:
GetChildType(uint32_t index)494     const ProfileType *GetChildType(uint32_t index) const
495     {
496         return (&childType_) + index;
497     }
498 
GetFirstProperty()499     const PGOLayoutDescInfo *GetFirstProperty() const
500     {
501         return reinterpret_cast<const PGOLayoutDescInfo *>(reinterpret_cast<uintptr_t>(&childType_ + childCount_));
502     }
503 
GetNextProperty(const PGOLayoutDescInfo * current)504     const PGOLayoutDescInfo *GetNextProperty(const PGOLayoutDescInfo *current) const
505     {
506         return reinterpret_cast<const PGOLayoutDescInfo *>(reinterpret_cast<uintptr_t>(current) + current->Size());
507     }
508 
509     JSType objType_;
510     uint32_t objSize_ {0};
511     uint32_t propCount_ {0};
512     uint32_t childCount_ {0};
513     ProfileType childType_;
514 };
515 
516 class ChildHClassLayoutDescInner : public HClassLayoutDescInner {
517 public:
CaculateSize(const ChildHClassLayoutDesc & desc)518     static size_t CaculateSize(const ChildHClassLayoutDesc &desc)
519     {
520         size_t size = sizeof(ChildHClassLayoutDescInner);
521         size += desc.GetChildSize() * sizeof(ProfileType);
522         auto key = desc.GetPropertyDesc().first;
523         size += static_cast<size_t>(PGOLayoutDescInfo::Size(key.size()));
524         return size;
525     }
526 
Merge(const ChildHClassLayoutDesc & desc)527     void Merge(const ChildHClassLayoutDesc &desc)
528     {
529         size_ = static_cast<int32_t>(ChildHClassLayoutDescInner::CaculateSize(desc));
530         type_ = desc.GetProfileType();
531         childCount_ = 0;
532         desc.IterateChilds([this] (const ProfileType &childType) -> bool {
533             auto newChildType = const_cast<ProfileType *>(GetChildType(childCount_++));
534             new (newChildType) ProfileType(childType);
535             return true;
536         });
537 
538         auto current = const_cast<PGOLayoutDescInfo *>(GetProperty());
539         auto propDesc = desc.GetPropertyDesc();
540         auto key = propDesc.first;
541         auto type = propDesc.second;
542         new (current) PGOLayoutDescInfo(key, type);
543     }
544 
Convert(PGOContext & context,ChildHClassLayoutDesc * desc)545     void Convert(PGOContext& context, ChildHClassLayoutDesc *desc) const
546     {
547         auto descInfo = GetProperty();
548         desc->InsertKeyAndDesc(descInfo->GetKey(), descInfo->GetHandler());
549         for (uint32_t i = 0; i < childCount_; i++) {
550             auto profileType(*GetChildType(i));
551             desc->AddChildHClassLayoutDesc(profileType.Remap(context));
552         }
553     }
554 
555 private:
GetChildType(uint32_t index)556     const ProfileType *GetChildType(uint32_t index) const
557     {
558         return (&childType_) + index;
559     }
560 
GetProperty()561     const PGOLayoutDescInfo *GetProperty() const
562     {
563         return reinterpret_cast<const PGOLayoutDescInfo *>(&childType_ + childCount_);
564     }
565 
566     uint32_t childCount_ { 0 };
567     ProfileType childType_;
568 };
569 
570 template <typename SampleType>
571 class PGOHClassTreeTemplate {
572 public:
PGOHClassTreeTemplate(size_t size,SampleType type,SampleType protoSt)573     PGOHClassTreeTemplate(size_t size, SampleType type, SampleType protoSt)
574         : size_(size), type_(type), protoSt_(protoSt) {}
575 
CaculateSize(const PGOHClassTreeDesc & desc)576     static size_t CaculateSize(const PGOHClassTreeDesc &desc)
577     {
578         auto rootLayout = desc.GetHClassLayoutDesc(desc.GetProfileType());
579         if (rootLayout == nullptr) {
580             return sizeof(PGOHClassTreeTemplate<SampleType>);
581         }
582         if (!rootLayout->IsRoot()) {
583             LOG_ECMA(ERROR) << "rootLayout is not RootHClassLayoutDesc!";
584         }
585         size_t size = sizeof(PGOHClassTreeTemplate<SampleType>) - sizeof(RootHClassLayoutDescInner);
586         size += RootHClassLayoutDescInner::CaculateSize(*reinterpret_cast<const RootHClassLayoutDesc *>(rootLayout));
587 
588         desc.IterateChilds([&size](ChildHClassLayoutDesc *desc) {
589             size += ChildHClassLayoutDescInner::CaculateSize(*desc);
590         });
591         return size;
592     }
593 
GetTypeString(const PGOHClassTreeDesc & desc)594     static std::string GetTypeString(const PGOHClassTreeDesc &desc)
595     {
596         std::string text;
597         text += desc.GetProfileType().GetTypeString();
598         text += DumpUtils::BLOCK_AND_ARRAY_START;
599         auto layoutDesc = desc.GetHClassLayoutDesc(desc.GetProfileType());
600         if (layoutDesc != nullptr) {
601             bool isLayoutFirst = true;
602             ASSERT(layoutDesc->GetProfileType().IsRootType());
603             auto rootLayoutDesc = reinterpret_cast<RootHClassLayoutDesc *>(layoutDesc);
604             rootLayoutDesc->IterateProps([&text, &isLayoutFirst] (const PropertyDesc &propDesc) {
605                 if (!isLayoutFirst) {
606                     text += DumpUtils::SPACE + DumpUtils::TYPE_SEPARATOR + DumpUtils::SPACE;
607                 }
608                 isLayoutFirst = false;
609                 text += propDesc.first;
610                 text += DumpUtils::BLOCK_START;
611                 text += std::to_string(propDesc.second.GetValue());
612             });
613         }
614         text += (DumpUtils::SPACE + DumpUtils::ARRAY_END);
615         return text;
616     }
617 
Merge(const PGOHClassTreeDesc & desc)618     void Merge(const PGOHClassTreeDesc &desc)
619     {
620         auto root = const_cast<RootHClassLayoutDescInner *>(GetRoot());
621         auto layoutDesc = desc.GetHClassLayoutDesc(desc.GetProfileType());
622         if (layoutDesc == nullptr) {
623             return;
624         }
625         auto rootLayoutDesc = reinterpret_cast<const RootHClassLayoutDesc *>(layoutDesc);
626         root->Merge(*rootLayoutDesc);
627         root->SetObjectType(rootLayoutDesc->GetObjectType());
628         root->SetObjectSize(rootLayoutDesc->GetObjectSize());
629 
630         childCount_ = 0;
631         auto last = reinterpret_cast<HClassLayoutDescInner *>(root);
632         desc.IterateChilds([this, &last](ChildHClassLayoutDesc *desc) {
633             auto current = const_cast<ChildHClassLayoutDescInner *>(GetNext(last));
634             new (current) ChildHClassLayoutDescInner();
635             current->Merge(*desc);
636             last = current;
637             childCount_++;
638         });
639     }
640 
Convert(PGOContext & context)641     PGOHClassTreeDesc Convert(PGOContext& context)
642     {
643         PGOHClassTreeDesc desc(ProfileType(context, GetType().GetProfileType()));
644         desc.SetProtoPt(ProfileType(context, GetProtoSt().GetProfileType()));
645         auto root = GetRoot();
646         if (root->GetProfileType().IsNone()) {
647             return desc;
648         }
649         auto layoutDesc = desc.GetOrInsertHClassLayoutDesc(root->GetProfileType().Remap(context), true);
650         auto rootLayoutDesc = reinterpret_cast<RootHClassLayoutDesc *>(layoutDesc);
651         rootLayoutDesc->SetObjectType(root->GetObjectType());
652         rootLayoutDesc->SetObjectSize(root->GetObjectSize());
653         root->Convert(context, rootLayoutDesc);
654 
655         auto last = reinterpret_cast<const HClassLayoutDescInner *>(root);
656         for (int32_t i = 0; i < childCount_; i++) {
657             auto current = GetNext(last);
658             auto childLayoutDesc = desc.GetOrInsertHClassLayoutDesc(current->GetProfileType().Remap(context), false);
659             current->Convert(context, reinterpret_cast<ChildHClassLayoutDesc *>(childLayoutDesc));
660             last = current;
661         }
662         return desc;
663     }
664 
Size()665     int32_t Size() const
666     {
667         return size_;
668     }
669 
GetType()670     SampleType GetType() const
671     {
672         return type_;
673     }
674 
GetProtoSt()675     SampleType GetProtoSt() const
676     {
677         return protoSt_;
678     }
679 
680 private:
GetRoot()681     const RootHClassLayoutDescInner *GetRoot() const
682     {
683         return &rootHClassLayout_;
684     }
685 
GetNext(const HClassLayoutDescInner * current)686     const ChildHClassLayoutDescInner *GetNext(const HClassLayoutDescInner *current) const
687     {
688         return reinterpret_cast<const ChildHClassLayoutDescInner *>(
689             reinterpret_cast<uintptr_t>(current) + current->Size());
690     }
691 
GetEnd()692     uintptr_t GetEnd() const
693     {
694         return reinterpret_cast<uintptr_t>(this) + Size();
695     }
696 
697     int32_t size_;
698     SampleType type_;
699     SampleType protoSt_;
700     int32_t childCount_ { 0 };
701     RootHClassLayoutDescInner rootHClassLayout_;
702 };
703 
704 using PGOHClassTreeDescInner = PGOHClassTreeTemplate<PGOSampleType>;
705 using PGOHClassTreeDescInnerRef = PGOHClassTreeTemplate<PGOSampleTypeRef>;
706 } // namespace panda::ecmascript::pgo
707 #endif // ECMASCRIPT_PGO_PROFILER_LAYOUT_H
708