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