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_INFO_H 17#define ECMASCRIPT_PGO_PROFILER_INFO_H 18 19#include <cstdint> 20#include <memory> 21#include <sstream> 22#include <unordered_map> 23#include <unordered_set> 24#include <utility> 25#include <string.h> 26 27#include "ecmascript/common.h" 28#include "ecmascript/jspandafile/method_literal.h" 29#include "ecmascript/log_wrapper.h" 30#include "ecmascript/mem/c_containers.h" 31#include "ecmascript/mem/c_string.h" 32#include "ecmascript/mem/chunk_containers.h" 33#include "ecmascript/mem/native_area_allocator.h" 34#include "ecmascript/mem/slots.h" 35#include "ecmascript/pgo_profiler/ap_file/pgo_file_info.h" 36#include "ecmascript/pgo_profiler/ap_file/pgo_method_type_set.h" 37#include "ecmascript/pgo_profiler/ap_file/pgo_profile_type_pool.h" 38#include "ecmascript/pgo_profiler/ap_file/pgo_proto_transition_type_pool.h" 39#include "ecmascript/pgo_profiler/ap_file/pgo_record_pool.h" 40#include "ecmascript/pgo_profiler/pgo_context.h" 41#include "ecmascript/pgo_profiler/pgo_profiler.h" 42#include "ecmascript/pgo_profiler/pgo_profiler_layout.h" 43#include "ecmascript/pgo_profiler/pgo_utils.h" 44#include "ecmascript/pgo_profiler/types/pgo_profiler_type.h" 45#include "ecmascript/property_attributes.h" 46#include "ecmascript/ts_types/global_type_info.h" 47#include "macros.h" 48 49namespace panda::ecmascript::pgo { 50class SaveTask; 51class PGOContext; 52 53class PGOPandaFileInfos { 54public: 55 void Sample(uint32_t checksum) 56 { 57 fileInfos_.emplace(checksum); 58 } 59 60 void Clear() 61 { 62 fileInfos_.clear(); 63 } 64 65 void ParseFromBinary(void *buffer, SectionInfo *const info); 66 void ProcessToBinary(std::fstream &fileStream, SectionInfo *info) const; 67 void Merge(const PGOPandaFileInfos &pandaFileInfos); 68 bool VerifyChecksum(const PGOPandaFileInfos &pandaFileInfos, const std::string &base, 69 const std::string &incoming) const; 70 71 void ProcessToText(std::ofstream &stream) const; 72 bool ParseFromText(std::ifstream &stream); 73 74 bool Checksum(uint32_t checksum) const; 75 76private: 77 class FileInfo { 78 public: 79 FileInfo() = default; 80 FileInfo(uint32_t checksum) : size_(LastSize()), checksum_(checksum) {} 81 82 static size_t LastSize() 83 { 84 return sizeof(FileInfo); 85 } 86 87 size_t Size() const 88 { 89 return static_cast<size_t>(size_); 90 } 91 92 bool operator<(const FileInfo &right) const 93 { 94 return checksum_ < right.checksum_; 95 } 96 97 uint32_t GetChecksum() const 98 { 99 return checksum_; 100 } 101 102 private: 103 // Support extended fields 104 uint32_t size_; 105 uint32_t checksum_; 106 }; 107 108 std::set<FileInfo> fileInfos_; 109}; 110 111class PGOMethodInfo { 112public: 113 static constexpr int METHOD_INFO_COUNT = 4; 114 static constexpr int METHOD_ID_INDEX = 0; 115 static constexpr int METHOD_COUNT_INDEX = 1; 116 static constexpr int METHOD_MODE_INDEX = 2; 117 static constexpr int METHOD_NAME_INDEX = 3; 118 static constexpr uint32_t METHOD_MAX_HIT_COUNT = 10000U; 119 120 explicit PGOMethodInfo(PGOMethodId id) : id_(id) {} 121 122 PGOMethodInfo(PGOMethodId id, uint32_t count, SampleMode mode, const char *methodName) 123 : id_(id), count_(count), mode_(mode) 124 { 125 size_t len = strlen(methodName); 126 size_ = static_cast<uint32_t>(Size(len)); 127 if (len > 0 && memcpy_s(&methodName_, len, methodName, len) != EOK) { 128 LOG_ECMA(ERROR) << "SetMethodName memcpy_s failed" << methodName << ", len = " << len; 129 UNREACHABLE(); 130 } 131 *(&methodName_ + len) = '\0'; 132 } 133 134 static uint32_t PUBLIC_API CalcChecksum(const char *name, const uint8_t *byteCodeArray, uint32_t byteCodeLength); 135 136 static uint32_t CalcOpCodeChecksum(const uint8_t *byteCodeArray, uint32_t byteCodeLength); 137 138 static int32_t Size(uint32_t length) 139 { 140 return sizeof(PGOMethodInfo) + AlignUp(length, GetAlignmentInBytes(ALIGN_SIZE)); 141 } 142 143 int32_t Size() const 144 { 145 return size_; 146 } 147 148 static bool GetSampleMode(std::string content, SampleMode &mode) 149 { 150 if (content == "HOTNESS_MODE") { 151 mode = SampleMode::HOTNESS_MODE; 152 } else if (content == "CALL_MODE") { 153 mode = SampleMode::CALL_MODE; 154 } else { 155 return false; 156 } 157 return true; 158 } 159 160 void IncreaseCount() 161 { 162 count_++; 163 } 164 165 void ClearCount() 166 { 167 count_ = 0; 168 } 169 170 void Merge(const PGOMethodInfo *info) 171 { 172 if (!(id_ == info->GetMethodId())) { 173 LOG_ECMA(ERROR) << "The method id must same for merging"; 174 return; 175 } 176 count_ = std::min(count_ + info->GetCount(), METHOD_MAX_HIT_COUNT); 177 SetSampleMode(info->GetSampleMode()); 178 } 179 180 PGOMethodId GetMethodId() const 181 { 182 return id_; 183 } 184 185 uint32_t GetCount() const 186 { 187 return count_; 188 } 189 190 const char *GetMethodName() const 191 { 192 return &methodName_; 193 } 194 195 void SetSampleMode(SampleMode mode) 196 { 197 if (mode_ == SampleMode::HOTNESS_MODE) { 198 return; 199 } 200 mode_ = mode; 201 } 202 203 SampleMode GetSampleMode() const 204 { 205 return mode_; 206 } 207 208 std::string GetSampleModeToString() const 209 { 210 std::string result; 211 switch (mode_) { 212 case SampleMode::HOTNESS_MODE: 213 result = "HOTNESS_MODE"; 214 break; 215 case SampleMode::CALL_MODE: 216 result = "CALL_MODE"; 217 break; 218 default: 219 LOG_ECMA(ERROR) << "mode error"; 220 } 221 return result; 222 } 223 224 bool IsFilter(uint32_t threshold) const 225 { 226 if (count_ < threshold && mode_ == SampleMode::CALL_MODE) { 227 return true; 228 } 229 return false; 230 } 231 232 void ParseFromBinary(void **buffer); 233 void ProcessToBinary(std::ofstream &fileStream) const; 234 235 static std::vector<std::string> ParseFromText(const std::string &infoString); 236 void ProcessToText(std::string &text) const; 237 238 void ProcessToJson(ProfileType::VariantMap &function) const; 239 240 NO_COPY_SEMANTIC(PGOMethodInfo); 241 NO_MOVE_SEMANTIC(PGOMethodInfo); 242 243private: 244 uint32_t size_ {0}; 245 PGOMethodId id_; 246 uint32_t count_ {0}; 247 SampleMode mode_ {SampleMode::CALL_MODE}; 248 char methodName_ {0}; 249}; 250 251class PGODecodeMethodInfo { 252public: 253 explicit PGODecodeMethodInfo(PGOMethodId id) : methodId_(id) {} 254 255 PGOMethodId GetMethodId() const 256 { 257 return methodId_; 258 } 259 260 PGOMethodTypeSet &GetPGOMethodTypeSet() 261 { 262 return pgoMethodTypeSet_; 263 } 264 265 void Merge(const PGODecodeMethodInfo &from); 266 267private: 268 PGOMethodId methodId_ {0}; 269 PGOMethodTypeSet pgoMethodTypeSet_ {}; 270}; 271 272class PGOMethodInfoMap { 273public: 274 PGOMethodInfoMap() = default; 275 276 void Clear() 277 { 278 // PGOMethodInfo release by chunk 279 for (auto &entry : methodTypeInfos_) { 280 entry.second->Clear(); 281 } 282 methodInfos_.clear(); 283 methodTypeInfos_.clear(); 284 } 285 286 bool AddMethod(Chunk *chunk, Method *jsMethod, SampleMode mode); 287 bool AddType(Chunk *chunk, PGOMethodId methodId, int32_t offset, PGOSampleType type); 288 bool AddCallTargetType(Chunk *chunk, PGOMethodId methodId, int32_t offset, PGOSampleType type); 289 bool AddObjectInfo(Chunk *chunk, PGOMethodId methodId, int32_t offset, const PGOObjectInfo &info); 290 bool AddDefine(Chunk *chunk, PGOMethodId methodId, int32_t offset, PGODefineOpType type); 291 void Merge(Chunk *chunk, PGOMethodInfoMap *methodInfos); 292 293 bool ParseFromBinary(Chunk *chunk, PGOContext &context, void **buffer); 294 bool ProcessToBinary(PGOContext &context, ProfileTypeRef recordProfileRef, const SaveTask *task, 295 std::fstream &fileStream, PGOProfilerHeader *const header) const; 296 297 bool ParseFromText(Chunk *chunk, uint32_t threshold, const std::vector<std::string> &content); 298 void ProcessToText(uint32_t threshold, const CString &recordName, std::ofstream &stream) const; 299 300 void ProcessToJson(uint32_t threshold, ProfileType::jModuleType &jModule) const; 301 302 const CMap<PGOMethodId, PGOMethodInfo *> &GetMethodInfos() const 303 { 304 return methodInfos_; 305 } 306 307 NO_COPY_SEMANTIC(PGOMethodInfoMap); 308 NO_MOVE_SEMANTIC(PGOMethodInfoMap); 309 310private: 311 PGOMethodTypeSet *GetOrInsertMethodTypeSet(Chunk *chunk, PGOMethodId methodId); 312 313 CMap<PGOMethodId, PGOMethodInfo *> methodInfos_; 314 CMap<PGOMethodId, PGOMethodTypeSet *> methodTypeInfos_; 315 CMap<PGOMethodId, uint32_t> methodsChecksum_; 316 CMap<PGOSampleType, CMap<CString, TrackType>> globalLayoutDescInfos_; 317}; 318 319class PGOMethodIdSet { 320public: 321 explicit PGOMethodIdSet(Chunk* chunk): chunk_(chunk), methodInfoMap_(chunk) {}; 322 ~PGOMethodIdSet() = default; 323 324 void Clear() 325 { 326 candidateSet_.clear(); 327 for (auto &methodNameSet : methodInfoMap_) { 328 methodNameSet.second.Clear(); 329 } 330 methodInfoMap_.clear(); 331 } 332 333 bool Match(EntityId methodId) 334 { 335 return candidateSet_.find(methodId) != candidateSet_.end(); 336 } 337 338 template <typename Callback> 339 bool Update(const CString &recordName, Callback callback) 340 { 341 std::unordered_set<EntityId> newIds = callback(recordName, candidateSet_); 342 if (!newIds.empty()) { 343 candidateSet_.insert(newIds.begin(), newIds.end()); 344 return true; 345 } 346 return false; 347 } 348 349 template <typename Callback> 350 void GetTypeInfo(const char *methodName, Callback callback) 351 { 352 // for no function checksum in ap file 353 auto iter = methodInfoMap_.find(methodName); 354 if ((iter != methodInfoMap_.end()) && (iter->second.GetFirstMethodInfo() != nullptr)) { 355 iter->second.GetFirstMethodInfo()->GetPGOMethodTypeSet().GetTypeInfo(callback); 356 } 357 } 358 359 template <typename Callback> 360 void GetTypeInfo(const char *methodName, uint32_t checksum, Callback callback) 361 { 362 auto iter = methodInfoMap_.find(methodName); 363 if ((iter != methodInfoMap_.end()) && (iter->second.GetMethodInfo(checksum) != nullptr)) { 364 return iter->second.GetMethodInfo(checksum)->GetPGOMethodTypeSet().GetTypeInfo(callback); 365 } 366 LOG_ECMA(DEBUG) << "Method checksum mismatched, name: " << methodName; 367 } 368 369 void MatchAndMarkMethod(const char *methodName, EntityId methodId) 370 { 371 const auto &iter = methodInfoMap_.find(methodName); 372 if (iter == methodInfoMap_.end()) { 373 // no matching method in PGO file. 374 return; 375 } 376 candidateSet_.emplace(methodId); 377 iter->second.SetMatch(); 378 } 379 380 bool ParseFromBinary(PGOContext &context, void **buffer); 381 382 void GetMismatchResult(const CString &recordName, uint32_t &totalMethodCount, uint32_t &mismatchMethodCount, 383 std::set<std::pair<std::string, CString>> &mismatchMethodSet) const; 384 385 void Merge(const PGOMethodIdSet &from); 386 387 class PGOMethodNameSet { 388 public: 389 explicit PGOMethodNameSet(Chunk* chunk): methodMap_(chunk) {}; 390 void SetMatch() 391 { 392 methodNameMatch_ = true; 393 } 394 395 bool IsMatch() const 396 { 397 return methodNameMatch_; 398 } 399 400 PGODecodeMethodInfo& GetOrCreateMethodInfo(uint32_t checksum, PGOMethodId methodId) 401 { 402 auto methodIter = methodMap_.find(checksum); 403 if (methodIter == methodMap_.end()) { 404 auto ret = methodMap_.emplace(checksum, methodId); 405 ASSERT(ret.second); 406 methodIter = ret.first; 407 } 408 return methodIter->second; 409 } 410 411 void Merge(const PGOMethodNameSet &from) 412 { 413 for (const auto &method : from.methodMap_) { 414 uint32_t checksum = method.first; 415 auto methodInfo = methodMap_.find(checksum); 416 if (methodInfo == methodMap_.end()) { 417 auto ret = methodMap_.emplace(checksum, method.second.GetMethodId()); 418 ASSERT(ret.second); 419 methodInfo = ret.first; 420 } 421 methodInfo->second.Merge(method.second); 422 } 423 } 424 425 PGODecodeMethodInfo *GetFirstMethodInfo() 426 { 427 if (methodMap_.empty()) { 428 return nullptr; 429 } 430 return &(methodMap_.begin()->second); 431 } 432 433 PGODecodeMethodInfo *GetMethodInfo(uint32_t checksum) 434 { 435 auto methodInfo = methodMap_.find(checksum); 436 if (methodInfo == methodMap_.end()) { 437 return nullptr; 438 } 439 return &(methodInfo->second); 440 } 441 442 void Clear() 443 { 444 methodMap_.clear(); 445 } 446 447 private: 448 bool methodNameMatch_ {false}; 449 ChunkUnorderedMap<uint32_t, PGODecodeMethodInfo> methodMap_; 450 }; 451 452 NO_COPY_SEMANTIC(PGOMethodIdSet); 453 NO_MOVE_SEMANTIC(PGOMethodIdSet); 454 455private: 456 Chunk* chunk_; 457 std::unordered_set<EntityId> candidateSet_; // methodId in abc file, DO NOT for pgo internal use 458 ChunkUnorderedMap<CString, PGOMethodNameSet> methodInfoMap_; 459}; 460 461class PGORecordDetailInfos : public PGOContext { 462public: 463 explicit PGORecordDetailInfos(uint32_t hotnessThreshold); 464 465 ~PGORecordDetailInfos() override; 466 467 void Clear(); 468 void InitSections(); 469 470 // If it is a new method, return true. 471 bool AddMethod(ProfileType recordProfileType, Method *jsMethod, SampleMode mode); 472 bool AddType(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, PGOSampleType type); 473 bool AddCallTargetType(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, PGOSampleType type); 474 bool AddObjectInfo(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, const PGOObjectInfo &info); 475 bool AddDefine(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, PGODefineOpType type); 476 477 bool AddRwUseInfo(ProfileType rootType); 478 bool AddRootLayout(JSTaggedType hclass, ProfileType rootType); 479 bool UpdateTransitionLayout( 480 ProfileType rootType, JSTaggedType parent, ProfileType parentType, JSTaggedType child, ProfileType childType); 481 bool UpdateLayout(ProfileType rootType, JSTaggedType hclass, ProfileType curType); 482 void AddRootPtType(ProfileType rootType, ProfileType ptType); 483 bool IsDumped(ProfileType rootType, ProfileType curType) const; 484 485 void Merge(const PGORecordDetailInfos &recordInfos); 486 487 void UpdateLayout(); 488 489 bool ParseFromBinary(void *buffer, PGOProfilerHeader *const header); 490 void ProcessToBinary(const SaveTask *task, std::fstream &fileStream, PGOProfilerHeader *const header); 491 492 bool ParseFromText(std::ifstream &stream); 493 void ProcessToText(std::ofstream &stream) const; 494 495 const CMap<ProfileType, PGOMethodInfoMap *> &GetRecordInfos() const 496 { 497 return recordInfos_; 498 } 499 500 std::shared_ptr<PGORecordPool> GetRecordPool() const 501 { 502 return recordPool_; 503 } 504 505 std::shared_ptr<PGOProfileTypePool> GetProfileTypePool() const override 506 { 507 return profileTypePool_; 508 } 509 510 std::shared_ptr<PGOProtoTransitionPool> GetProtoTransitionPool() const 511 { 512 return protoTransitionPool_; 513 } 514 515 uint32_t GetHotnessThreshold() const override 516 { 517 return hotnessThreshold_; 518 } 519 520 PGOProfilerHeader *GetHeader() const override 521 { 522 return header_; 523 } 524 525 bool SupportElementsKind() const override 526 { 527 ASSERT(header_ != nullptr); 528 return header_->SupportElementsKind(); 529 } 530 531 bool SupportElementsTrackInfo() const override 532 { 533 ASSERT(header_ != nullptr); 534 return header_->SupportElementsTrackInfo(); 535 } 536 537 void ResetAbcIdRemap() const override 538 { 539 abcIdRemap_.clear(); 540 } 541 542 void AddAbcIdRemap(ApEntityId oldId, ApEntityId newId) const override 543 { 544 abcIdRemap_[oldId] = newId; 545 } 546 547 const std::map<ApEntityId, ApEntityId> &GetAbcIdRemap() const override 548 { 549 return abcIdRemap_; 550 } 551 552 NO_COPY_SEMANTIC(PGORecordDetailInfos); 553 NO_MOVE_SEMANTIC(PGORecordDetailInfos); 554 555private: 556 PGOMethodInfoMap *GetMethodInfoMap(ProfileType recordProfileType); 557 bool ParseFromBinaryForLayout(void **buffer); 558 bool ProcessToBinaryForLayout(NativeAreaAllocator *allocator, const SaveTask *task, std::fstream &stream); 559 560 uint32_t hotnessThreshold_ {2}; 561 NativeAreaAllocator nativeAreaAllocator_; 562 std::unique_ptr<Chunk> chunk_; 563 CMap<ProfileType, PGOMethodInfoMap *> recordInfos_; 564 std::set<PGOHClassTreeDesc> hclassTreeDescInfos_; 565 PGOProfilerHeader *header_ {nullptr}; 566 std::shared_ptr<PGORecordPool> recordPool_; 567 std::shared_ptr<PGOProtoTransitionPool> protoTransitionPool_; 568 std::shared_ptr<PGOProfileTypePool> profileTypePool_; 569 mutable std::map<ApEntityId, ApEntityId> abcIdRemap_; 570}; 571 572class PGORecordSimpleInfos : public PGOContext { 573public: 574 explicit PGORecordSimpleInfos(uint32_t threshold); 575 576 ~PGORecordSimpleInfos() override; 577 578 void Clear(); 579 580 void InitSections(); 581 582 bool Match(const CString &abcNormalizedDesc, const CString &recordName, EntityId methodId); 583 584 template <typename Callback> 585 void Update(const CString &abcNormalizedDesc, Callback callback) 586 { 587 auto abcMethodIds = methodIds_.find(abcNormalizedDesc); 588 if (abcMethodIds == methodIds_.end()) { 589 return; 590 } 591 for (auto iter = abcMethodIds->second.begin(); iter != abcMethodIds->second.end(); iter++) { 592 auto recordName = iter->first; 593 auto methodIds = iter->second; 594 methodIds->Update(recordName, callback); 595 } 596 } 597 598 template <typename Callback> 599 void Update(const CString &abcNormalizedDesc, const CString &recordName, Callback callback) 600 { 601 auto abcMethodIds = methodIds_.find(abcNormalizedDesc); 602 if (abcMethodIds == methodIds_.end()) { 603 return; 604 } 605 auto iter = abcMethodIds->second.find(recordName); 606 if (iter != abcMethodIds->second.end()) { 607 iter->second->Update(recordName, callback); 608 } else { 609 PGOMethodIdSet *methodIdSet = nativeAreaAllocator_.New<PGOMethodIdSet>(chunk_.get()); 610 if (methodIdSet->Update(recordName, callback)) { 611 abcMethodIds->second.emplace(recordName, methodIdSet); 612 } else { 613 nativeAreaAllocator_.Delete(methodIdSet); 614 } 615 } 616 } 617 618 template <typename Callback> 619 void GetTypeInfo(const CString &abcNormalizedDesc, const CString &recordName, const char *methodName, 620 Callback callback) 621 { 622 auto abcMethodIds = methodIds_.find(abcNormalizedDesc); 623 if (abcMethodIds == methodIds_.end()) { 624 return; 625 } 626 auto iter = abcMethodIds->second.find(recordName); 627 if (iter != abcMethodIds->second.end()) { 628 iter->second->GetTypeInfo(methodName, callback); 629 } 630 } 631 632 template <typename Callback> 633 void GetTypeInfo(const CString &abcNormalizedDesc, const CString &recordName, const char *methodName, 634 uint32_t checksum, Callback callback) 635 { 636 auto abcMethodIds = methodIds_.find(abcNormalizedDesc); 637 if (abcMethodIds == methodIds_.end()) { 638 return; 639 } 640 auto iter = abcMethodIds->second.find(recordName); 641 if (iter != abcMethodIds->second.end()) { 642 iter->second->GetTypeInfo(methodName, checksum, callback); 643 } 644 } 645 646 std::shared_ptr<PGOProtoTransitionPool> GetProtoTransitionPool() const 647 { 648 return protoTransitionPool_; 649 } 650 651 bool GetHClassTreeDesc(PGOSampleType profileType, PGOHClassTreeDesc **desc) const 652 { 653 auto iter = hclassTreeDescInfos_.find(PGOHClassTreeDesc(profileType.GetProfileType())); 654 if (iter != hclassTreeDescInfos_.end()) { 655 *desc = &(const_cast<PGOHClassTreeDesc &>(*iter)); 656 return true; 657 } 658 return false; 659 } 660 661 template <typename Callback> 662 bool IterateHClassTreeDesc(Callback callback) const 663 { 664 for (auto treeDescInfo : hclassTreeDescInfos_) { 665 callback(&treeDescInfo); 666 } 667 return true; 668 } 669 670 template <typename Callback> 671 bool IterateProtoTransitionPool(Callback callback) const 672 { 673 protoTransitionPool_->Iterate(callback); 674 return true; 675 } 676 677 void MatchAndMarkMethod(const CString &abcNormalizedDesc, const CString &recordName, const char *methodName, 678 EntityId methodId) 679 { 680 auto abcMethodIds = methodIds_.find(abcNormalizedDesc); 681 if (abcMethodIds == methodIds_.end()) { 682 return; 683 } 684 auto iter = abcMethodIds->second.find(recordName); 685 if (iter != abcMethodIds->second.end()) { 686 return iter->second->MatchAndMarkMethod(methodName, methodId); 687 } 688 } 689 690 void GetMismatchResult(const CString &abcNormalizedDesc, uint32_t &totalMethodCount, uint32_t &mismatchMethodCount, 691 std::set<std::pair<std::string, CString>> &mismatchMethodSet) const 692 { 693 auto abcMethodIds = methodIds_.find(abcNormalizedDesc); 694 if (abcMethodIds == methodIds_.end()) { 695 return; 696 } 697 for (const auto &methodId : abcMethodIds->second) { 698 methodId.second->GetMismatchResult(methodId.first, totalMethodCount, mismatchMethodCount, 699 mismatchMethodSet); 700 } 701 } 702 703 void ParseFromBinary(void *buffer, PGOProfilerHeader *const header, std::shared_ptr<PGOAbcFilePool> &abcFilePool); 704 705 void Merge(const PGORecordSimpleInfos &simpleInfos); 706 707 std::shared_ptr<PGOProfileTypePool> GetProfileTypePool() const override 708 { 709 return profileTypePool_; 710 } 711 712 uint32_t GetHotnessThreshold() const override 713 { 714 return hotnessThreshold_; 715 } 716 717 PGOProfilerHeader *GetHeader() const override 718 { 719 return header_; 720 } 721 722 bool SupportElementsKind() const override 723 { 724 ASSERT(header_ != nullptr); 725 return header_->SupportElementsKind(); 726 } 727 728 bool SupportElementsTrackInfo() const override 729 { 730 ASSERT(header_ != nullptr); 731 return header_->SupportElementsTrackInfo(); 732 } 733 734 void ResetAbcIdRemap() const override 735 { 736 abcIdRemap_.clear(); 737 } 738 739 const std::map<ApEntityId, ApEntityId> &GetAbcIdRemap() const override 740 { 741 return abcIdRemap_; 742 } 743 744 void AddAbcIdRemap(ApEntityId oldId, ApEntityId newId) const override 745 { 746 abcIdRemap_[oldId] = newId; 747 } 748 749 NO_COPY_SEMANTIC(PGORecordSimpleInfos); 750 NO_MOVE_SEMANTIC(PGORecordSimpleInfos); 751 752private: 753 bool ParseFromBinaryForLayout(void **buffer); 754 755 uint32_t hotnessThreshold_ {2}; 756 NativeAreaAllocator nativeAreaAllocator_; 757 std::unique_ptr<Chunk> chunk_; 758 CUnorderedMap<CString, CUnorderedMap<CString, PGOMethodIdSet *>> methodIds_; 759 PGOProfilerHeader *header_ {nullptr}; 760 // std::list<std::weak_ptr<PGOFileSectionInterface>> apSectionList_; 761 std::shared_ptr<PGORecordPool> recordPool_; 762 std::shared_ptr<PGOProtoTransitionPool> protoTransitionPool_; 763 std::shared_ptr<PGOProfileTypePool> profileTypePool_; 764 std::set<PGOHClassTreeDesc> hclassTreeDescInfos_; 765 mutable std::map<ApEntityId, ApEntityId> abcIdRemap_; 766}; 767} // namespace panda::ecmascript::pgo 768#endif // ECMASCRIPT_PGO_PROFILER_INFO_H 769