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() const53 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() const66 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() const76 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) const100 void GetTypeInfo(const JSPandaFile *jsPandaFile, const CString &recordName, const MethodLiteral *methodLiteral, 101 Callback callback) const 102 { 103 if (!isLoaded_ || !isVerifySuccess_ || methodLiteral == nullptr) { 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 PUBLIC_API GetMismatchResult(const JSPandaFile *jsPandaFile, uint32_t &totalMethodCount, 128 uint32_t &mismatchMethodCount, std::set<std::pair<std::string, CString>> &mismatchMethodSet) const; 129 IsMethodMatchEnabled() const130 bool IsMethodMatchEnabled() const 131 { 132 return header_->SupportMethodChecksum(); 133 } 134 135 bool PUBLIC_API GetHClassTreeDesc(PGOSampleType profileType, PGOHClassTreeDesc **desc) const; 136 137 template <typename Callback> IterateHClassTreeDesc(Callback callback) const138 bool IterateHClassTreeDesc(Callback callback) const 139 { 140 if (!isLoaded_ || !isVerifySuccess_) { 141 return false; 142 } 143 return recordSimpleInfos_->IterateHClassTreeDesc(callback); 144 } 145 146 template <typename Callback> IterateProtoTransitionPool(Callback callback) const147 bool IterateProtoTransitionPool(Callback callback) const 148 { 149 if (!isLoaded_ || !isVerifySuccess_) { 150 return false; 151 } 152 return recordSimpleInfos_->IterateProtoTransitionPool(callback); 153 } 154 IsLoaded() const155 bool IsLoaded() const 156 { 157 return isLoaded_; 158 } 159 GetRecordDetailInfos() const160 PGORecordDetailInfos &GetRecordDetailInfos() const 161 { 162 return *recordDetailInfos_; 163 } 164 GetRecordDetailInfosPtr() const165 std::shared_ptr<PGORecordDetailInfos> GetRecordDetailInfosPtr() const 166 { 167 return recordDetailInfos_; 168 } 169 GetRecordSimpleInfos() const170 PGORecordSimpleInfos &GetRecordSimpleInfos() const 171 { 172 return *recordSimpleInfos_; 173 } 174 GetPandaFileInfos() const175 const PGOPandaFileInfos &GetPandaFileInfos() const 176 { 177 return pandaFileInfos_; 178 } 179 GetAbcNameById(ApEntityId abcId, CString &abcName) const180 bool GetAbcNameById(ApEntityId abcId, CString &abcName) const 181 { 182 ASSERT(header_ != nullptr); 183 if (!header_->SupportProfileTypeWithAbcId()) { 184 return false; 185 } 186 ASSERT(abcFilePool_ != nullptr); 187 ASSERT(abcFilePool_->GetPool() != nullptr); 188 const auto *entry = abcFilePool_->GetPool()->GetEntry(abcId); 189 if (entry == nullptr) { 190 LOG_COMPILER(ERROR) << "Can not find abcId in pgo file. abcId: " << abcId; 191 return false; 192 } 193 abcName = entry->GetData(); 194 return true; 195 } 196 GetABCIdByJSPandaFile(const JSPandaFile *jsPandaFile, ApEntityId &entryId) const197 bool GetABCIdByJSPandaFile(const JSPandaFile *jsPandaFile, ApEntityId &entryId) const 198 { 199 if (abcFilePool_ == nullptr) { 200 return false; 201 } 202 CString name = jsPandaFile->GetNormalizedFileDesc(); 203 return abcFilePool_->GetEntryIdByNormalizedName(name, entryId); 204 } 205 IsCompatibleWithAOTFile()206 bool IsCompatibleWithAOTFile() 207 { 208 // Can be null when AP file path is empty 209 if (header_ == nullptr) { 210 return false; 211 } 212 return header_->IsCompatibleWithAOTFile(); 213 } 214 215 private: 216 bool Load(const std::shared_ptr<PGOAbcFilePool> &externalAbcFilePool); 217 bool Verify(uint32_t checksum); 218 219 bool LoadAPBinaryFile(int prot = PAGE_PROT_READ); 220 void UnLoadAPBinaryFile(); 221 CString PUBLIC_API GetNormalizedFileDesc(const JSPandaFile *jsPandaFile) const; 222 void LoadAbcIdPool(const std::shared_ptr<PGOAbcFilePool> &externalAbcFilePool, PGOContext &context, 223 void *addr); 224 225 bool isLoaded_ {false}; 226 bool isVerifySuccess_ {false}; 227 std::string inPath_; 228 uint32_t hotnessThreshold_ {0}; 229 PGOProfilerHeader *header_ {nullptr}; 230 PGOPandaFileInfos pandaFileInfos_; 231 std::shared_ptr<PGOAbcFilePool> abcFilePool_; 232 bool externalAbcFilePool_ {false}; 233 std::shared_ptr<PGORecordDetailInfos> recordDetailInfos_; 234 std::unique_ptr<PGORecordSimpleInfos> recordSimpleInfos_; 235 MemMap fileMapAddr_; 236 }; 237 } // namespace panda::ecmascript::pgo 238 #endif // ECMASCRIPT_PGO_PROFILE_DECODER_H 239