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