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