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