• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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