14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/pgo_profiler/pgo_profiler_info.h" 174514f5e3Sopenharmony_ci#include <cstdint> 184514f5e3Sopenharmony_ci#include <fstream> 194514f5e3Sopenharmony_ci#include <iomanip> 204514f5e3Sopenharmony_ci#include <memory> 214514f5e3Sopenharmony_ci#include <utility> 224514f5e3Sopenharmony_ci#include "ecmascript/js_thread.h" 234514f5e3Sopenharmony_ci#include "ecmascript/ohos/framework_helper.h" 244514f5e3Sopenharmony_ci#include "ecmascript/pgo_profiler/pgo_profiler_manager.h" 254514f5e3Sopenharmony_ci#include "libpandafile/bytecode_instruction-inl.h" 264514f5e3Sopenharmony_ci 274514f5e3Sopenharmony_cinamespace panda::ecmascript::pgo { 284514f5e3Sopenharmony_ciusing StringHelper = base::StringHelper; 294514f5e3Sopenharmony_civoid PGOPandaFileInfos::ParseFromBinary(void *buffer, SectionInfo *const info) 304514f5e3Sopenharmony_ci{ 314514f5e3Sopenharmony_ci void *addr = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + info->offset_); 324514f5e3Sopenharmony_ci for (uint32_t i = 0; i < info->number_; i++) { 334514f5e3Sopenharmony_ci fileInfos_.emplace(*base::ReadBufferInSize<FileInfo>(&addr)); 344514f5e3Sopenharmony_ci } 354514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "Profiler panda file count:" << info->number_; 364514f5e3Sopenharmony_ci} 374514f5e3Sopenharmony_ci 384514f5e3Sopenharmony_civoid PGOPandaFileInfos::ProcessToBinary(std::fstream &fileStream, SectionInfo *info) const 394514f5e3Sopenharmony_ci{ 404514f5e3Sopenharmony_ci fileStream.seekp(info->offset_); 414514f5e3Sopenharmony_ci info->number_ = fileInfos_.size(); 424514f5e3Sopenharmony_ci for (auto localInfo : fileInfos_) { 434514f5e3Sopenharmony_ci fileStream.write(reinterpret_cast<char *>(&localInfo), localInfo.Size()); 444514f5e3Sopenharmony_ci } 454514f5e3Sopenharmony_ci info->size_ = static_cast<uint32_t>(fileStream.tellp()) - info->offset_; 464514f5e3Sopenharmony_ci} 474514f5e3Sopenharmony_ci 484514f5e3Sopenharmony_civoid PGOPandaFileInfos::Merge(const PGOPandaFileInfos &pandaFileInfos) 494514f5e3Sopenharmony_ci{ 504514f5e3Sopenharmony_ci for (const auto &info : pandaFileInfos.fileInfos_) { 514514f5e3Sopenharmony_ci fileInfos_.emplace(info.GetChecksum()); 524514f5e3Sopenharmony_ci } 534514f5e3Sopenharmony_ci} 544514f5e3Sopenharmony_ci 554514f5e3Sopenharmony_cibool PGOPandaFileInfos::VerifyChecksum(const PGOPandaFileInfos &pandaFileInfos, const std::string &base, 564514f5e3Sopenharmony_ci const std::string &incoming) const 574514f5e3Sopenharmony_ci{ 584514f5e3Sopenharmony_ci std::set<FileInfo> unionChecksum; 594514f5e3Sopenharmony_ci set_union(fileInfos_.begin(), fileInfos_.end(), pandaFileInfos.fileInfos_.begin(), pandaFileInfos.fileInfos_.end(), 604514f5e3Sopenharmony_ci inserter(unionChecksum, unionChecksum.begin())); 614514f5e3Sopenharmony_ci if (!fileInfos_.empty() && unionChecksum.empty()) { 624514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "First AP file(" << base << ") and the incoming file(" << incoming 634514f5e3Sopenharmony_ci << ") do not come from the same abc file, skip merge the incoming file."; 644514f5e3Sopenharmony_ci return false; 654514f5e3Sopenharmony_ci } 664514f5e3Sopenharmony_ci return true; 674514f5e3Sopenharmony_ci} 684514f5e3Sopenharmony_ci 694514f5e3Sopenharmony_cibool PGOPandaFileInfos::ParseFromText(std::ifstream &stream) 704514f5e3Sopenharmony_ci{ 714514f5e3Sopenharmony_ci std::string pandaFileInfo; 724514f5e3Sopenharmony_ci while (std::getline(stream, pandaFileInfo)) { 734514f5e3Sopenharmony_ci if (pandaFileInfo.empty()) { 744514f5e3Sopenharmony_ci continue; 754514f5e3Sopenharmony_ci } 764514f5e3Sopenharmony_ci 774514f5e3Sopenharmony_ci size_t start = pandaFileInfo.find_first_of(DumpUtils::ARRAY_START); 784514f5e3Sopenharmony_ci size_t end = pandaFileInfo.find_last_of(DumpUtils::ARRAY_END); 794514f5e3Sopenharmony_ci if (start == std::string::npos || end == std::string::npos || start >= end) { 804514f5e3Sopenharmony_ci return false; 814514f5e3Sopenharmony_ci } 824514f5e3Sopenharmony_ci auto content = pandaFileInfo.substr(start + 1, end - (start + 1) - 1); 834514f5e3Sopenharmony_ci std::vector<std::string> infos = StringHelper::SplitString(content, DumpUtils::BLOCK_SEPARATOR); 844514f5e3Sopenharmony_ci for (auto checksum : infos) { 854514f5e3Sopenharmony_ci uint32_t result; 864514f5e3Sopenharmony_ci if (!StringHelper::StrToUInt32(checksum.c_str(), &result)) { 874514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "checksum: " << checksum << " parse failed"; 884514f5e3Sopenharmony_ci return false; 894514f5e3Sopenharmony_ci } 904514f5e3Sopenharmony_ci Sample(result); 914514f5e3Sopenharmony_ci } 924514f5e3Sopenharmony_ci return true; 934514f5e3Sopenharmony_ci } 944514f5e3Sopenharmony_ci return true; 954514f5e3Sopenharmony_ci} 964514f5e3Sopenharmony_ci 974514f5e3Sopenharmony_civoid PGOPandaFileInfos::ProcessToText(std::ofstream &stream) const 984514f5e3Sopenharmony_ci{ 994514f5e3Sopenharmony_ci std::string pandaFileInfo = DumpUtils::NEW_LINE + DumpUtils::PANDA_FILE_INFO_HEADER; 1004514f5e3Sopenharmony_ci bool isFirst = true; 1014514f5e3Sopenharmony_ci for (auto &info : fileInfos_) { 1024514f5e3Sopenharmony_ci if (!isFirst) { 1034514f5e3Sopenharmony_ci pandaFileInfo += DumpUtils::BLOCK_SEPARATOR + DumpUtils::SPACE; 1044514f5e3Sopenharmony_ci } else { 1054514f5e3Sopenharmony_ci isFirst = false; 1064514f5e3Sopenharmony_ci } 1074514f5e3Sopenharmony_ci pandaFileInfo += std::to_string(info.GetChecksum()); 1084514f5e3Sopenharmony_ci } 1094514f5e3Sopenharmony_ci 1104514f5e3Sopenharmony_ci pandaFileInfo += (DumpUtils::SPACE + DumpUtils::ARRAY_END + DumpUtils::NEW_LINE); 1114514f5e3Sopenharmony_ci stream << pandaFileInfo; 1124514f5e3Sopenharmony_ci} 1134514f5e3Sopenharmony_ci 1144514f5e3Sopenharmony_cibool PGOPandaFileInfos::Checksum(uint32_t checksum) const 1154514f5e3Sopenharmony_ci{ 1164514f5e3Sopenharmony_ci if (fileInfos_.find(checksum) == fileInfos_.end()) { 1174514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Checksum verification failed. Please ensure that the .abc and .ap match."; 1184514f5e3Sopenharmony_ci return false; 1194514f5e3Sopenharmony_ci } 1204514f5e3Sopenharmony_ci return true; 1214514f5e3Sopenharmony_ci} 1224514f5e3Sopenharmony_ci 1234514f5e3Sopenharmony_civoid PGOMethodInfo::ProcessToText(std::string &text) const 1244514f5e3Sopenharmony_ci{ 1254514f5e3Sopenharmony_ci text += std::to_string(GetMethodId().GetOffset()); 1264514f5e3Sopenharmony_ci text += DumpUtils::ELEMENT_SEPARATOR; 1274514f5e3Sopenharmony_ci text += std::to_string(GetCount()); 1284514f5e3Sopenharmony_ci text += DumpUtils::ELEMENT_SEPARATOR; 1294514f5e3Sopenharmony_ci text += GetSampleModeToString(); 1304514f5e3Sopenharmony_ci text += DumpUtils::ELEMENT_SEPARATOR; 1314514f5e3Sopenharmony_ci text += GetMethodName(); 1324514f5e3Sopenharmony_ci} 1334514f5e3Sopenharmony_ci 1344514f5e3Sopenharmony_civoid PGOMethodInfo::ProcessToJson(ProfileType::VariantMap &function) const 1354514f5e3Sopenharmony_ci{ 1364514f5e3Sopenharmony_ci std::string methodName = GetMethodName(); 1374514f5e3Sopenharmony_ci std::string functionName = methodName + "(" + std::to_string(GetMethodId().GetOffset()) + ")"; 1384514f5e3Sopenharmony_ci function.insert(std::make_pair(DumpJsonUtils::FUNCTION_NAME, functionName)); 1394514f5e3Sopenharmony_ci} 1404514f5e3Sopenharmony_ci 1414514f5e3Sopenharmony_cistd::vector<std::string> PGOMethodInfo::ParseFromText(const std::string &infoString) 1424514f5e3Sopenharmony_ci{ 1434514f5e3Sopenharmony_ci std::vector<std::string> infoStrings = StringHelper::SplitString(infoString, DumpUtils::ELEMENT_SEPARATOR); 1444514f5e3Sopenharmony_ci return infoStrings; 1454514f5e3Sopenharmony_ci} 1464514f5e3Sopenharmony_ci 1474514f5e3Sopenharmony_ciuint32_t PGOMethodInfo::CalcChecksum(const char *name, const uint8_t *byteCodeArray, uint32_t byteCodeLength) 1484514f5e3Sopenharmony_ci{ 1494514f5e3Sopenharmony_ci uint32_t checksum = 0; 1504514f5e3Sopenharmony_ci if (byteCodeArray != nullptr) { 1514514f5e3Sopenharmony_ci checksum = CalcOpCodeChecksum(byteCodeArray, byteCodeLength); 1524514f5e3Sopenharmony_ci } 1534514f5e3Sopenharmony_ci 1544514f5e3Sopenharmony_ci if (name != nullptr) { 1554514f5e3Sopenharmony_ci checksum = adler32(checksum, reinterpret_cast<const Bytef *>(name), strlen(name)); 1564514f5e3Sopenharmony_ci } 1574514f5e3Sopenharmony_ci return checksum; 1584514f5e3Sopenharmony_ci} 1594514f5e3Sopenharmony_ci 1604514f5e3Sopenharmony_ciuint32_t PGOMethodInfo::CalcOpCodeChecksum(const uint8_t *byteCodeArray, uint32_t byteCodeLength) 1614514f5e3Sopenharmony_ci{ 1624514f5e3Sopenharmony_ci uint32_t checksum = 0; 1634514f5e3Sopenharmony_ci BytecodeInstruction bcIns(byteCodeArray); 1644514f5e3Sopenharmony_ci auto bcInsLast = bcIns.JumpTo(byteCodeLength); 1654514f5e3Sopenharmony_ci while (bcIns.GetAddress() != bcInsLast.GetAddress()) { 1664514f5e3Sopenharmony_ci auto opCode = bcIns.GetOpcode(); 1674514f5e3Sopenharmony_ci checksum = adler32(checksum, reinterpret_cast<const Bytef *>(&opCode), sizeof(decltype(opCode))); 1684514f5e3Sopenharmony_ci bcIns = bcIns.GetNext(); 1694514f5e3Sopenharmony_ci } 1704514f5e3Sopenharmony_ci return checksum; 1714514f5e3Sopenharmony_ci} 1724514f5e3Sopenharmony_ci 1734514f5e3Sopenharmony_cibool PGOMethodInfoMap::AddMethod(Chunk *chunk, Method *jsMethod, SampleMode mode) 1744514f5e3Sopenharmony_ci{ 1754514f5e3Sopenharmony_ci PGOMethodId methodId(jsMethod->GetMethodId()); 1764514f5e3Sopenharmony_ci auto result = methodInfos_.find(methodId); 1774514f5e3Sopenharmony_ci if (result != methodInfos_.end()) { 1784514f5e3Sopenharmony_ci auto info = result->second; 1794514f5e3Sopenharmony_ci info->IncreaseCount(); 1804514f5e3Sopenharmony_ci info->SetSampleMode(mode); 1814514f5e3Sopenharmony_ci return false; 1824514f5e3Sopenharmony_ci } else { 1834514f5e3Sopenharmony_ci CString methodName = jsMethod->GetMethodName(); 1844514f5e3Sopenharmony_ci size_t strlen = methodName.size(); 1854514f5e3Sopenharmony_ci size_t size = static_cast<size_t>(PGOMethodInfo::Size(strlen)); 1864514f5e3Sopenharmony_ci void *infoAddr = chunk->Allocate(size); 1874514f5e3Sopenharmony_ci if (infoAddr == nullptr) { 1884514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "infoAddr is null!"; 1894514f5e3Sopenharmony_ci return false; 1904514f5e3Sopenharmony_ci } 1914514f5e3Sopenharmony_ci auto info = new (infoAddr) PGOMethodInfo(methodId, 0, mode, methodName.c_str()); 1924514f5e3Sopenharmony_ci info->IncreaseCount(); 1934514f5e3Sopenharmony_ci methodInfos_.emplace(methodId, info); 1944514f5e3Sopenharmony_ci auto checksum = PGOMethodInfo::CalcChecksum(jsMethod->GetMethodName(), jsMethod->GetBytecodeArray(), 1954514f5e3Sopenharmony_ci jsMethod->GetCodeSize()); 1964514f5e3Sopenharmony_ci methodsChecksum_.emplace(methodId, checksum); 1974514f5e3Sopenharmony_ci return true; 1984514f5e3Sopenharmony_ci } 1994514f5e3Sopenharmony_ci} 2004514f5e3Sopenharmony_ci 2014514f5e3Sopenharmony_ciPGOMethodTypeSet *PGOMethodInfoMap::GetOrInsertMethodTypeSet(Chunk *chunk, PGOMethodId methodId) 2024514f5e3Sopenharmony_ci{ 2034514f5e3Sopenharmony_ci auto typeInfoSetIter = methodTypeInfos_.find(methodId); 2044514f5e3Sopenharmony_ci if (typeInfoSetIter != methodTypeInfos_.end()) { 2054514f5e3Sopenharmony_ci return typeInfoSetIter->second; 2064514f5e3Sopenharmony_ci } else { 2074514f5e3Sopenharmony_ci auto typeInfoSet = chunk->New<PGOMethodTypeSet>(); 2084514f5e3Sopenharmony_ci methodTypeInfos_.emplace(methodId, typeInfoSet); 2094514f5e3Sopenharmony_ci return typeInfoSet; 2104514f5e3Sopenharmony_ci } 2114514f5e3Sopenharmony_ci} 2124514f5e3Sopenharmony_ci 2134514f5e3Sopenharmony_cibool PGOMethodInfoMap::AddType(Chunk *chunk, PGOMethodId methodId, int32_t offset, PGOSampleType type) 2144514f5e3Sopenharmony_ci{ 2154514f5e3Sopenharmony_ci auto typeInfoSet = GetOrInsertMethodTypeSet(chunk, methodId); 2164514f5e3Sopenharmony_ci ASSERT(typeInfoSet != nullptr); 2174514f5e3Sopenharmony_ci typeInfoSet->AddType(offset, type); 2184514f5e3Sopenharmony_ci return true; 2194514f5e3Sopenharmony_ci} 2204514f5e3Sopenharmony_ci 2214514f5e3Sopenharmony_cibool PGOMethodInfoMap::AddCallTargetType(Chunk *chunk, PGOMethodId methodId, int32_t offset, PGOSampleType type) 2224514f5e3Sopenharmony_ci{ 2234514f5e3Sopenharmony_ci auto typeInfoSet = GetOrInsertMethodTypeSet(chunk, methodId); 2244514f5e3Sopenharmony_ci ASSERT(typeInfoSet != nullptr); 2254514f5e3Sopenharmony_ci typeInfoSet->AddCallTargetType(offset, type); 2264514f5e3Sopenharmony_ci return true; 2274514f5e3Sopenharmony_ci} 2284514f5e3Sopenharmony_ci 2294514f5e3Sopenharmony_cibool PGOMethodInfoMap::AddObjectInfo(Chunk *chunk, PGOMethodId methodId, int32_t offset, const PGOObjectInfo &info) 2304514f5e3Sopenharmony_ci{ 2314514f5e3Sopenharmony_ci auto typeInfoSet = GetOrInsertMethodTypeSet(chunk, methodId); 2324514f5e3Sopenharmony_ci ASSERT(typeInfoSet != nullptr); 2334514f5e3Sopenharmony_ci typeInfoSet->AddObjectInfo(offset, info); 2344514f5e3Sopenharmony_ci return true; 2354514f5e3Sopenharmony_ci} 2364514f5e3Sopenharmony_ci 2374514f5e3Sopenharmony_cibool PGOMethodInfoMap::AddDefine(Chunk *chunk, PGOMethodId methodId, int32_t offset, PGODefineOpType type) 2384514f5e3Sopenharmony_ci{ 2394514f5e3Sopenharmony_ci auto typeInfoSet = GetOrInsertMethodTypeSet(chunk, methodId); 2404514f5e3Sopenharmony_ci ASSERT(typeInfoSet != nullptr); 2414514f5e3Sopenharmony_ci typeInfoSet->AddDefine(offset, type); 2424514f5e3Sopenharmony_ci return true; 2434514f5e3Sopenharmony_ci} 2444514f5e3Sopenharmony_ci 2454514f5e3Sopenharmony_civoid PGOMethodInfoMap::Merge(Chunk *chunk, PGOMethodInfoMap *methodInfos) 2464514f5e3Sopenharmony_ci{ 2474514f5e3Sopenharmony_ci for (auto iter = methodInfos->methodInfos_.begin(); iter != methodInfos->methodInfos_.end(); iter++) { 2484514f5e3Sopenharmony_ci auto methodId = iter->first; 2494514f5e3Sopenharmony_ci auto fromMethodInfo = iter->second; 2504514f5e3Sopenharmony_ci 2514514f5e3Sopenharmony_ci auto result = methodInfos_.find(methodId); 2524514f5e3Sopenharmony_ci if (result != methodInfos_.end()) { 2534514f5e3Sopenharmony_ci auto toMethodInfo = result->second; 2544514f5e3Sopenharmony_ci toMethodInfo->Merge(fromMethodInfo); 2554514f5e3Sopenharmony_ci } else { 2564514f5e3Sopenharmony_ci size_t len = strlen(fromMethodInfo->GetMethodName()); 2574514f5e3Sopenharmony_ci size_t size = static_cast<size_t>(PGOMethodInfo::Size(len)); 2584514f5e3Sopenharmony_ci void *infoAddr = chunk->Allocate(size); 2594514f5e3Sopenharmony_ci auto newMethodInfo = new (infoAddr) PGOMethodInfo( 2604514f5e3Sopenharmony_ci methodId, fromMethodInfo->GetCount(), fromMethodInfo->GetSampleMode(), fromMethodInfo->GetMethodName()); 2614514f5e3Sopenharmony_ci methodInfos_.emplace(methodId, newMethodInfo); 2624514f5e3Sopenharmony_ci } 2634514f5e3Sopenharmony_ci fromMethodInfo->ClearCount(); 2644514f5e3Sopenharmony_ci } 2654514f5e3Sopenharmony_ci 2664514f5e3Sopenharmony_ci for (auto iter = methodInfos->methodTypeInfos_.begin(); iter != methodInfos->methodTypeInfos_.end(); iter++) { 2674514f5e3Sopenharmony_ci auto methodId = iter->first; 2684514f5e3Sopenharmony_ci auto fromTypeInfo = iter->second; 2694514f5e3Sopenharmony_ci 2704514f5e3Sopenharmony_ci auto result = methodTypeInfos_.find(methodId); 2714514f5e3Sopenharmony_ci if (result != methodTypeInfos_.end()) { 2724514f5e3Sopenharmony_ci auto toTypeInfo = result->second; 2734514f5e3Sopenharmony_ci toTypeInfo->Merge(fromTypeInfo); 2744514f5e3Sopenharmony_ci } else { 2754514f5e3Sopenharmony_ci auto typeInfoSet = chunk->New<PGOMethodTypeSet>(); 2764514f5e3Sopenharmony_ci typeInfoSet->Merge(fromTypeInfo); 2774514f5e3Sopenharmony_ci methodTypeInfos_.emplace(methodId, typeInfoSet); 2784514f5e3Sopenharmony_ci } 2794514f5e3Sopenharmony_ci } 2804514f5e3Sopenharmony_ci 2814514f5e3Sopenharmony_ci for (auto iter = methodInfos->methodsChecksum_.begin(); iter != methodInfos->methodsChecksum_.end(); iter++) { 2824514f5e3Sopenharmony_ci auto methodId = iter->first; 2834514f5e3Sopenharmony_ci auto result = methodsChecksum_.find(methodId); 2844514f5e3Sopenharmony_ci if (result == methodsChecksum_.end()) { 2854514f5e3Sopenharmony_ci methodsChecksum_.emplace(methodId, iter->second); 2864514f5e3Sopenharmony_ci } 2874514f5e3Sopenharmony_ci } 2884514f5e3Sopenharmony_ci} 2894514f5e3Sopenharmony_ci 2904514f5e3Sopenharmony_cibool PGOMethodInfoMap::ParseFromBinary(Chunk *chunk, PGOContext &context, void **buffer) 2914514f5e3Sopenharmony_ci{ 2924514f5e3Sopenharmony_ci PGOProfilerHeader *const header = context.GetHeader(); 2934514f5e3Sopenharmony_ci ASSERT(header != nullptr); 2944514f5e3Sopenharmony_ci SectionInfo secInfo = base::ReadBuffer<SectionInfo>(buffer); 2954514f5e3Sopenharmony_ci for (uint32_t j = 0; j < secInfo.number_; j++) { 2964514f5e3Sopenharmony_ci PGOMethodInfo *info = base::ReadBufferInSize<PGOMethodInfo>(buffer); 2974514f5e3Sopenharmony_ci if (info->IsFilter(context.GetHotnessThreshold())) { 2984514f5e3Sopenharmony_ci if (header->SupportMethodChecksum()) { 2994514f5e3Sopenharmony_ci base::ReadBuffer<uint32_t>(buffer, sizeof(uint32_t)); 3004514f5e3Sopenharmony_ci } 3014514f5e3Sopenharmony_ci if (header->SupportType()) { 3024514f5e3Sopenharmony_ci PGOMethodTypeSet::SkipFromBinary(buffer); 3034514f5e3Sopenharmony_ci } 3044514f5e3Sopenharmony_ci continue; 3054514f5e3Sopenharmony_ci } 3064514f5e3Sopenharmony_ci methodInfos_.emplace(info->GetMethodId(), info); 3074514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "Method:" << info->GetMethodId() << DumpUtils::ELEMENT_SEPARATOR << info->GetCount() 3084514f5e3Sopenharmony_ci << DumpUtils::ELEMENT_SEPARATOR << std::to_string(static_cast<int>(info->GetSampleMode())) 3094514f5e3Sopenharmony_ci << DumpUtils::ELEMENT_SEPARATOR << info->GetMethodName(); 3104514f5e3Sopenharmony_ci if (header->SupportMethodChecksum()) { 3114514f5e3Sopenharmony_ci auto checksum = base::ReadBuffer<uint32_t>(buffer, sizeof(uint32_t)); 3124514f5e3Sopenharmony_ci methodsChecksum_.emplace(info->GetMethodId(), checksum); 3134514f5e3Sopenharmony_ci } 3144514f5e3Sopenharmony_ci if (header->SupportType()) { 3154514f5e3Sopenharmony_ci auto typeInfoSet = chunk->New<PGOMethodTypeSet>(); 3164514f5e3Sopenharmony_ci typeInfoSet->ParseFromBinary(context, buffer); 3174514f5e3Sopenharmony_ci methodTypeInfos_.emplace(info->GetMethodId(), typeInfoSet); 3184514f5e3Sopenharmony_ci } 3194514f5e3Sopenharmony_ci } 3204514f5e3Sopenharmony_ci return !methodInfos_.empty(); 3214514f5e3Sopenharmony_ci} 3224514f5e3Sopenharmony_ci 3234514f5e3Sopenharmony_cibool PGOMethodInfoMap::ProcessToBinary(PGOContext &context, ProfileTypeRef recordProfileRef, const SaveTask *task, 3244514f5e3Sopenharmony_ci std::fstream &stream, PGOProfilerHeader *const header) const 3254514f5e3Sopenharmony_ci{ 3264514f5e3Sopenharmony_ci SectionInfo secInfo; 3274514f5e3Sopenharmony_ci std::stringstream methodStream; 3284514f5e3Sopenharmony_ci for (auto iter = methodInfos_.begin(); iter != methodInfos_.end(); iter++) { 3294514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "Method:" << iter->first << DumpUtils::ELEMENT_SEPARATOR << iter->second->GetCount() 3304514f5e3Sopenharmony_ci << DumpUtils::ELEMENT_SEPARATOR 3314514f5e3Sopenharmony_ci << std::to_string(static_cast<int>(iter->second->GetSampleMode())) 3324514f5e3Sopenharmony_ci << DumpUtils::ELEMENT_SEPARATOR << iter->second->GetMethodName(); 3334514f5e3Sopenharmony_ci if (task && task->IsTerminate()) { 3344514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "ProcessProfile: task is already terminate"; 3354514f5e3Sopenharmony_ci return false; 3364514f5e3Sopenharmony_ci } 3374514f5e3Sopenharmony_ci auto curMethodInfo = iter->second; 3384514f5e3Sopenharmony_ci if (curMethodInfo->IsFilter(context.GetHotnessThreshold())) { 3394514f5e3Sopenharmony_ci continue; 3404514f5e3Sopenharmony_ci } 3414514f5e3Sopenharmony_ci methodStream.write(reinterpret_cast<char *>(curMethodInfo), curMethodInfo->Size()); 3424514f5e3Sopenharmony_ci if (header->SupportMethodChecksum()) { 3434514f5e3Sopenharmony_ci auto checksumIter = methodsChecksum_.find(curMethodInfo->GetMethodId()); 3444514f5e3Sopenharmony_ci uint32_t checksum = 0; 3454514f5e3Sopenharmony_ci if (checksumIter != methodsChecksum_.end()) { 3464514f5e3Sopenharmony_ci checksum = checksumIter->second; 3474514f5e3Sopenharmony_ci } 3484514f5e3Sopenharmony_ci methodStream.write(reinterpret_cast<char *>(&checksum), sizeof(uint32_t)); 3494514f5e3Sopenharmony_ci } 3504514f5e3Sopenharmony_ci if (header->SupportType()) { 3514514f5e3Sopenharmony_ci auto typeInfoIter = methodTypeInfos_.find(curMethodInfo->GetMethodId()); 3524514f5e3Sopenharmony_ci if (typeInfoIter != methodTypeInfos_.end()) { 3534514f5e3Sopenharmony_ci typeInfoIter->second->ProcessToBinary(context, methodStream); 3544514f5e3Sopenharmony_ci } else { 3554514f5e3Sopenharmony_ci uint32_t number = 0; 3564514f5e3Sopenharmony_ci methodStream.write(reinterpret_cast<char *>(&number), sizeof(uint32_t)); 3574514f5e3Sopenharmony_ci } 3584514f5e3Sopenharmony_ci } 3594514f5e3Sopenharmony_ci secInfo.number_++; 3604514f5e3Sopenharmony_ci } 3614514f5e3Sopenharmony_ci if (secInfo.number_ > 0) { 3624514f5e3Sopenharmony_ci secInfo.offset_ = sizeof(SectionInfo); 3634514f5e3Sopenharmony_ci secInfo.size_ = static_cast<uint32_t>(methodStream.tellp()); 3644514f5e3Sopenharmony_ci stream.write(reinterpret_cast<char *>(&recordProfileRef), sizeof(uint32_t)); 3654514f5e3Sopenharmony_ci stream.write(reinterpret_cast<char *>(&secInfo), sizeof(SectionInfo)); 3664514f5e3Sopenharmony_ci stream << methodStream.rdbuf(); 3674514f5e3Sopenharmony_ci return true; 3684514f5e3Sopenharmony_ci } 3694514f5e3Sopenharmony_ci return false; 3704514f5e3Sopenharmony_ci} 3714514f5e3Sopenharmony_ci 3724514f5e3Sopenharmony_cibool PGOMethodInfoMap::ParseFromText(Chunk *chunk, uint32_t threshold, const std::vector<std::string> &content) 3734514f5e3Sopenharmony_ci{ 3744514f5e3Sopenharmony_ci for (auto infoString : content) { 3754514f5e3Sopenharmony_ci std::vector<std::string> infoStrings = PGOMethodInfo::ParseFromText(infoString); 3764514f5e3Sopenharmony_ci if (infoStrings.size() < PGOMethodInfo::METHOD_INFO_COUNT) { 3774514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "method info:" << infoString << " format error"; 3784514f5e3Sopenharmony_ci return false; 3794514f5e3Sopenharmony_ci } 3804514f5e3Sopenharmony_ci uint32_t count; 3814514f5e3Sopenharmony_ci if (!StringHelper::StrToUInt32(infoStrings[PGOMethodInfo::METHOD_COUNT_INDEX].c_str(), &count)) { 3824514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "count: " << infoStrings[PGOMethodInfo::METHOD_COUNT_INDEX] << " parse failed"; 3834514f5e3Sopenharmony_ci return false; 3844514f5e3Sopenharmony_ci } 3854514f5e3Sopenharmony_ci SampleMode mode; 3864514f5e3Sopenharmony_ci if (!PGOMethodInfo::GetSampleMode(infoStrings[PGOMethodInfo::METHOD_MODE_INDEX], mode)) { 3874514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "mode: " << infoStrings[PGOMethodInfo::METHOD_MODE_INDEX] << " parse failed"; 3884514f5e3Sopenharmony_ci return false; 3894514f5e3Sopenharmony_ci } 3904514f5e3Sopenharmony_ci if (count < threshold && mode == SampleMode::CALL_MODE) { 3914514f5e3Sopenharmony_ci return true; 3924514f5e3Sopenharmony_ci } 3934514f5e3Sopenharmony_ci uint32_t methodId; 3944514f5e3Sopenharmony_ci if (!StringHelper::StrToUInt32(infoStrings[PGOMethodInfo::METHOD_ID_INDEX].c_str(), &methodId)) { 3954514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "method id: " << infoStrings[PGOMethodInfo::METHOD_ID_INDEX] << " parse failed"; 3964514f5e3Sopenharmony_ci return false; 3974514f5e3Sopenharmony_ci } 3984514f5e3Sopenharmony_ci std::string methodName = infoStrings[PGOMethodInfo::METHOD_NAME_INDEX]; 3994514f5e3Sopenharmony_ci 4004514f5e3Sopenharmony_ci void *infoAddr = chunk->Allocate(PGOMethodInfo::Size(methodName.size())); 4014514f5e3Sopenharmony_ci auto info = new (infoAddr) PGOMethodInfo(PGOMethodId(methodId), count, mode, methodName.c_str()); 4024514f5e3Sopenharmony_ci methodInfos_.emplace(methodId, info); 4034514f5e3Sopenharmony_ci 4044514f5e3Sopenharmony_ci // Parse Type Info 4054514f5e3Sopenharmony_ci if (infoStrings.size() <= PGOMethodTypeSet::METHOD_TYPE_INFO_INDEX) { 4064514f5e3Sopenharmony_ci continue; 4074514f5e3Sopenharmony_ci } 4084514f5e3Sopenharmony_ci std::string typeInfos = infoStrings[PGOMethodTypeSet::METHOD_TYPE_INFO_INDEX]; 4094514f5e3Sopenharmony_ci if (!typeInfos.empty()) { 4104514f5e3Sopenharmony_ci size_t start = typeInfos.find_first_of(DumpUtils::ARRAY_START); 4114514f5e3Sopenharmony_ci size_t end = typeInfos.find_last_of(DumpUtils::ARRAY_END); 4124514f5e3Sopenharmony_ci if (start == std::string::npos || end == std::string::npos || start > end) { 4134514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Type info: " << typeInfos << " parse failed"; 4144514f5e3Sopenharmony_ci return false; 4154514f5e3Sopenharmony_ci } 4164514f5e3Sopenharmony_ci ASSERT(end > start + 1); 4174514f5e3Sopenharmony_ci auto typeContent = typeInfos.substr(start + 1, end - (start + 1) - 1); 4184514f5e3Sopenharmony_ci auto typeInfoSet = chunk->New<PGOMethodTypeSet>(); 4194514f5e3Sopenharmony_ci if (!typeInfoSet->ParseFromText(typeContent)) { 4204514f5e3Sopenharmony_ci // delete by chunk 4214514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Type info: " << typeInfos << " parse failed"; 4224514f5e3Sopenharmony_ci return false; 4234514f5e3Sopenharmony_ci } 4244514f5e3Sopenharmony_ci methodTypeInfos_.emplace(info->GetMethodId(), typeInfoSet); 4254514f5e3Sopenharmony_ci } 4264514f5e3Sopenharmony_ci } 4274514f5e3Sopenharmony_ci 4284514f5e3Sopenharmony_ci return true; 4294514f5e3Sopenharmony_ci} 4304514f5e3Sopenharmony_ci 4314514f5e3Sopenharmony_civoid PGOMethodInfoMap::ProcessToText(uint32_t threshold, const CString &recordName, std::ofstream &stream) const 4324514f5e3Sopenharmony_ci{ 4334514f5e3Sopenharmony_ci std::string profilerString; 4344514f5e3Sopenharmony_ci bool isFirst = true; 4354514f5e3Sopenharmony_ci for (auto methodInfoIter : methodInfos_) { 4364514f5e3Sopenharmony_ci auto methodInfo = methodInfoIter.second; 4374514f5e3Sopenharmony_ci if (methodInfo->IsFilter(threshold)) { 4384514f5e3Sopenharmony_ci continue; 4394514f5e3Sopenharmony_ci } 4404514f5e3Sopenharmony_ci if (isFirst) { 4414514f5e3Sopenharmony_ci profilerString += DumpUtils::NEW_LINE; 4424514f5e3Sopenharmony_ci profilerString += recordName; 4434514f5e3Sopenharmony_ci profilerString += DumpUtils::BLOCK_AND_ARRAY_START; 4444514f5e3Sopenharmony_ci isFirst = false; 4454514f5e3Sopenharmony_ci } else { 4464514f5e3Sopenharmony_ci profilerString += DumpUtils::BLOCK_SEPARATOR + DumpUtils::SPACE; 4474514f5e3Sopenharmony_ci } 4484514f5e3Sopenharmony_ci methodInfo->ProcessToText(profilerString); 4494514f5e3Sopenharmony_ci profilerString += DumpUtils::ELEMENT_SEPARATOR; 4504514f5e3Sopenharmony_ci auto checksumIter = methodsChecksum_.find(methodInfo->GetMethodId()); 4514514f5e3Sopenharmony_ci if (checksumIter != methodsChecksum_.end()) { 4524514f5e3Sopenharmony_ci std::stringstream parseStream; 4534514f5e3Sopenharmony_ci parseStream << std::internal << std::setfill('0') << std::showbase 4544514f5e3Sopenharmony_ci << std::setw(DumpUtils::HEX_FORMAT_WIDTH_FOR_32BITS) << std::hex << checksumIter->second 4554514f5e3Sopenharmony_ci << DumpUtils::ELEMENT_SEPARATOR; 4564514f5e3Sopenharmony_ci profilerString += parseStream.str(); 4574514f5e3Sopenharmony_ci } 4584514f5e3Sopenharmony_ci auto iter = methodTypeInfos_.find(methodInfo->GetMethodId()); 4594514f5e3Sopenharmony_ci if (iter != methodTypeInfos_.end()) { 4604514f5e3Sopenharmony_ci iter->second->ProcessToText(profilerString); 4614514f5e3Sopenharmony_ci } 4624514f5e3Sopenharmony_ci } 4634514f5e3Sopenharmony_ci if (!isFirst) { 4644514f5e3Sopenharmony_ci profilerString += (DumpUtils::SPACE + DumpUtils::ARRAY_END + DumpUtils::NEW_LINE); 4654514f5e3Sopenharmony_ci stream << profilerString; 4664514f5e3Sopenharmony_ci } 4674514f5e3Sopenharmony_ci} 4684514f5e3Sopenharmony_ci 4694514f5e3Sopenharmony_civoid PGOMethodInfoMap::ProcessToJson(uint32_t threshold, ProfileType::jModuleType &jModule) const 4704514f5e3Sopenharmony_ci{ 4714514f5e3Sopenharmony_ci std::vector<ProfileType::VariantMap> functionArray; 4724514f5e3Sopenharmony_ci for (auto methodInfoIter : methodInfos_) { 4734514f5e3Sopenharmony_ci auto methodInfo = methodInfoIter.second; 4744514f5e3Sopenharmony_ci if (methodInfo->IsFilter(threshold)) { 4754514f5e3Sopenharmony_ci continue; 4764514f5e3Sopenharmony_ci } 4774514f5e3Sopenharmony_ci ProfileType::VariantMap function; 4784514f5e3Sopenharmony_ci methodInfo->ProcessToJson(function); 4794514f5e3Sopenharmony_ci auto iter = methodTypeInfos_.find(methodInfo->GetMethodId()); 4804514f5e3Sopenharmony_ci if (iter != methodTypeInfos_.end()) { 4814514f5e3Sopenharmony_ci ProfileType::VariantVector typeArray; 4824514f5e3Sopenharmony_ci iter->second->ProcessToJson(typeArray); 4834514f5e3Sopenharmony_ci function.insert(std::make_pair(DumpJsonUtils::TYPE, typeArray)); 4844514f5e3Sopenharmony_ci } 4854514f5e3Sopenharmony_ci functionArray.push_back(function); 4864514f5e3Sopenharmony_ci } 4874514f5e3Sopenharmony_ci jModule.insert(std::make_pair(DumpJsonUtils::FUNCTION, functionArray)); 4884514f5e3Sopenharmony_ci} 4894514f5e3Sopenharmony_ci 4904514f5e3Sopenharmony_cibool PGOMethodIdSet::ParseFromBinary(PGOContext &context, void **buffer) 4914514f5e3Sopenharmony_ci{ 4924514f5e3Sopenharmony_ci PGOProfilerHeader *const header = context.GetHeader(); 4934514f5e3Sopenharmony_ci ASSERT(header != nullptr); 4944514f5e3Sopenharmony_ci SectionInfo secInfo = base::ReadBuffer<SectionInfo>(buffer); 4954514f5e3Sopenharmony_ci for (uint32_t j = 0; j < secInfo.number_; j++) { 4964514f5e3Sopenharmony_ci PGOMethodInfo *info = base::ReadBufferInSize<PGOMethodInfo>(buffer); 4974514f5e3Sopenharmony_ci if (info->IsFilter(context.GetHotnessThreshold())) { 4984514f5e3Sopenharmony_ci if (header->SupportMethodChecksum()) { 4994514f5e3Sopenharmony_ci base::ReadBuffer<uint32_t>(buffer, sizeof(uint32_t)); 5004514f5e3Sopenharmony_ci } 5014514f5e3Sopenharmony_ci if (header->SupportType()) { 5024514f5e3Sopenharmony_ci PGOMethodTypeSet::SkipFromBinary(buffer); 5034514f5e3Sopenharmony_ci } 5044514f5e3Sopenharmony_ci continue; 5054514f5e3Sopenharmony_ci } 5064514f5e3Sopenharmony_ci uint32_t checksum = 0; 5074514f5e3Sopenharmony_ci if (header->SupportMethodChecksum()) { 5084514f5e3Sopenharmony_ci checksum = base::ReadBuffer<uint32_t>(buffer, sizeof(uint32_t)); 5094514f5e3Sopenharmony_ci } 5104514f5e3Sopenharmony_ci auto ret = methodInfoMap_.try_emplace(info->GetMethodName(), chunk_); 5114514f5e3Sopenharmony_ci auto methodNameSetIter = ret.first; 5124514f5e3Sopenharmony_ci auto &methodInfo = methodNameSetIter->second.GetOrCreateMethodInfo(checksum, info->GetMethodId()); 5134514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "Method:" << info->GetMethodId() << DumpUtils::ELEMENT_SEPARATOR << info->GetCount() 5144514f5e3Sopenharmony_ci << DumpUtils::ELEMENT_SEPARATOR << std::to_string(static_cast<int>(info->GetSampleMode())) 5154514f5e3Sopenharmony_ci << DumpUtils::ELEMENT_SEPARATOR << info->GetMethodName(); 5164514f5e3Sopenharmony_ci if (header->SupportType()) { 5174514f5e3Sopenharmony_ci methodInfo.GetPGOMethodTypeSet().ParseFromBinary(context, buffer); 5184514f5e3Sopenharmony_ci } 5194514f5e3Sopenharmony_ci } 5204514f5e3Sopenharmony_ci 5214514f5e3Sopenharmony_ci return !methodInfoMap_.empty(); 5224514f5e3Sopenharmony_ci} 5234514f5e3Sopenharmony_ci 5244514f5e3Sopenharmony_civoid PGOMethodIdSet::GetMismatchResult(const CString &recordName, uint32_t &totalMethodCount, 5254514f5e3Sopenharmony_ci uint32_t &mismatchMethodCount, 5264514f5e3Sopenharmony_ci std::set<std::pair<std::string, CString>> &mismatchMethodSet) const 5274514f5e3Sopenharmony_ci{ 5284514f5e3Sopenharmony_ci totalMethodCount += methodInfoMap_.size(); 5294514f5e3Sopenharmony_ci for (const auto &methodNameSet : methodInfoMap_) { 5304514f5e3Sopenharmony_ci if (methodNameSet.second.IsMatch()) { 5314514f5e3Sopenharmony_ci continue; 5324514f5e3Sopenharmony_ci } 5334514f5e3Sopenharmony_ci auto info = std::make_pair(methodNameSet.first, recordName); 5344514f5e3Sopenharmony_ci mismatchMethodSet.emplace(info); 5354514f5e3Sopenharmony_ci mismatchMethodCount++; 5364514f5e3Sopenharmony_ci } 5374514f5e3Sopenharmony_ci} 5384514f5e3Sopenharmony_ci 5394514f5e3Sopenharmony_civoid PGOMethodIdSet::Merge(const PGOMethodIdSet &from) 5404514f5e3Sopenharmony_ci{ 5414514f5e3Sopenharmony_ci for (const auto &methodNameSet : from.methodInfoMap_) { 5424514f5e3Sopenharmony_ci auto iter = methodInfoMap_.find(methodNameSet.first); 5434514f5e3Sopenharmony_ci if (iter == methodInfoMap_.end()) { 5444514f5e3Sopenharmony_ci auto ret = methodInfoMap_.try_emplace(methodNameSet.first, chunk_); 5454514f5e3Sopenharmony_ci iter = ret.first; 5464514f5e3Sopenharmony_ci } 5474514f5e3Sopenharmony_ci const_cast<PGOMethodNameSet &>(iter->second).Merge(methodNameSet.second); 5484514f5e3Sopenharmony_ci } 5494514f5e3Sopenharmony_ci} 5504514f5e3Sopenharmony_ci 5514514f5e3Sopenharmony_civoid PGODecodeMethodInfo::Merge(const PGODecodeMethodInfo &from) 5524514f5e3Sopenharmony_ci{ 5534514f5e3Sopenharmony_ci ASSERT(methodId_.IsValid() && from.methodId_.IsValid()); 5544514f5e3Sopenharmony_ci if (!(methodId_ == from.methodId_)) { 5554514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "MethodId not match. " << methodId_ << " vs " << from.methodId_; 5564514f5e3Sopenharmony_ci return; 5574514f5e3Sopenharmony_ci } 5584514f5e3Sopenharmony_ci pgoMethodTypeSet_.Merge(&from.pgoMethodTypeSet_); 5594514f5e3Sopenharmony_ci} 5604514f5e3Sopenharmony_ci 5614514f5e3Sopenharmony_ciPGORecordDetailInfos::PGORecordDetailInfos(uint32_t hotnessThreshold) : hotnessThreshold_(hotnessThreshold) 5624514f5e3Sopenharmony_ci{ 5634514f5e3Sopenharmony_ci chunk_ = std::make_unique<Chunk>(&nativeAreaAllocator_); 5644514f5e3Sopenharmony_ci InitSections(); 5654514f5e3Sopenharmony_ci}; 5664514f5e3Sopenharmony_ci 5674514f5e3Sopenharmony_ciPGORecordDetailInfos::~PGORecordDetailInfos() 5684514f5e3Sopenharmony_ci{ 5694514f5e3Sopenharmony_ci Clear(); 5704514f5e3Sopenharmony_ci} 5714514f5e3Sopenharmony_ci 5724514f5e3Sopenharmony_ciPGOMethodInfoMap *PGORecordDetailInfos::GetMethodInfoMap(ProfileType recordProfileType) 5734514f5e3Sopenharmony_ci{ 5744514f5e3Sopenharmony_ci auto iter = recordInfos_.find(recordProfileType); 5754514f5e3Sopenharmony_ci if (iter != recordInfos_.end()) { 5764514f5e3Sopenharmony_ci return iter->second; 5774514f5e3Sopenharmony_ci } else { 5784514f5e3Sopenharmony_ci auto curMethodInfos = nativeAreaAllocator_.New<PGOMethodInfoMap>(); 5794514f5e3Sopenharmony_ci recordInfos_.emplace(recordProfileType, curMethodInfos); 5804514f5e3Sopenharmony_ci return curMethodInfos; 5814514f5e3Sopenharmony_ci } 5824514f5e3Sopenharmony_ci} 5834514f5e3Sopenharmony_ci 5844514f5e3Sopenharmony_cibool PGORecordDetailInfos::AddMethod(ProfileType recordProfileType, Method *jsMethod, SampleMode mode) 5854514f5e3Sopenharmony_ci{ 5864514f5e3Sopenharmony_ci auto curMethodInfos = GetMethodInfoMap(recordProfileType); 5874514f5e3Sopenharmony_ci ASSERT(curMethodInfos != nullptr); 5884514f5e3Sopenharmony_ci ASSERT(jsMethod != nullptr); 5894514f5e3Sopenharmony_ci return curMethodInfos->AddMethod(chunk_.get(), jsMethod, mode); 5904514f5e3Sopenharmony_ci} 5914514f5e3Sopenharmony_ci 5924514f5e3Sopenharmony_cibool PGORecordDetailInfos::AddType(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, 5934514f5e3Sopenharmony_ci PGOSampleType type) 5944514f5e3Sopenharmony_ci{ 5954514f5e3Sopenharmony_ci auto curMethodInfos = GetMethodInfoMap(recordProfileType); 5964514f5e3Sopenharmony_ci ASSERT(curMethodInfos != nullptr); 5974514f5e3Sopenharmony_ci return curMethodInfos->AddType(chunk_.get(), methodId, offset, type); 5984514f5e3Sopenharmony_ci} 5994514f5e3Sopenharmony_ci 6004514f5e3Sopenharmony_cibool PGORecordDetailInfos::AddCallTargetType(ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, 6014514f5e3Sopenharmony_ci PGOSampleType type) 6024514f5e3Sopenharmony_ci{ 6034514f5e3Sopenharmony_ci auto curMethodInfos = GetMethodInfoMap(recordProfileType); 6044514f5e3Sopenharmony_ci ASSERT(curMethodInfos != nullptr); 6054514f5e3Sopenharmony_ci return curMethodInfos->AddCallTargetType(chunk_.get(), methodId, offset, type); 6064514f5e3Sopenharmony_ci} 6074514f5e3Sopenharmony_ci 6084514f5e3Sopenharmony_cibool PGORecordDetailInfos::AddObjectInfo( 6094514f5e3Sopenharmony_ci ProfileType recordProfileType, EntityId methodId, int32_t offset, const PGOObjectInfo &info) 6104514f5e3Sopenharmony_ci{ 6114514f5e3Sopenharmony_ci auto curMethodInfos = GetMethodInfoMap(recordProfileType); 6124514f5e3Sopenharmony_ci ASSERT(curMethodInfos != nullptr); 6134514f5e3Sopenharmony_ci return curMethodInfos->AddObjectInfo(chunk_.get(), methodId, offset, info); 6144514f5e3Sopenharmony_ci} 6154514f5e3Sopenharmony_ci 6164514f5e3Sopenharmony_cibool PGORecordDetailInfos::AddDefine( 6174514f5e3Sopenharmony_ci ProfileType recordProfileType, PGOMethodId methodId, int32_t offset, PGODefineOpType type) 6184514f5e3Sopenharmony_ci{ 6194514f5e3Sopenharmony_ci auto curMethodInfos = GetMethodInfoMap(recordProfileType); 6204514f5e3Sopenharmony_ci ASSERT(curMethodInfos != nullptr); 6214514f5e3Sopenharmony_ci curMethodInfos->AddDefine(chunk_.get(), methodId, offset, type); 6224514f5e3Sopenharmony_ci 6234514f5e3Sopenharmony_ci PGOHClassTreeDesc descInfo(type.GetProfileType()); 6244514f5e3Sopenharmony_ci auto iter = hclassTreeDescInfos_.find(descInfo); 6254514f5e3Sopenharmony_ci if (iter == hclassTreeDescInfos_.end()) { 6264514f5e3Sopenharmony_ci descInfo.SetProtoPt(type.GetProtoTypePt()); 6274514f5e3Sopenharmony_ci hclassTreeDescInfos_.emplace(descInfo); 6284514f5e3Sopenharmony_ci } else { 6294514f5e3Sopenharmony_ci const_cast<PGOHClassTreeDesc &>(*iter).SetProtoPt(type.GetProtoTypePt()); 6304514f5e3Sopenharmony_ci } 6314514f5e3Sopenharmony_ci return true; 6324514f5e3Sopenharmony_ci} 6334514f5e3Sopenharmony_ci 6344514f5e3Sopenharmony_cibool PGORecordDetailInfos::AddRootLayout(JSTaggedType hclass, ProfileType rootType) 6354514f5e3Sopenharmony_ci{ 6364514f5e3Sopenharmony_ci PGOHClassTreeDesc descInfo(rootType); 6374514f5e3Sopenharmony_ci auto iter = hclassTreeDescInfos_.find(descInfo); 6384514f5e3Sopenharmony_ci if (iter != hclassTreeDescInfos_.end()) { 6394514f5e3Sopenharmony_ci return const_cast<PGOHClassTreeDesc &>(*iter).DumpForRoot(hclass, rootType); 6404514f5e3Sopenharmony_ci } else { 6414514f5e3Sopenharmony_ci if (!descInfo.DumpForRoot(hclass, rootType)) { 6424514f5e3Sopenharmony_ci return false; 6434514f5e3Sopenharmony_ci } 6444514f5e3Sopenharmony_ci hclassTreeDescInfos_.emplace(descInfo); 6454514f5e3Sopenharmony_ci } 6464514f5e3Sopenharmony_ci return true; 6474514f5e3Sopenharmony_ci} 6484514f5e3Sopenharmony_ci 6494514f5e3Sopenharmony_cibool PGORecordDetailInfos::UpdateLayout(ProfileType rootType, JSTaggedType hclass, ProfileType curType) 6504514f5e3Sopenharmony_ci{ 6514514f5e3Sopenharmony_ci PGOHClassTreeDesc descInfo(rootType); 6524514f5e3Sopenharmony_ci auto iter = hclassTreeDescInfos_.find(descInfo); 6534514f5e3Sopenharmony_ci if (iter != hclassTreeDescInfos_.end()) { 6544514f5e3Sopenharmony_ci return const_cast<PGOHClassTreeDesc &>(*iter).UpdateLayout(hclass, curType); 6554514f5e3Sopenharmony_ci } else { 6564514f5e3Sopenharmony_ci if (!descInfo.UpdateLayout(hclass, curType)) { 6574514f5e3Sopenharmony_ci return false; 6584514f5e3Sopenharmony_ci } 6594514f5e3Sopenharmony_ci hclassTreeDescInfos_.emplace(descInfo); 6604514f5e3Sopenharmony_ci return false; 6614514f5e3Sopenharmony_ci } 6624514f5e3Sopenharmony_ci return true; 6634514f5e3Sopenharmony_ci} 6644514f5e3Sopenharmony_ci 6654514f5e3Sopenharmony_cibool PGORecordDetailInfos::UpdateTransitionLayout( 6664514f5e3Sopenharmony_ci ProfileType rootType, JSTaggedType parent, ProfileType parentType, JSTaggedType child, ProfileType childType) 6674514f5e3Sopenharmony_ci{ 6684514f5e3Sopenharmony_ci PGOHClassTreeDesc descInfo(rootType); 6694514f5e3Sopenharmony_ci auto iter = hclassTreeDescInfos_.find(descInfo); 6704514f5e3Sopenharmony_ci if (iter != hclassTreeDescInfos_.end()) { 6714514f5e3Sopenharmony_ci return const_cast<PGOHClassTreeDesc &>(*iter).UpdateForTransition(parent, parentType, child, childType); 6724514f5e3Sopenharmony_ci } else { 6734514f5e3Sopenharmony_ci if (!descInfo.UpdateForTransition(parent, parentType, child, childType)) { 6744514f5e3Sopenharmony_ci return false; 6754514f5e3Sopenharmony_ci } 6764514f5e3Sopenharmony_ci hclassTreeDescInfos_.emplace(descInfo); 6774514f5e3Sopenharmony_ci } 6784514f5e3Sopenharmony_ci return true; 6794514f5e3Sopenharmony_ci} 6804514f5e3Sopenharmony_ci 6814514f5e3Sopenharmony_civoid PGORecordDetailInfos::AddRootPtType(ProfileType rootType, ProfileType ptType) 6824514f5e3Sopenharmony_ci{ 6834514f5e3Sopenharmony_ci PGOHClassTreeDesc descInfo(rootType); 6844514f5e3Sopenharmony_ci auto iter = hclassTreeDescInfos_.find(descInfo); 6854514f5e3Sopenharmony_ci if (iter != hclassTreeDescInfos_.end()) { 6864514f5e3Sopenharmony_ci const_cast<PGOHClassTreeDesc &>(*iter).SetProtoPt(ptType); 6874514f5e3Sopenharmony_ci } else { 6884514f5e3Sopenharmony_ci descInfo.SetProtoPt(ptType); 6894514f5e3Sopenharmony_ci hclassTreeDescInfos_.emplace(descInfo); 6904514f5e3Sopenharmony_ci } 6914514f5e3Sopenharmony_ci} 6924514f5e3Sopenharmony_ci 6934514f5e3Sopenharmony_cibool PGORecordDetailInfos::IsDumped(ProfileType rootType, ProfileType curType) const 6944514f5e3Sopenharmony_ci{ 6954514f5e3Sopenharmony_ci PGOHClassTreeDesc descInfo(rootType); 6964514f5e3Sopenharmony_ci auto iter = hclassTreeDescInfos_.find(descInfo); 6974514f5e3Sopenharmony_ci if (iter != hclassTreeDescInfos_.end()) { 6984514f5e3Sopenharmony_ci return const_cast<PGOHClassTreeDesc &>(*iter).IsDumped(curType); 6994514f5e3Sopenharmony_ci } 7004514f5e3Sopenharmony_ci return false; 7014514f5e3Sopenharmony_ci} 7024514f5e3Sopenharmony_ci 7034514f5e3Sopenharmony_civoid PGORecordDetailInfos::Merge(const PGORecordDetailInfos &recordInfos) 7044514f5e3Sopenharmony_ci{ 7054514f5e3Sopenharmony_ci CMap<ProfileType, PGOMethodInfoMap *> methodInfos = recordInfos.recordInfos_; 7064514f5e3Sopenharmony_ci for (auto iter = methodInfos.begin(); iter != methodInfos.end(); iter++) { 7074514f5e3Sopenharmony_ci auto recordType = iter->first; 7084514f5e3Sopenharmony_ci auto fromMethodInfos = iter->second; 7094514f5e3Sopenharmony_ci 7104514f5e3Sopenharmony_ci auto recordInfosIter = recordInfos_.find(recordType); 7114514f5e3Sopenharmony_ci PGOMethodInfoMap *toMethodInfos = nullptr; 7124514f5e3Sopenharmony_ci if (recordInfosIter == recordInfos_.end()) { 7134514f5e3Sopenharmony_ci toMethodInfos = nativeAreaAllocator_.New<PGOMethodInfoMap>(); 7144514f5e3Sopenharmony_ci recordInfos_.emplace(recordType, toMethodInfos); 7154514f5e3Sopenharmony_ci } else { 7164514f5e3Sopenharmony_ci toMethodInfos = recordInfosIter->second; 7174514f5e3Sopenharmony_ci } 7184514f5e3Sopenharmony_ci 7194514f5e3Sopenharmony_ci ASSERT(toMethodInfos != nullptr); 7204514f5e3Sopenharmony_ci toMethodInfos->Merge(chunk_.get(), fromMethodInfos); 7214514f5e3Sopenharmony_ci } 7224514f5e3Sopenharmony_ci 7234514f5e3Sopenharmony_ci recordPool_->Merge(*recordInfos.recordPool_); 7244514f5e3Sopenharmony_ci protoTransitionPool_->Merge(*recordInfos.protoTransitionPool_); 7254514f5e3Sopenharmony_ci // Merge global layout desc infos to global method info map 7264514f5e3Sopenharmony_ci std::set<PGOHClassTreeDesc> hclassTreeDescInfos = recordInfos.hclassTreeDescInfos_; 7274514f5e3Sopenharmony_ci for (auto info = hclassTreeDescInfos.begin(); info != hclassTreeDescInfos.end(); 7284514f5e3Sopenharmony_ci info++) { 7294514f5e3Sopenharmony_ci auto &fromInfo = *info; 7304514f5e3Sopenharmony_ci auto result = hclassTreeDescInfos_.find(fromInfo); 7314514f5e3Sopenharmony_ci if (result == hclassTreeDescInfos_.end()) { 7324514f5e3Sopenharmony_ci PGOHClassTreeDesc descInfo(fromInfo.GetProfileType()); 7334514f5e3Sopenharmony_ci descInfo.SetProtoPt(fromInfo.GetProtoPt()); 7344514f5e3Sopenharmony_ci descInfo.Merge(fromInfo); 7354514f5e3Sopenharmony_ci hclassTreeDescInfos_.emplace(descInfo); 7364514f5e3Sopenharmony_ci } else { 7374514f5e3Sopenharmony_ci const_cast<PGOHClassTreeDesc &>(*result).Merge(fromInfo); 7384514f5e3Sopenharmony_ci } 7394514f5e3Sopenharmony_ci } 7404514f5e3Sopenharmony_ci} 7414514f5e3Sopenharmony_ci 7424514f5e3Sopenharmony_cibool PGORecordDetailInfos::ParseFromBinary(void *buffer, PGOProfilerHeader *const header) 7434514f5e3Sopenharmony_ci{ 7444514f5e3Sopenharmony_ci header_ = header; 7454514f5e3Sopenharmony_ci // ProfileTypePool must be parsed at first 7464514f5e3Sopenharmony_ci PGOFileSectionInterface::ParseSectionFromBinary(*this, buffer, header, *profileTypePool_->GetPool()); 7474514f5e3Sopenharmony_ci if (!abcIdRemap_.empty()) { 7484514f5e3Sopenharmony_ci // step2: [abc pool merge] remap decoder's profileType pool's abcId field. 7494514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "remap with abcRemapSize: " << abcIdRemap_.size(); 7504514f5e3Sopenharmony_ci profileTypePool_->Remap(*this); 7514514f5e3Sopenharmony_ci } 7524514f5e3Sopenharmony_ci PGOFileSectionInterface::ParseSectionFromBinary(*this, buffer, header, *protoTransitionPool_); 7534514f5e3Sopenharmony_ci PGOFileSectionInterface::ParseSectionFromBinary(*this, buffer, header, *recordPool_); 7544514f5e3Sopenharmony_ci SectionInfo *info = header->GetRecordInfoSection(); 7554514f5e3Sopenharmony_ci void *addr = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + info->offset_); 7564514f5e3Sopenharmony_ci for (uint32_t i = 0; i < info->number_; i++) { 7574514f5e3Sopenharmony_ci ApEntityId recordId(0); 7584514f5e3Sopenharmony_ci ProfileType recordType; 7594514f5e3Sopenharmony_ci if (header->SupportProfileTypeWithAbcId()) { 7604514f5e3Sopenharmony_ci auto recordTypeRef = ProfileTypeRef(base::ReadBuffer<ApEntityId>(&addr, sizeof(ApEntityId))); 7614514f5e3Sopenharmony_ci auto res = ProfileType::CreateFromProfileTypeRef(*this, recordTypeRef); 7624514f5e3Sopenharmony_ci if (!res.has_value()) { 7634514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "ParseFromBinary failed, current addr: " << addr << std::endl; 7644514f5e3Sopenharmony_ci return false; 7654514f5e3Sopenharmony_ci } 7664514f5e3Sopenharmony_ci recordType = res.value(); 7674514f5e3Sopenharmony_ci recordId = recordType.GetId(); 7684514f5e3Sopenharmony_ci } else if (header->SupportRecordPool()) { 7694514f5e3Sopenharmony_ci recordId = base::ReadBuffer<ApEntityId>(&addr, sizeof(ApEntityId)); 7704514f5e3Sopenharmony_ci } else { 7714514f5e3Sopenharmony_ci auto *recordName = base::ReadBuffer(&addr); 7724514f5e3Sopenharmony_ci recordPool_->Add(ProfileType(recordId), recordName); 7734514f5e3Sopenharmony_ci } 7744514f5e3Sopenharmony_ci recordType.UpdateId(recordId); 7754514f5e3Sopenharmony_ci recordType.UpdateKind(ProfileType::Kind::RecordClassId); 7764514f5e3Sopenharmony_ci PGOMethodInfoMap *methodInfos = nativeAreaAllocator_.New<PGOMethodInfoMap>(); 7774514f5e3Sopenharmony_ci ASSERT(methodInfos != nullptr); 7784514f5e3Sopenharmony_ci if (methodInfos->ParseFromBinary(chunk_.get(), *this, &addr)) { 7794514f5e3Sopenharmony_ci recordInfos_.emplace(recordType, methodInfos); 7804514f5e3Sopenharmony_ci } 7814514f5e3Sopenharmony_ci } 7824514f5e3Sopenharmony_ci 7834514f5e3Sopenharmony_ci info = header->GetLayoutDescSection(); 7844514f5e3Sopenharmony_ci if (info == nullptr) { 7854514f5e3Sopenharmony_ci return false; 7864514f5e3Sopenharmony_ci } 7874514f5e3Sopenharmony_ci if (header->SupportTrackField()) { 7884514f5e3Sopenharmony_ci ParseFromBinaryForLayout(&addr); 7894514f5e3Sopenharmony_ci } 7904514f5e3Sopenharmony_ci return true; 7914514f5e3Sopenharmony_ci} 7924514f5e3Sopenharmony_ci 7934514f5e3Sopenharmony_cibool PGORecordDetailInfos::ParseFromBinaryForLayout(void **buffer) 7944514f5e3Sopenharmony_ci{ 7954514f5e3Sopenharmony_ci SectionInfo secInfo = base::ReadBuffer<SectionInfo>(buffer); 7964514f5e3Sopenharmony_ci for (uint32_t i = 0; i < secInfo.number_; i++) { 7974514f5e3Sopenharmony_ci auto *info = base::ReadBufferInSize<PGOHClassTreeDescInnerRef>(buffer); 7984514f5e3Sopenharmony_ci if (info == nullptr) { 7994514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "Binary format error!"; 8004514f5e3Sopenharmony_ci continue; 8014514f5e3Sopenharmony_ci } 8024514f5e3Sopenharmony_ci hclassTreeDescInfos_.emplace(info->Convert(*this)); 8034514f5e3Sopenharmony_ci } 8044514f5e3Sopenharmony_ci return true; 8054514f5e3Sopenharmony_ci} 8064514f5e3Sopenharmony_ci 8074514f5e3Sopenharmony_civoid PGORecordDetailInfos::ProcessToBinary( 8084514f5e3Sopenharmony_ci const SaveTask *task, std::fstream &fileStream, PGOProfilerHeader *const header) 8094514f5e3Sopenharmony_ci{ 8104514f5e3Sopenharmony_ci header_ = header; 8114514f5e3Sopenharmony_ci auto info = header->GetRecordInfoSection(); 8124514f5e3Sopenharmony_ci info->number_ = 0; 8134514f5e3Sopenharmony_ci info->offset_ = static_cast<uint32_t>(fileStream.tellp()); 8144514f5e3Sopenharmony_ci for (auto iter = recordInfos_.begin(); iter != recordInfos_.end(); iter++) { 8154514f5e3Sopenharmony_ci if (task && task->IsTerminate()) { 8164514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "ProcessProfile: task is already terminate"; 8174514f5e3Sopenharmony_ci break; 8184514f5e3Sopenharmony_ci } 8194514f5e3Sopenharmony_ci auto recordId = iter->first; 8204514f5e3Sopenharmony_ci auto curMethodInfos = iter->second; 8214514f5e3Sopenharmony_ci if (curMethodInfos->ProcessToBinary(*this, ProfileTypeRef(*this, recordId), task, fileStream, header)) { 8224514f5e3Sopenharmony_ci info->number_++; 8234514f5e3Sopenharmony_ci } 8244514f5e3Sopenharmony_ci } 8254514f5e3Sopenharmony_ci info->size_ = static_cast<uint32_t>(fileStream.tellp()) - info->offset_; 8264514f5e3Sopenharmony_ci 8274514f5e3Sopenharmony_ci info = header->GetLayoutDescSection(); 8284514f5e3Sopenharmony_ci if (info == nullptr) { 8294514f5e3Sopenharmony_ci return; 8304514f5e3Sopenharmony_ci } 8314514f5e3Sopenharmony_ci info->number_ = 0; 8324514f5e3Sopenharmony_ci info->offset_ = static_cast<uint32_t>(fileStream.tellp()); 8334514f5e3Sopenharmony_ci if (header->SupportType()) { 8344514f5e3Sopenharmony_ci if (!ProcessToBinaryForLayout(const_cast<NativeAreaAllocator *>(&nativeAreaAllocator_), task, fileStream)) { 8354514f5e3Sopenharmony_ci return; 8364514f5e3Sopenharmony_ci } 8374514f5e3Sopenharmony_ci info->number_++; 8384514f5e3Sopenharmony_ci } 8394514f5e3Sopenharmony_ci info->size_ = static_cast<uint32_t>(fileStream.tellp()) - info->offset_; 8404514f5e3Sopenharmony_ci 8414514f5e3Sopenharmony_ci PGOFileSectionInterface::ProcessSectionToBinary(*this, fileStream, header, *recordPool_); 8424514f5e3Sopenharmony_ci PGOFileSectionInterface::ProcessSectionToBinary(*this, fileStream, header, *protoTransitionPool_); 8434514f5e3Sopenharmony_ci // ProfileTypePool must be processed at last 8444514f5e3Sopenharmony_ci PGOFileSectionInterface::ProcessSectionToBinary(*this, fileStream, header, *profileTypePool_->GetPool()); 8454514f5e3Sopenharmony_ci} 8464514f5e3Sopenharmony_ci 8474514f5e3Sopenharmony_cibool PGORecordDetailInfos::ProcessToBinaryForLayout( 8484514f5e3Sopenharmony_ci NativeAreaAllocator *allocator, const SaveTask *task, std::fstream &stream) 8494514f5e3Sopenharmony_ci{ 8504514f5e3Sopenharmony_ci SectionInfo secInfo; 8514514f5e3Sopenharmony_ci auto layoutBeginPosition = stream.tellp(); 8524514f5e3Sopenharmony_ci stream.seekp(sizeof(SectionInfo), std::ofstream::cur); 8534514f5e3Sopenharmony_ci for (const auto &typeInfo : hclassTreeDescInfos_) { 8544514f5e3Sopenharmony_ci if (task && task->IsTerminate()) { 8554514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "ProcessProfile: task is already terminate"; 8564514f5e3Sopenharmony_ci return false; 8574514f5e3Sopenharmony_ci } 8584514f5e3Sopenharmony_ci auto profileType = PGOSampleType(typeInfo.GetProfileType()); 8594514f5e3Sopenharmony_ci size_t size = PGOHClassTreeDescInnerRef::CaculateSize(typeInfo); 8604514f5e3Sopenharmony_ci if (size == 0) { 8614514f5e3Sopenharmony_ci continue; 8624514f5e3Sopenharmony_ci } 8634514f5e3Sopenharmony_ci 8644514f5e3Sopenharmony_ci PGOSampleTypeRef classRef = PGOSampleTypeRef::ConvertFrom(*this, profileType); 8654514f5e3Sopenharmony_ci auto protoSt = PGOSampleType(typeInfo.GetProtoPt()); 8664514f5e3Sopenharmony_ci PGOSampleTypeRef protoClassRef = PGOSampleTypeRef::ConvertFrom(*this, protoSt); 8674514f5e3Sopenharmony_ci void *addr = allocator->Allocate(size); 8684514f5e3Sopenharmony_ci auto descInfos = new (addr) PGOHClassTreeDescInnerRef(size, classRef, protoClassRef); 8694514f5e3Sopenharmony_ci descInfos->Merge(typeInfo); 8704514f5e3Sopenharmony_ci stream.write(reinterpret_cast<char *>(descInfos), size); 8714514f5e3Sopenharmony_ci allocator->Delete(addr); 8724514f5e3Sopenharmony_ci secInfo.number_++; 8734514f5e3Sopenharmony_ci } 8744514f5e3Sopenharmony_ci 8754514f5e3Sopenharmony_ci secInfo.offset_ = sizeof(SectionInfo); 8764514f5e3Sopenharmony_ci secInfo.size_ = static_cast<uint32_t>(stream.tellp()) - 8774514f5e3Sopenharmony_ci static_cast<uint32_t>(layoutBeginPosition) - sizeof(SectionInfo); 8784514f5e3Sopenharmony_ci stream.seekp(layoutBeginPosition, std::ofstream::beg) 8794514f5e3Sopenharmony_ci .write(reinterpret_cast<char *>(&secInfo), sizeof(SectionInfo)) 8804514f5e3Sopenharmony_ci .seekp(0, std::ofstream::end); 8814514f5e3Sopenharmony_ci return true; 8824514f5e3Sopenharmony_ci} 8834514f5e3Sopenharmony_ci 8844514f5e3Sopenharmony_cibool PGORecordDetailInfos::ParseFromText(std::ifstream &stream) 8854514f5e3Sopenharmony_ci{ 8864514f5e3Sopenharmony_ci std::string details; 8874514f5e3Sopenharmony_ci while (std::getline(stream, details)) { 8884514f5e3Sopenharmony_ci if (details.empty()) { 8894514f5e3Sopenharmony_ci continue; 8904514f5e3Sopenharmony_ci } 8914514f5e3Sopenharmony_ci size_t blockIndex = details.find(DumpUtils::BLOCK_AND_ARRAY_START); 8924514f5e3Sopenharmony_ci if (blockIndex == std::string::npos) { 8934514f5e3Sopenharmony_ci return false; 8944514f5e3Sopenharmony_ci } 8954514f5e3Sopenharmony_ci CString recordName = ConvertToString(details.substr(0, blockIndex)); 8964514f5e3Sopenharmony_ci 8974514f5e3Sopenharmony_ci size_t start = details.find_first_of(DumpUtils::ARRAY_START); 8984514f5e3Sopenharmony_ci size_t end = details.find_last_of(DumpUtils::ARRAY_END); 8994514f5e3Sopenharmony_ci if (start == std::string::npos || end == std::string::npos || start > end) { 9004514f5e3Sopenharmony_ci return false; 9014514f5e3Sopenharmony_ci } 9024514f5e3Sopenharmony_ci ASSERT(end > start + 1); 9034514f5e3Sopenharmony_ci auto content = details.substr(start + 1, end - (start + 1) - 1); 9044514f5e3Sopenharmony_ci std::vector<std::string> infoStrings = StringHelper::SplitString(content, DumpUtils::BLOCK_SEPARATOR); 9054514f5e3Sopenharmony_ci if (infoStrings.size() <= 0) { 9064514f5e3Sopenharmony_ci continue; 9074514f5e3Sopenharmony_ci } 9084514f5e3Sopenharmony_ci 9094514f5e3Sopenharmony_ci ApEntityId recordId(0); 9104514f5e3Sopenharmony_ci ProfileType profileType(0, recordId, ProfileType::Kind::RecordClassId); 9114514f5e3Sopenharmony_ci auto methodInfosIter = recordInfos_.find(profileType); 9124514f5e3Sopenharmony_ci PGOMethodInfoMap *methodInfos = nullptr; 9134514f5e3Sopenharmony_ci if (methodInfosIter == recordInfos_.end()) { 9144514f5e3Sopenharmony_ci methodInfos = nativeAreaAllocator_.New<PGOMethodInfoMap>(); 9154514f5e3Sopenharmony_ci recordInfos_.emplace(profileType, methodInfos); 9164514f5e3Sopenharmony_ci } else { 9174514f5e3Sopenharmony_ci methodInfos = methodInfosIter->second; 9184514f5e3Sopenharmony_ci } 9194514f5e3Sopenharmony_ci ASSERT(methodInfos != nullptr); 9204514f5e3Sopenharmony_ci if (!methodInfos->ParseFromText(chunk_.get(), hotnessThreshold_, infoStrings)) { 9214514f5e3Sopenharmony_ci return false; 9224514f5e3Sopenharmony_ci } 9234514f5e3Sopenharmony_ci } 9244514f5e3Sopenharmony_ci return true; 9254514f5e3Sopenharmony_ci} 9264514f5e3Sopenharmony_ci 9274514f5e3Sopenharmony_civoid PGORecordDetailInfos::ProcessToText(std::ofstream &stream) const 9284514f5e3Sopenharmony_ci{ 9294514f5e3Sopenharmony_ci std::string profilerString; 9304514f5e3Sopenharmony_ci bool isFirst = true; 9314514f5e3Sopenharmony_ci for (auto layoutInfoIter : hclassTreeDescInfos_) { 9324514f5e3Sopenharmony_ci if (isFirst) { 9334514f5e3Sopenharmony_ci profilerString += DumpUtils::NEW_LINE; 9344514f5e3Sopenharmony_ci profilerString += DumpUtils::ARRAY_START + DumpUtils::SPACE; 9354514f5e3Sopenharmony_ci isFirst = false; 9364514f5e3Sopenharmony_ci } else { 9374514f5e3Sopenharmony_ci profilerString += DumpUtils::BLOCK_SEPARATOR + DumpUtils::SPACE; 9384514f5e3Sopenharmony_ci } 9394514f5e3Sopenharmony_ci profilerString += PGOHClassTreeDescInner::GetTypeString(layoutInfoIter); 9404514f5e3Sopenharmony_ci } 9414514f5e3Sopenharmony_ci if (!isFirst) { 9424514f5e3Sopenharmony_ci profilerString += (DumpUtils::SPACE + DumpUtils::ARRAY_END + DumpUtils::NEW_LINE); 9434514f5e3Sopenharmony_ci stream << profilerString; 9444514f5e3Sopenharmony_ci } 9454514f5e3Sopenharmony_ci for (auto iter = recordInfos_.begin(); iter != recordInfos_.end(); iter++) { 9464514f5e3Sopenharmony_ci const CString recordName(recordPool_->GetName(iter->first)); 9474514f5e3Sopenharmony_ci if (recordName.empty()) { 9484514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "record name is empty, " << iter->first.GetTypeString(); 9494514f5e3Sopenharmony_ci continue; 9504514f5e3Sopenharmony_ci } 9514514f5e3Sopenharmony_ci auto methodInfos = iter->second; 9524514f5e3Sopenharmony_ci methodInfos->ProcessToText(hotnessThreshold_, recordName, stream); 9534514f5e3Sopenharmony_ci } 9544514f5e3Sopenharmony_ci recordPool_->ProcessToText(stream); 9554514f5e3Sopenharmony_ci protoTransitionPool_->ProcessToText(stream); 9564514f5e3Sopenharmony_ci // ProfileTypePool must be processed at last 9574514f5e3Sopenharmony_ci profileTypePool_->GetPool()->ProcessToText(stream); 9584514f5e3Sopenharmony_ci} 9594514f5e3Sopenharmony_ci 9604514f5e3Sopenharmony_civoid PGORecordDetailInfos::InitSections() 9614514f5e3Sopenharmony_ci{ 9624514f5e3Sopenharmony_ci recordPool_ = std::make_unique<PGORecordPool>(); 9634514f5e3Sopenharmony_ci protoTransitionPool_ = std::make_unique<PGOProtoTransitionPool>(); 9644514f5e3Sopenharmony_ci profileTypePool_ = std::make_unique<PGOProfileTypePool>(); 9654514f5e3Sopenharmony_ci} 9664514f5e3Sopenharmony_ci 9674514f5e3Sopenharmony_civoid PGORecordDetailInfos::Clear() 9684514f5e3Sopenharmony_ci{ 9694514f5e3Sopenharmony_ci for (auto iter : recordInfos_) { 9704514f5e3Sopenharmony_ci iter.second->Clear(); 9714514f5e3Sopenharmony_ci nativeAreaAllocator_.Delete(iter.second); 9724514f5e3Sopenharmony_ci } 9734514f5e3Sopenharmony_ci for (auto iter : hclassTreeDescInfos_) { 9744514f5e3Sopenharmony_ci iter.Clear(); 9754514f5e3Sopenharmony_ci } 9764514f5e3Sopenharmony_ci hclassTreeDescInfos_.clear(); 9774514f5e3Sopenharmony_ci recordInfos_.clear(); 9784514f5e3Sopenharmony_ci recordPool_->Clear(); 9794514f5e3Sopenharmony_ci protoTransitionPool_->Clear(); 9804514f5e3Sopenharmony_ci profileTypePool_->Clear(); 9814514f5e3Sopenharmony_ci hclassTreeDescInfos_.clear(); 9824514f5e3Sopenharmony_ci abcIdRemap_.clear(); 9834514f5e3Sopenharmony_ci chunk_ = std::make_unique<Chunk>(&nativeAreaAllocator_); 9844514f5e3Sopenharmony_ci InitSections(); 9854514f5e3Sopenharmony_ci} 9864514f5e3Sopenharmony_ci 9874514f5e3Sopenharmony_cibool PGORecordSimpleInfos::Match(const CString &abcNormalizedDesc, const CString &recordName, EntityId methodId) 9884514f5e3Sopenharmony_ci{ 9894514f5e3Sopenharmony_ci auto abcMethodIds = methodIds_.find(abcNormalizedDesc); 9904514f5e3Sopenharmony_ci if (abcMethodIds == methodIds_.end()) { 9914514f5e3Sopenharmony_ci LOG_COMPILER(DEBUG) << "AbcDesc not found. abcNormalizedDesc: " << abcNormalizedDesc 9924514f5e3Sopenharmony_ci << ", methodIdsCount: " << methodIds_.size(); 9934514f5e3Sopenharmony_ci return false; 9944514f5e3Sopenharmony_ci } 9954514f5e3Sopenharmony_ci auto methodIdsIter = abcMethodIds->second.find(recordName); 9964514f5e3Sopenharmony_ci if (methodIdsIter == abcMethodIds->second.end()) { 9974514f5e3Sopenharmony_ci LOG_COMPILER(DEBUG) << "AbcDesc not found. recordName: " << recordName; 9984514f5e3Sopenharmony_ci return false; 9994514f5e3Sopenharmony_ci } 10004514f5e3Sopenharmony_ci return methodIdsIter->second->Match(methodId); 10014514f5e3Sopenharmony_ci} 10024514f5e3Sopenharmony_ci 10034514f5e3Sopenharmony_civoid PGORecordSimpleInfos::ParseFromBinary(void *buffer, PGOProfilerHeader *const header, 10044514f5e3Sopenharmony_ci std::shared_ptr<PGOAbcFilePool> &abcFilePool) 10054514f5e3Sopenharmony_ci{ 10064514f5e3Sopenharmony_ci header_ = header; 10074514f5e3Sopenharmony_ci // ProfileTypePool must be parsed at first 10084514f5e3Sopenharmony_ci if (!PGOFileSectionInterface::ParseSectionFromBinary(*this, buffer, header, *profileTypePool_->GetPool())) { 10094514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Parse from binary failed for profile type pool."; 10104514f5e3Sopenharmony_ci return; 10114514f5e3Sopenharmony_ci } 10124514f5e3Sopenharmony_ci if (!abcIdRemap_.empty()) { 10134514f5e3Sopenharmony_ci // step2: [abc pool merge] remap decoder's profileType pool's abcId field. 10144514f5e3Sopenharmony_ci LOG_ECMA(DEBUG) << "remap with abcRemapSize: " << abcIdRemap_.size(); 10154514f5e3Sopenharmony_ci profileTypePool_->Remap(*this); 10164514f5e3Sopenharmony_ci } 10174514f5e3Sopenharmony_ci if (!PGOFileSectionInterface::ParseSectionFromBinary(*this, buffer, header, *protoTransitionPool_)) { 10184514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Parse from binary failed for proto transition pool."; 10194514f5e3Sopenharmony_ci return; 10204514f5e3Sopenharmony_ci } 10214514f5e3Sopenharmony_ci if (!PGOFileSectionInterface::ParseSectionFromBinary(*this, buffer, header, *recordPool_)) { 10224514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Parse from binary failed for record pool."; 10234514f5e3Sopenharmony_ci return; 10244514f5e3Sopenharmony_ci } 10254514f5e3Sopenharmony_ci SectionInfo *info = header->GetRecordInfoSection(); 10264514f5e3Sopenharmony_ci void *addr = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(buffer) + info->offset_); 10274514f5e3Sopenharmony_ci for (uint32_t i = 0; i < info->number_; i++) { 10284514f5e3Sopenharmony_ci CString recordName; 10294514f5e3Sopenharmony_ci const char *abcDesc = ""; 10304514f5e3Sopenharmony_ci ProfileType recordType; 10314514f5e3Sopenharmony_ci if (header->SupportProfileTypeWithAbcId()) { 10324514f5e3Sopenharmony_ci auto recordTypeRef = ProfileTypeRef(base::ReadBuffer<ApEntityId>(&addr, sizeof(ApEntityId))); 10334514f5e3Sopenharmony_ci recordType = ProfileType(*this, recordTypeRef); 10344514f5e3Sopenharmony_ci recordName = recordPool_->GetName(recordType); 10354514f5e3Sopenharmony_ci auto abcId = recordType.GetAbcId(); 10364514f5e3Sopenharmony_ci const auto *entry = abcFilePool->GetPool()->GetEntry(abcId); 10374514f5e3Sopenharmony_ci if (entry != nullptr) { 10384514f5e3Sopenharmony_ci abcDesc = entry->GetData().c_str(); 10394514f5e3Sopenharmony_ci } 10404514f5e3Sopenharmony_ci } else if (header->SupportRecordPool()) { 10414514f5e3Sopenharmony_ci auto recordId = base::ReadBuffer<ApEntityId>(&addr, sizeof(ApEntityId)); 10424514f5e3Sopenharmony_ci recordName = recordPool_->GetName(ProfileType(recordId)); 10434514f5e3Sopenharmony_ci } else { 10444514f5e3Sopenharmony_ci recordName = base::ReadBuffer(&addr); 10454514f5e3Sopenharmony_ci } 10464514f5e3Sopenharmony_ci PGOMethodIdSet *methodIds = nativeAreaAllocator_.New<PGOMethodIdSet>(chunk_.get()); 10474514f5e3Sopenharmony_ci if (methodIds->ParseFromBinary(*this, &addr)) { 10484514f5e3Sopenharmony_ci auto methodIdsResult = methodIds_.try_emplace(JSPandaFile::GetNormalizedFileDesc(abcDesc)); 10494514f5e3Sopenharmony_ci // check record name, the default record name of the framework abc does not enter the aot compilation 10504514f5e3Sopenharmony_ci FrameworkHelper::GetRealRecordName(recordName); 10514514f5e3Sopenharmony_ci (methodIdsResult.first->second).emplace(recordName, methodIds); 10524514f5e3Sopenharmony_ci } 10534514f5e3Sopenharmony_ci } 10544514f5e3Sopenharmony_ci 10554514f5e3Sopenharmony_ci info = header->GetLayoutDescSection(); 10564514f5e3Sopenharmony_ci if (info == nullptr) { 10574514f5e3Sopenharmony_ci return; 10584514f5e3Sopenharmony_ci } 10594514f5e3Sopenharmony_ci if (header->SupportTrackField()) { 10604514f5e3Sopenharmony_ci ParseFromBinaryForLayout(&addr); 10614514f5e3Sopenharmony_ci } 10624514f5e3Sopenharmony_ci} 10634514f5e3Sopenharmony_ci 10644514f5e3Sopenharmony_civoid PGORecordSimpleInfos::Merge(const PGORecordSimpleInfos &simpleInfos) 10654514f5e3Sopenharmony_ci{ 10664514f5e3Sopenharmony_ci for (const auto &fromAbcMethodIds : simpleInfos.methodIds_) { 10674514f5e3Sopenharmony_ci auto toAbcMethodIds = methodIds_.try_emplace(fromAbcMethodIds.first); 10684514f5e3Sopenharmony_ci for (const auto &method : fromAbcMethodIds.second) { 10694514f5e3Sopenharmony_ci auto result = toAbcMethodIds.first->second.find(method.first); 10704514f5e3Sopenharmony_ci if (result == toAbcMethodIds.first->second.end()) { 10714514f5e3Sopenharmony_ci PGOMethodIdSet *methodIds = nativeAreaAllocator_.New<PGOMethodIdSet>(chunk_.get()); 10724514f5e3Sopenharmony_ci auto ret = toAbcMethodIds.first->second.emplace(method.first, methodIds); 10734514f5e3Sopenharmony_ci ASSERT(ret.second); 10744514f5e3Sopenharmony_ci result = ret.first; 10754514f5e3Sopenharmony_ci } 10764514f5e3Sopenharmony_ci const_cast<PGOMethodIdSet &>(*result->second).Merge(*method.second); 10774514f5e3Sopenharmony_ci } 10784514f5e3Sopenharmony_ci } 10794514f5e3Sopenharmony_ci recordPool_->Merge(*simpleInfos.recordPool_); 10804514f5e3Sopenharmony_ci protoTransitionPool_->Merge(*simpleInfos.protoTransitionPool_); 10814514f5e3Sopenharmony_ci // Merge global layout desc infos to global method info map 10824514f5e3Sopenharmony_ci for (const auto &hclassTreeDescInfo : simpleInfos.hclassTreeDescInfos_) { 10834514f5e3Sopenharmony_ci auto result = hclassTreeDescInfos_.find(hclassTreeDescInfo); 10844514f5e3Sopenharmony_ci if (result == hclassTreeDescInfos_.end()) { 10854514f5e3Sopenharmony_ci PGOHClassTreeDesc descInfo(hclassTreeDescInfo.GetProfileType()); 10864514f5e3Sopenharmony_ci descInfo.SetProtoPt(hclassTreeDescInfo.GetProtoPt()); 10874514f5e3Sopenharmony_ci descInfo.Merge(hclassTreeDescInfo); 10884514f5e3Sopenharmony_ci hclassTreeDescInfos_.emplace(descInfo); 10894514f5e3Sopenharmony_ci } else { 10904514f5e3Sopenharmony_ci const_cast<PGOHClassTreeDesc &>(*result).Merge(hclassTreeDescInfo); 10914514f5e3Sopenharmony_ci } 10924514f5e3Sopenharmony_ci } 10934514f5e3Sopenharmony_ci} 10944514f5e3Sopenharmony_ci 10954514f5e3Sopenharmony_cibool PGORecordSimpleInfos::ParseFromBinaryForLayout(void **buffer) 10964514f5e3Sopenharmony_ci{ 10974514f5e3Sopenharmony_ci SectionInfo secInfo = base::ReadBuffer<SectionInfo>(buffer); 10984514f5e3Sopenharmony_ci for (uint32_t i = 0; i < secInfo.number_; i++) { 10994514f5e3Sopenharmony_ci auto *info = base::ReadBufferInSize<PGOHClassTreeDescInnerRef>(buffer); 11004514f5e3Sopenharmony_ci if (info == nullptr) { 11014514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "Binary format error!"; 11024514f5e3Sopenharmony_ci continue; 11034514f5e3Sopenharmony_ci } 11044514f5e3Sopenharmony_ci hclassTreeDescInfos_.emplace(info->Convert(*this)); 11054514f5e3Sopenharmony_ci } 11064514f5e3Sopenharmony_ci return true; 11074514f5e3Sopenharmony_ci} 11084514f5e3Sopenharmony_ci 11094514f5e3Sopenharmony_civoid PGORecordSimpleInfos::InitSections() 11104514f5e3Sopenharmony_ci{ 11114514f5e3Sopenharmony_ci recordPool_ = std::make_unique<PGORecordPool>(); 11124514f5e3Sopenharmony_ci protoTransitionPool_ = std::make_unique<PGOProtoTransitionPool>(); 11134514f5e3Sopenharmony_ci profileTypePool_ = std::make_unique<PGOProfileTypePool>(); 11144514f5e3Sopenharmony_ci} 11154514f5e3Sopenharmony_ci 11164514f5e3Sopenharmony_civoid PGORecordSimpleInfos::Clear() 11174514f5e3Sopenharmony_ci{ 11184514f5e3Sopenharmony_ci for (const auto &abcMethodIds: methodIds_) { 11194514f5e3Sopenharmony_ci for (const auto &iter : abcMethodIds.second) { 11204514f5e3Sopenharmony_ci iter.second->Clear(); 11214514f5e3Sopenharmony_ci nativeAreaAllocator_.Delete(iter.second); 11224514f5e3Sopenharmony_ci } 11234514f5e3Sopenharmony_ci } 11244514f5e3Sopenharmony_ci for (auto iter : hclassTreeDescInfos_) { 11254514f5e3Sopenharmony_ci iter.Clear(); 11264514f5e3Sopenharmony_ci } 11274514f5e3Sopenharmony_ci hclassTreeDescInfos_.clear(); 11284514f5e3Sopenharmony_ci methodIds_.clear(); 11294514f5e3Sopenharmony_ci recordPool_->Clear(); 11304514f5e3Sopenharmony_ci profileTypePool_->Clear(); 11314514f5e3Sopenharmony_ci hclassTreeDescInfos_.clear(); 11324514f5e3Sopenharmony_ci abcIdRemap_.clear(); 11334514f5e3Sopenharmony_ci chunk_ = std::make_unique<Chunk>(&nativeAreaAllocator_); 11344514f5e3Sopenharmony_ci InitSections(); 11354514f5e3Sopenharmony_ci} 11364514f5e3Sopenharmony_ci 11374514f5e3Sopenharmony_ciPGORecordSimpleInfos::PGORecordSimpleInfos(uint32_t threshold) : hotnessThreshold_(threshold) 11384514f5e3Sopenharmony_ci{ 11394514f5e3Sopenharmony_ci chunk_ = std::make_unique<Chunk>(&nativeAreaAllocator_); 11404514f5e3Sopenharmony_ci InitSections(); 11414514f5e3Sopenharmony_ci} 11424514f5e3Sopenharmony_ci 11434514f5e3Sopenharmony_ciPGORecordSimpleInfos::~PGORecordSimpleInfos() 11444514f5e3Sopenharmony_ci{ 11454514f5e3Sopenharmony_ci Clear(); 11464514f5e3Sopenharmony_ci} 11474514f5e3Sopenharmony_ci} // namespace panda::ecmascript::pgo 1148