• 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(JSTaggedType root, ProfileType rootType);
317     bool DumpForChild(JSTaggedType child, ProfileType childType);
318     bool UpdateForTransition(JSTaggedType parent, ProfileType parentType, JSTaggedType child, ProfileType childType);
319     bool UpdateLayout(JSTaggedType curHClass, ProfileType curType);
320     bool IsDumped(ProfileType curType) const;
321 
322     template<typename Callback>
IterateChilds(Callback callback)323     void IterateChilds(Callback callback) const
324     {
325         IterateAll([&callback] (HClassLayoutDesc *desc) {
326             if (desc->GetProfileType().IsRootType()) {
327                 return;
328             }
329             callback(reinterpret_cast<ChildHClassLayoutDesc *>(desc));
330         });
331     }
332 
333 private:
334     template<typename Callback>
IterateAll(Callback callback)335     void IterateAll(Callback callback) const
336     {
337         for (auto iter : transitionLayout_) {
338             callback(iter.second);
339         }
340     }
341 
342     ProfileType type_;
343     ProfileType protoPt_;
344     CMap<ProfileType, HClassLayoutDesc *> transitionLayout_;
345 };
346 
347 class PGOLayoutDescInfo {
348 public:
349     PGOLayoutDescInfo() = default;
PGOLayoutDescInfo(const CString & key,PGOHandler handler)350     PGOLayoutDescInfo(const CString &key, PGOHandler handler) : handler_(handler)
351     {
352         size_t len = key.size();
353         size_ = Size(len);
354         if (len > 0 && memcpy_s(&key_, len, key.c_str(), len) != EOK) {
355             LOG_ECMA(ERROR) << "SetMethodName memcpy_s failed" << key << ", len = " << len;
356             UNREACHABLE();
357         }
358         *(&key_ + len) = '\0';
359     }
360 
Size(size_t len)361     static int32_t Size(size_t len)
362     {
363         return sizeof(PGOLayoutDescInfo) + AlignUp(len, GetAlignmentInBytes(ALIGN_SIZE));
364     }
365 
Size()366     int32_t Size() const
367     {
368         return size_;
369     }
370 
GetKey()371     const char *GetKey() const
372     {
373         return &key_;
374     }
375 
GetHandler()376     PGOHandler GetHandler() const
377     {
378         return handler_;
379     }
380 
381 private:
382     int32_t size_ {0};
383     PGOHandler handler_;
384     char key_ {'\0'};
385 };
386 
387 class HClassLayoutDescInner {
388 public:
389     virtual ~HClassLayoutDescInner() = default;
Size()390     int32_t Size() const
391     {
392         return size_;
393     }
394 
GetProfileType()395     ProfileType GetProfileType() const
396     {
397         return type_;
398     }
399 
400 protected:
401     int32_t size_ { 0 };
402     ProfileType type_;
403 };
404 
405 class RootHClassLayoutDescInner : public HClassLayoutDescInner {
406 public:
CaculateSize(const RootHClassLayoutDesc & desc)407     static size_t CaculateSize(const RootHClassLayoutDesc &desc)
408     {
409         size_t size = sizeof(RootHClassLayoutDescInner);
410         size += desc.GetChildSize() * sizeof(ProfileType);
411         desc.IterateProps([&size] (const PropertyDesc &propDesc) {
412             auto keyLen = propDesc.first.size();
413             size += static_cast<size_t>(PGOLayoutDescInfo::Size(keyLen));
414         });
415         return size;
416     }
417 
Merge(const RootHClassLayoutDesc & desc)418     void Merge(const RootHClassLayoutDesc &desc)
419     {
420         size_ = static_cast<int32_t>(RootHClassLayoutDescInner::CaculateSize(desc));
421         type_ = desc.GetProfileType();
422         childCount_ = 0;
423         desc.IterateChilds([this] (const ProfileType &childType) -> bool {
424             auto newChildType = const_cast<ProfileType *>(GetChildType(childCount_++));
425             new (newChildType) ProfileType(childType);
426             return true;
427         });
428 
429         auto current = const_cast<PGOLayoutDescInfo *>(GetFirstProperty());
430         desc.IterateProps([this, &current] (const PropertyDesc &propDesc) {
431             auto key = propDesc.first;
432             auto type = propDesc.second;
433             new (current) PGOLayoutDescInfo(key, type);
434             current = const_cast<PGOLayoutDescInfo *>(GetNextProperty(current));
435             propCount_++;
436         });
437     }
438 
Convert(PGOContext & context,RootHClassLayoutDesc * desc)439     void Convert(PGOContext& context, RootHClassLayoutDesc *desc) const
440     {
441         auto descInfo = GetFirstProperty();
442         for (uint32_t i = 0; i < propCount_; i++) {
443             desc->InsertKeyAndDesc(descInfo->GetKey(), descInfo->GetHandler());
444             descInfo = GetNextProperty(descInfo);
445         }
446         for (uint32_t i = 0; i < childCount_; i++) {
447             auto profileType(*GetChildType(i));
448             desc->AddChildHClassLayoutDesc(profileType.Remap(context));
449         }
450     }
451 
SetObjectType(JSType objType)452     void SetObjectType(JSType objType)
453     {
454         objType_ = objType;
455     }
456 
GetObjectType()457     JSType GetObjectType() const
458     {
459         return objType_;
460     }
461 
SetObjectSize(uint32_t size)462     void SetObjectSize(uint32_t size)
463     {
464         objSize_ = size;
465     }
466 
GetObjectSize()467     uint32_t GetObjectSize() const
468     {
469         return objSize_;
470     }
471 
472 private:
GetChildType(uint32_t index)473     const ProfileType *GetChildType(uint32_t index) const
474     {
475         return (&childType_) + index;
476     }
477 
GetFirstProperty()478     const PGOLayoutDescInfo *GetFirstProperty() const
479     {
480         return reinterpret_cast<const PGOLayoutDescInfo *>(reinterpret_cast<uintptr_t>(&childType_ + childCount_));
481     }
482 
GetNextProperty(const PGOLayoutDescInfo * current)483     const PGOLayoutDescInfo *GetNextProperty(const PGOLayoutDescInfo *current) const
484     {
485         return reinterpret_cast<const PGOLayoutDescInfo *>(reinterpret_cast<uintptr_t>(current) + current->Size());
486     }
487 
488     JSType objType_;
489     uint32_t objSize_ {0};
490     uint32_t propCount_ {0};
491     uint32_t childCount_ {0};
492     ProfileType childType_;
493 };
494 
495 class ChildHClassLayoutDescInner : public HClassLayoutDescInner {
496 public:
CaculateSize(const ChildHClassLayoutDesc & desc)497     static size_t CaculateSize(const ChildHClassLayoutDesc &desc)
498     {
499         size_t size = sizeof(ChildHClassLayoutDescInner);
500         size += desc.GetChildSize() * sizeof(ProfileType);
501         auto key = desc.GetPropertyDesc().first;
502         size += static_cast<size_t>(PGOLayoutDescInfo::Size(key.size()));
503         return size;
504     }
505 
Merge(const ChildHClassLayoutDesc & desc)506     void Merge(const ChildHClassLayoutDesc &desc)
507     {
508         size_ = static_cast<int32_t>(ChildHClassLayoutDescInner::CaculateSize(desc));
509         type_ = desc.GetProfileType();
510         childCount_ = 0;
511         desc.IterateChilds([this] (const ProfileType &childType) -> bool {
512             auto newChildType = const_cast<ProfileType *>(GetChildType(childCount_++));
513             new (newChildType) ProfileType(childType);
514             return true;
515         });
516 
517         auto current = const_cast<PGOLayoutDescInfo *>(GetProperty());
518         auto propDesc = desc.GetPropertyDesc();
519         auto key = propDesc.first;
520         auto type = propDesc.second;
521         new (current) PGOLayoutDescInfo(key, type);
522     }
523 
Convert(PGOContext & context,ChildHClassLayoutDesc * desc)524     void Convert(PGOContext& context, ChildHClassLayoutDesc *desc) const
525     {
526         auto descInfo = GetProperty();
527         desc->InsertKeyAndDesc(descInfo->GetKey(), descInfo->GetHandler());
528         for (uint32_t i = 0; i < childCount_; i++) {
529             auto profileType(*GetChildType(i));
530             desc->AddChildHClassLayoutDesc(profileType.Remap(context));
531         }
532     }
533 
534 private:
GetChildType(uint32_t index)535     const ProfileType *GetChildType(uint32_t index) const
536     {
537         return (&childType_) + index;
538     }
539 
GetProperty()540     const PGOLayoutDescInfo *GetProperty() const
541     {
542         return reinterpret_cast<const PGOLayoutDescInfo *>(&childType_ + childCount_);
543     }
544 
545     uint32_t childCount_ { 0 };
546     ProfileType childType_;
547 };
548 
549 template <typename SampleType>
550 class PGOHClassTreeTemplate {
551 public:
PGOHClassTreeTemplate(size_t size,SampleType type,SampleType protoSt)552     PGOHClassTreeTemplate(size_t size, SampleType type, SampleType protoSt)
553         : size_(size), type_(type), protoSt_(protoSt) {}
554 
CaculateSize(const PGOHClassTreeDesc & desc)555     static size_t CaculateSize(const PGOHClassTreeDesc &desc)
556     {
557         auto rootLayout = desc.GetHClassLayoutDesc(desc.GetProfileType());
558         if (rootLayout == nullptr) {
559             return sizeof(PGOHClassTreeTemplate<SampleType>);
560         }
561         if (!rootLayout->IsRoot()) {
562             LOG_ECMA(ERROR) << "rootLayout is not RootHClassLayoutDesc!";
563         }
564         size_t size = sizeof(PGOHClassTreeTemplate<SampleType>) - sizeof(RootHClassLayoutDescInner);
565         size += RootHClassLayoutDescInner::CaculateSize(*reinterpret_cast<const RootHClassLayoutDesc *>(rootLayout));
566 
567         desc.IterateChilds([&size](ChildHClassLayoutDesc *desc) {
568             size += ChildHClassLayoutDescInner::CaculateSize(*desc);
569         });
570         return size;
571     }
572 
GetTypeString(const PGOHClassTreeDesc & desc)573     static std::string GetTypeString(const PGOHClassTreeDesc &desc)
574     {
575         std::string text;
576         text += desc.GetProfileType().GetTypeString();
577         text += DumpUtils::BLOCK_AND_ARRAY_START;
578         auto layoutDesc = desc.GetHClassLayoutDesc(desc.GetProfileType());
579         if (layoutDesc != nullptr) {
580             bool isLayoutFirst = true;
581             ASSERT(layoutDesc->GetProfileType().IsRootType());
582             auto rootLayoutDesc = reinterpret_cast<RootHClassLayoutDesc *>(layoutDesc);
583             rootLayoutDesc->IterateProps([&text, &isLayoutFirst] (const PropertyDesc &propDesc) {
584                 if (!isLayoutFirst) {
585                     text += DumpUtils::TYPE_SEPARATOR + DumpUtils::SPACE;
586                 } else {
587                     text += DumpUtils::ARRAY_START;
588                 }
589                 isLayoutFirst = false;
590                 text += propDesc.first;
591                 text += DumpUtils::BLOCK_START;
592                 text += std::to_string(propDesc.second.GetValue());
593             });
594         }
595         text += (DumpUtils::SPACE + DumpUtils::ARRAY_END);
596         return text;
597     }
598 
Merge(const PGOHClassTreeDesc & desc)599     void Merge(const PGOHClassTreeDesc &desc)
600     {
601         auto root = const_cast<RootHClassLayoutDescInner *>(GetRoot());
602         auto layoutDesc = desc.GetHClassLayoutDesc(desc.GetProfileType());
603         if (layoutDesc == nullptr) {
604             return;
605         }
606         auto rootLayoutDesc = reinterpret_cast<const RootHClassLayoutDesc *>(layoutDesc);
607         root->Merge(*rootLayoutDesc);
608         root->SetObjectType(rootLayoutDesc->GetObjectType());
609         root->SetObjectSize(rootLayoutDesc->GetObjectSize());
610 
611         childCount_ = 0;
612         auto last = reinterpret_cast<HClassLayoutDescInner *>(root);
613         desc.IterateChilds([this, &last](ChildHClassLayoutDesc *desc) {
614             auto current = const_cast<ChildHClassLayoutDescInner *>(GetNext(last));
615             new (current) ChildHClassLayoutDescInner();
616             current->Merge(*desc);
617             last = current;
618             childCount_++;
619         });
620     }
621 
Convert(PGOContext & context)622     PGOHClassTreeDesc Convert(PGOContext& context)
623     {
624         PGOHClassTreeDesc desc(ProfileType(context, GetType().GetProfileType()));
625         desc.SetProtoPt(ProfileType(context, GetProtoSt().GetProfileType()));
626         auto root = GetRoot();
627         if (root->GetProfileType().IsNone()) {
628             return desc;
629         }
630         auto layoutDesc = desc.GetOrInsertHClassLayoutDesc(root->GetProfileType().Remap(context), true);
631         auto rootLayoutDesc = reinterpret_cast<RootHClassLayoutDesc *>(layoutDesc);
632         rootLayoutDesc->SetObjectType(root->GetObjectType());
633         rootLayoutDesc->SetObjectSize(root->GetObjectSize());
634         root->Convert(context, rootLayoutDesc);
635 
636         auto last = reinterpret_cast<const HClassLayoutDescInner *>(root);
637         for (int32_t i = 0; i < childCount_; i++) {
638             auto current = GetNext(last);
639             auto childLayoutDesc = desc.GetOrInsertHClassLayoutDesc(current->GetProfileType().Remap(context), false);
640             current->Convert(context, reinterpret_cast<ChildHClassLayoutDesc *>(childLayoutDesc));
641             last = current;
642         }
643         return desc;
644     }
645 
Size()646     int32_t Size() const
647     {
648         return size_;
649     }
650 
GetType()651     SampleType GetType() const
652     {
653         return type_;
654     }
655 
GetProtoSt()656     SampleType GetProtoSt() const
657     {
658         return protoSt_;
659     }
660 
661 private:
GetRoot()662     const RootHClassLayoutDescInner *GetRoot() const
663     {
664         return &rootHClassLayout_;
665     }
666 
GetNext(const HClassLayoutDescInner * current)667     const ChildHClassLayoutDescInner *GetNext(const HClassLayoutDescInner *current) const
668     {
669         return reinterpret_cast<const ChildHClassLayoutDescInner *>(
670             reinterpret_cast<uintptr_t>(current) + current->Size());
671     }
672 
GetEnd()673     uintptr_t GetEnd() const
674     {
675         return reinterpret_cast<uintptr_t>(this) + Size();
676     }
677 
678     int32_t size_;
679     SampleType type_;
680     SampleType protoSt_;
681     int32_t childCount_ { 0 };
682     RootHClassLayoutDescInner rootHClassLayout_;
683 };
684 
685 using PGOHClassTreeDescInner = PGOHClassTreeTemplate<PGOSampleType>;
686 using PGOHClassTreeDescInnerRef = PGOHClassTreeTemplate<PGOSampleTypeRef>;
687 } // namespace panda::ecmascript::pgo
688 #endif // ECMASCRIPT_PGO_PROFILER_LAYOUT_H
689