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, ¤t] (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