1 /* 2 * Copyright (c) 2022 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_PROFILE_DECODER_H 17 #define ECMASCRIPT_PGO_PROFILE_DECODER_H 18 19 #include "ecmascript/jspandafile/method_literal.h" 20 #include "ecmascript/log.h" 21 #include "ecmascript/log_wrapper.h" 22 #include "ecmascript/pgo_profiler/pgo_profiler_info.h" 23 #include "ecmascript/pgo_profiler/pgo_utils.h" 24 #include "ecmascript/pgo_profiler/types/pgo_profiler_type.h" 25 #include "ecmascript/platform/map.h" 26 27 namespace panda::ecmascript::pgo { 28 class PGOProfilerDecoder { 29 public: 30 PGOProfilerDecoder() = default; PGOProfilerDecoder(const std::string & inPath,uint32_t hotnessThreshold)31 PGOProfilerDecoder(const std::string &inPath, uint32_t hotnessThreshold) 32 : inPath_(inPath), hotnessThreshold_(hotnessThreshold) {} 33 ~PGOProfilerDecoder()34 virtual ~PGOProfilerDecoder() 35 { 36 Clear(); 37 }; 38 39 NO_COPY_SEMANTIC(PGOProfilerDecoder); 40 NO_MOVE_SEMANTIC(PGOProfilerDecoder); 41 42 bool PUBLIC_API Match(const JSPandaFile *jsPandaFile, const CString &recordName, PGOMethodId methodId); 43 44 bool PUBLIC_API LoadAndVerify(uint32_t checksum, 45 const std::shared_ptr<PGOAbcFilePool> &externalAbcFilePool = nullptr); 46 bool PUBLIC_API LoadFull(const std::shared_ptr<PGOAbcFilePool> &externalAbcFilePool = nullptr); 47 void PUBLIC_API Clear(); 48 49 bool PUBLIC_API SaveAPTextFile(const std::string &outPath); 50 51 void Merge(const PGOProfilerDecoder &decoder); 52 GetAbcFilePool()53 std::shared_ptr<PGOAbcFilePool> GetAbcFilePool() const 54 { 55 return abcFilePool_; 56 } 57 58 bool InitMergeData(); 59 SetInPath(const std::string & inPath)60 void SetInPath(const std::string &inPath) 61 { 62 LOG_COMPILER(INFO) << "Set Profiler paths: " << inPath; 63 inPath_ = inPath; 64 } 65 GetInPath()66 const std::string& GetInPath() const 67 { 68 return inPath_; 69 } 70 SetHotnessThreshold(uint32_t hotnessThreshold)71 void SetHotnessThreshold(uint32_t hotnessThreshold) 72 { 73 hotnessThreshold_ = hotnessThreshold; 74 } 75 GetHotnessThreshold()76 uint32_t GetHotnessThreshold() const 77 { 78 return hotnessThreshold_; 79 } 80 81 template <typename Callback> Update(const JSPandaFile * jsPandaFile,Callback callback)82 void Update(const JSPandaFile *jsPandaFile, Callback callback) 83 { 84 if (!isLoaded_ || !isVerifySuccess_) { 85 return; 86 } 87 recordSimpleInfos_->Update(GetNormalizedFileDesc(jsPandaFile), callback); 88 } 89 90 template <typename Callback> Update(const JSPandaFile * jsPandaFile,const CString & recordName,Callback callback)91 void Update(const JSPandaFile *jsPandaFile, const CString &recordName, Callback callback) 92 { 93 if (!isLoaded_ || !isVerifySuccess_) { 94 return; 95 } 96 recordSimpleInfos_->Update(GetNormalizedFileDesc(jsPandaFile), recordName, callback); 97 } 98 99 template <typename Callback> GetTypeInfo(const JSPandaFile * jsPandaFile,const CString & recordName,const MethodLiteral * methodLiteral,Callback callback)100 void GetTypeInfo(const JSPandaFile *jsPandaFile, const CString &recordName, const MethodLiteral *methodLiteral, 101 Callback callback) const 102 { 103 if (!isLoaded_ || !isVerifySuccess_) { 104 return; 105 } 106 const auto *methodName = MethodLiteral::GetMethodName(jsPandaFile, methodLiteral->GetMethodId()); 107 if (IsMethodMatchEnabled()) { 108 auto checksum = 109 PGOMethodInfo::CalcChecksum(methodName, methodLiteral->GetBytecodeArray(), 110 MethodLiteral::GetCodeSize(jsPandaFile, methodLiteral->GetMethodId())); 111 112 return recordSimpleInfos_->GetTypeInfo(GetNormalizedFileDesc(jsPandaFile), recordName, methodName, checksum, 113 callback); 114 } 115 recordSimpleInfos_->GetTypeInfo(GetNormalizedFileDesc(jsPandaFile), recordName, methodName, callback); 116 } 117 MatchAndMarkMethod(const JSPandaFile * jsPandaFile,const CString & recordName,const char * methodName,EntityId methodId)118 void MatchAndMarkMethod(const JSPandaFile *jsPandaFile, const CString &recordName, const char *methodName, 119 EntityId methodId) 120 { 121 if (!isLoaded_ || !isVerifySuccess_) { 122 return; 123 } 124 recordSimpleInfos_->MatchAndMarkMethod(GetNormalizedFileDesc(jsPandaFile), recordName, methodName, methodId); 125 } 126 127 void GetMismatchResult(const JSPandaFile *jsPandaFile, uint32_t &totalMethodCount, uint32_t &mismatchMethodCount, 128 std::set<std::pair<std::string, CString>> &mismatchMethodSet) const; 129 IsMethodMatchEnabled()130 bool IsMethodMatchEnabled() const 131 { 132 return header_->SupportMethodChecksum(); 133 } 134 135 bool GetHClassTreeDesc(PGOSampleType profileType, PGOHClassTreeDesc **desc) const; 136 137 template <typename Callback> IterateHClassTreeDesc(Callback callback)138 bool IterateHClassTreeDesc(Callback callback) const 139 { 140 if (!isLoaded_ || !isVerifySuccess_) { 141 return false; 142 } 143 return recordSimpleInfos_->IterateHClassTreeDesc(callback); 144 } 145 IsLoaded()146 bool IsLoaded() const 147 { 148 return isLoaded_; 149 } 150 GetRecordDetailInfos()151 PGORecordDetailInfos &GetRecordDetailInfos() const 152 { 153 return *recordDetailInfos_; 154 } 155 GetRecordDetailInfosPtr()156 std::shared_ptr<PGORecordDetailInfos> GetRecordDetailInfosPtr() const 157 { 158 return recordDetailInfos_; 159 } 160 GetRecordSimpleInfos()161 PGORecordSimpleInfos &GetRecordSimpleInfos() const 162 { 163 return *recordSimpleInfos_; 164 } 165 GetPandaFileInfos()166 const PGOPandaFileInfos &GetPandaFileInfos() const 167 { 168 return pandaFileInfos_; 169 } 170 GetAbcNameById(ApEntityId abcId,CString & abcName)171 bool GetAbcNameById(ApEntityId abcId, CString &abcName) const 172 { 173 ASSERT(header_ != nullptr); 174 if (!header_->SupportProfileTypeWithAbcId()) { 175 return false; 176 } 177 ASSERT(abcFilePool_ != nullptr); 178 ASSERT(abcFilePool_->GetPool() != nullptr); 179 const auto *entry = abcFilePool_->GetPool()->GetEntry(abcId); 180 if (entry == nullptr) { 181 LOG_COMPILER(ERROR) << "Can not find abcId in pgo file. abcId: " << abcId; 182 return false; 183 } 184 abcName = entry->GetData(); 185 return true; 186 } 187 GetABCIdByJSPandaFile(const JSPandaFile * jsPandaFile,ApEntityId & entryId)188 bool GetABCIdByJSPandaFile(const JSPandaFile *jsPandaFile, ApEntityId &entryId) const 189 { 190 if (abcFilePool_ == nullptr) { 191 return false; 192 } 193 CString name = jsPandaFile->GetNormalizedFileDesc(); 194 return abcFilePool_->GetEntryIdByNormalizedName(name, entryId); 195 } 196 197 private: 198 bool Load(const std::shared_ptr<PGOAbcFilePool> &externalAbcFilePool); 199 bool Verify(uint32_t checksum); 200 201 bool LoadAPBinaryFile(int prot = PAGE_PROT_READ); 202 void UnLoadAPBinaryFile(); 203 CString GetNormalizedFileDesc(const JSPandaFile *jsPandaFile) const; 204 void LoadAbcIdPool(const std::shared_ptr<PGOAbcFilePool> &externalAbcFilePool, PGOContext &context, 205 void *addr); 206 207 bool isLoaded_ {false}; 208 bool isVerifySuccess_ {false}; 209 std::string inPath_; 210 uint32_t hotnessThreshold_ {0}; 211 PGOProfilerHeader *header_ {nullptr}; 212 PGOPandaFileInfos pandaFileInfos_; 213 std::shared_ptr<PGOAbcFilePool> abcFilePool_; 214 bool externalAbcFilePool_ {false}; 215 std::shared_ptr<PGORecordDetailInfos> recordDetailInfos_; 216 std::unique_ptr<PGORecordSimpleInfos> recordSimpleInfos_; 217 MemMap fileMapAddr_; 218 }; 219 } // namespace panda::ecmascript::pgo 220 #endif // ECMASCRIPT_PGO_PROFILE_DECODER_H 221