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