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