14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2022 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#ifndef ECMASCRIPT_PGO_PROFILE_DECODER_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_PGO_PROFILE_DECODER_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include "ecmascript/jspandafile/method_literal.h"
204514f5e3Sopenharmony_ci#include "ecmascript/log.h"
214514f5e3Sopenharmony_ci#include "ecmascript/log_wrapper.h"
224514f5e3Sopenharmony_ci#include "ecmascript/pgo_profiler/pgo_profiler_info.h"
234514f5e3Sopenharmony_ci#include "ecmascript/pgo_profiler/pgo_utils.h"
244514f5e3Sopenharmony_ci#include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
254514f5e3Sopenharmony_ci#include "ecmascript/platform/map.h"
264514f5e3Sopenharmony_ci
274514f5e3Sopenharmony_cinamespace panda::ecmascript::pgo {
284514f5e3Sopenharmony_ciclass PGOProfilerDecoder {
294514f5e3Sopenharmony_cipublic:
304514f5e3Sopenharmony_ci    PGOProfilerDecoder() = default;
314514f5e3Sopenharmony_ci    PGOProfilerDecoder(const std::string &inPath, uint32_t hotnessThreshold)
324514f5e3Sopenharmony_ci        : inPath_(inPath), hotnessThreshold_(hotnessThreshold) {}
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_ci    virtual ~PGOProfilerDecoder()
354514f5e3Sopenharmony_ci    {
364514f5e3Sopenharmony_ci        Clear();
374514f5e3Sopenharmony_ci    };
384514f5e3Sopenharmony_ci
394514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(PGOProfilerDecoder);
404514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(PGOProfilerDecoder);
414514f5e3Sopenharmony_ci
424514f5e3Sopenharmony_ci    bool PUBLIC_API Match(const JSPandaFile *jsPandaFile, const CString &recordName, PGOMethodId methodId);
434514f5e3Sopenharmony_ci
444514f5e3Sopenharmony_ci    bool PUBLIC_API LoadAndVerify(uint32_t checksum,
454514f5e3Sopenharmony_ci                                  const std::shared_ptr<PGOAbcFilePool> &externalAbcFilePool = nullptr);
464514f5e3Sopenharmony_ci    bool PUBLIC_API LoadFull(const std::shared_ptr<PGOAbcFilePool> &externalAbcFilePool = nullptr);
474514f5e3Sopenharmony_ci    void PUBLIC_API Clear();
484514f5e3Sopenharmony_ci
494514f5e3Sopenharmony_ci    bool PUBLIC_API SaveAPTextFile(const std::string &outPath);
504514f5e3Sopenharmony_ci
514514f5e3Sopenharmony_ci    void Merge(const PGOProfilerDecoder &decoder);
524514f5e3Sopenharmony_ci
534514f5e3Sopenharmony_ci    std::shared_ptr<PGOAbcFilePool> GetAbcFilePool() const
544514f5e3Sopenharmony_ci    {
554514f5e3Sopenharmony_ci        return abcFilePool_;
564514f5e3Sopenharmony_ci    }
574514f5e3Sopenharmony_ci
584514f5e3Sopenharmony_ci    bool InitMergeData();
594514f5e3Sopenharmony_ci
604514f5e3Sopenharmony_ci    void SetInPath(const std::string &inPath)
614514f5e3Sopenharmony_ci    {
624514f5e3Sopenharmony_ci        LOG_COMPILER(INFO) << "Set Profiler paths: " << inPath;
634514f5e3Sopenharmony_ci        inPath_ = inPath;
644514f5e3Sopenharmony_ci    }
654514f5e3Sopenharmony_ci
664514f5e3Sopenharmony_ci    const std::string& GetInPath() const
674514f5e3Sopenharmony_ci    {
684514f5e3Sopenharmony_ci        return inPath_;
694514f5e3Sopenharmony_ci    }
704514f5e3Sopenharmony_ci
714514f5e3Sopenharmony_ci    void SetHotnessThreshold(uint32_t hotnessThreshold)
724514f5e3Sopenharmony_ci    {
734514f5e3Sopenharmony_ci        hotnessThreshold_ = hotnessThreshold;
744514f5e3Sopenharmony_ci    }
754514f5e3Sopenharmony_ci
764514f5e3Sopenharmony_ci    uint32_t GetHotnessThreshold() const
774514f5e3Sopenharmony_ci    {
784514f5e3Sopenharmony_ci        return hotnessThreshold_;
794514f5e3Sopenharmony_ci    }
804514f5e3Sopenharmony_ci
814514f5e3Sopenharmony_ci    template <typename Callback>
824514f5e3Sopenharmony_ci    void Update(const JSPandaFile *jsPandaFile, Callback callback)
834514f5e3Sopenharmony_ci    {
844514f5e3Sopenharmony_ci        if (!isLoaded_ || !isVerifySuccess_) {
854514f5e3Sopenharmony_ci            return;
864514f5e3Sopenharmony_ci        }
874514f5e3Sopenharmony_ci        recordSimpleInfos_->Update(GetNormalizedFileDesc(jsPandaFile), callback);
884514f5e3Sopenharmony_ci    }
894514f5e3Sopenharmony_ci
904514f5e3Sopenharmony_ci    template <typename Callback>
914514f5e3Sopenharmony_ci    void Update(const JSPandaFile *jsPandaFile, const CString &recordName, Callback callback)
924514f5e3Sopenharmony_ci    {
934514f5e3Sopenharmony_ci        if (!isLoaded_ || !isVerifySuccess_) {
944514f5e3Sopenharmony_ci            return;
954514f5e3Sopenharmony_ci        }
964514f5e3Sopenharmony_ci        recordSimpleInfos_->Update(GetNormalizedFileDesc(jsPandaFile), recordName, callback);
974514f5e3Sopenharmony_ci    }
984514f5e3Sopenharmony_ci
994514f5e3Sopenharmony_ci    template <typename Callback>
1004514f5e3Sopenharmony_ci    void GetTypeInfo(const JSPandaFile *jsPandaFile, const CString &recordName, const MethodLiteral *methodLiteral,
1014514f5e3Sopenharmony_ci                     Callback callback) const
1024514f5e3Sopenharmony_ci    {
1034514f5e3Sopenharmony_ci        if (!isLoaded_ || !isVerifySuccess_ || methodLiteral == nullptr) {
1044514f5e3Sopenharmony_ci            return;
1054514f5e3Sopenharmony_ci        }
1064514f5e3Sopenharmony_ci        const auto *methodName = MethodLiteral::GetMethodName(jsPandaFile, methodLiteral->GetMethodId());
1074514f5e3Sopenharmony_ci        if (IsMethodMatchEnabled()) {
1084514f5e3Sopenharmony_ci            auto checksum =
1094514f5e3Sopenharmony_ci                PGOMethodInfo::CalcChecksum(methodName, methodLiteral->GetBytecodeArray(),
1104514f5e3Sopenharmony_ci                                            MethodLiteral::GetCodeSize(jsPandaFile, methodLiteral->GetMethodId()));
1114514f5e3Sopenharmony_ci
1124514f5e3Sopenharmony_ci            return recordSimpleInfos_->GetTypeInfo(GetNormalizedFileDesc(jsPandaFile), recordName, methodName, checksum,
1134514f5e3Sopenharmony_ci                                                   callback);
1144514f5e3Sopenharmony_ci        }
1154514f5e3Sopenharmony_ci        recordSimpleInfos_->GetTypeInfo(GetNormalizedFileDesc(jsPandaFile), recordName, methodName, callback);
1164514f5e3Sopenharmony_ci    }
1174514f5e3Sopenharmony_ci
1184514f5e3Sopenharmony_ci    void MatchAndMarkMethod(const JSPandaFile *jsPandaFile, const CString &recordName, const char *methodName,
1194514f5e3Sopenharmony_ci                            EntityId methodId)
1204514f5e3Sopenharmony_ci    {
1214514f5e3Sopenharmony_ci        if (!isLoaded_ || !isVerifySuccess_) {
1224514f5e3Sopenharmony_ci            return;
1234514f5e3Sopenharmony_ci        }
1244514f5e3Sopenharmony_ci        recordSimpleInfos_->MatchAndMarkMethod(GetNormalizedFileDesc(jsPandaFile), recordName, methodName, methodId);
1254514f5e3Sopenharmony_ci    }
1264514f5e3Sopenharmony_ci
1274514f5e3Sopenharmony_ci    void PUBLIC_API GetMismatchResult(const JSPandaFile *jsPandaFile, uint32_t &totalMethodCount,
1284514f5e3Sopenharmony_ci        uint32_t &mismatchMethodCount, std::set<std::pair<std::string, CString>> &mismatchMethodSet) const;
1294514f5e3Sopenharmony_ci
1304514f5e3Sopenharmony_ci    bool IsMethodMatchEnabled() const
1314514f5e3Sopenharmony_ci    {
1324514f5e3Sopenharmony_ci        return header_->SupportMethodChecksum();
1334514f5e3Sopenharmony_ci    }
1344514f5e3Sopenharmony_ci
1354514f5e3Sopenharmony_ci    bool PUBLIC_API GetHClassTreeDesc(PGOSampleType profileType, PGOHClassTreeDesc **desc) const;
1364514f5e3Sopenharmony_ci
1374514f5e3Sopenharmony_ci    template <typename Callback>
1384514f5e3Sopenharmony_ci    bool IterateHClassTreeDesc(Callback callback) const
1394514f5e3Sopenharmony_ci    {
1404514f5e3Sopenharmony_ci        if (!isLoaded_ || !isVerifySuccess_) {
1414514f5e3Sopenharmony_ci            return false;
1424514f5e3Sopenharmony_ci        }
1434514f5e3Sopenharmony_ci        return recordSimpleInfos_->IterateHClassTreeDesc(callback);
1444514f5e3Sopenharmony_ci    }
1454514f5e3Sopenharmony_ci
1464514f5e3Sopenharmony_ci    template <typename Callback>
1474514f5e3Sopenharmony_ci    bool IterateProtoTransitionPool(Callback callback) const
1484514f5e3Sopenharmony_ci    {
1494514f5e3Sopenharmony_ci        if (!isLoaded_ || !isVerifySuccess_) {
1504514f5e3Sopenharmony_ci            return false;
1514514f5e3Sopenharmony_ci        }
1524514f5e3Sopenharmony_ci        return recordSimpleInfos_->IterateProtoTransitionPool(callback);
1534514f5e3Sopenharmony_ci    }
1544514f5e3Sopenharmony_ci
1554514f5e3Sopenharmony_ci    bool IsLoaded() const
1564514f5e3Sopenharmony_ci    {
1574514f5e3Sopenharmony_ci        return isLoaded_;
1584514f5e3Sopenharmony_ci    }
1594514f5e3Sopenharmony_ci
1604514f5e3Sopenharmony_ci    PGORecordDetailInfos &GetRecordDetailInfos() const
1614514f5e3Sopenharmony_ci    {
1624514f5e3Sopenharmony_ci        return *recordDetailInfos_;
1634514f5e3Sopenharmony_ci    }
1644514f5e3Sopenharmony_ci
1654514f5e3Sopenharmony_ci    std::shared_ptr<PGORecordDetailInfos> GetRecordDetailInfosPtr() const
1664514f5e3Sopenharmony_ci    {
1674514f5e3Sopenharmony_ci        return recordDetailInfos_;
1684514f5e3Sopenharmony_ci    }
1694514f5e3Sopenharmony_ci
1704514f5e3Sopenharmony_ci    PGORecordSimpleInfos &GetRecordSimpleInfos() const
1714514f5e3Sopenharmony_ci    {
1724514f5e3Sopenharmony_ci        return *recordSimpleInfos_;
1734514f5e3Sopenharmony_ci    }
1744514f5e3Sopenharmony_ci
1754514f5e3Sopenharmony_ci    const PGOPandaFileInfos &GetPandaFileInfos() const
1764514f5e3Sopenharmony_ci    {
1774514f5e3Sopenharmony_ci        return pandaFileInfos_;
1784514f5e3Sopenharmony_ci    }
1794514f5e3Sopenharmony_ci
1804514f5e3Sopenharmony_ci    bool GetAbcNameById(ApEntityId abcId, CString &abcName) const
1814514f5e3Sopenharmony_ci    {
1824514f5e3Sopenharmony_ci        ASSERT(header_ != nullptr);
1834514f5e3Sopenharmony_ci        if (!header_->SupportProfileTypeWithAbcId()) {
1844514f5e3Sopenharmony_ci            return false;
1854514f5e3Sopenharmony_ci        }
1864514f5e3Sopenharmony_ci        ASSERT(abcFilePool_ != nullptr);
1874514f5e3Sopenharmony_ci        ASSERT(abcFilePool_->GetPool() != nullptr);
1884514f5e3Sopenharmony_ci        const auto *entry = abcFilePool_->GetPool()->GetEntry(abcId);
1894514f5e3Sopenharmony_ci        if (entry == nullptr) {
1904514f5e3Sopenharmony_ci            LOG_COMPILER(ERROR) << "Can not find abcId in pgo file. abcId: " << abcId;
1914514f5e3Sopenharmony_ci            return false;
1924514f5e3Sopenharmony_ci        }
1934514f5e3Sopenharmony_ci        abcName = entry->GetData();
1944514f5e3Sopenharmony_ci        return true;
1954514f5e3Sopenharmony_ci    }
1964514f5e3Sopenharmony_ci
1974514f5e3Sopenharmony_ci    bool GetABCIdByJSPandaFile(const JSPandaFile *jsPandaFile, ApEntityId &entryId) const
1984514f5e3Sopenharmony_ci    {
1994514f5e3Sopenharmony_ci        if (abcFilePool_ == nullptr) {
2004514f5e3Sopenharmony_ci            return false;
2014514f5e3Sopenharmony_ci        }
2024514f5e3Sopenharmony_ci        CString name = jsPandaFile->GetNormalizedFileDesc();
2034514f5e3Sopenharmony_ci        return abcFilePool_->GetEntryIdByNormalizedName(name, entryId);
2044514f5e3Sopenharmony_ci    }
2054514f5e3Sopenharmony_ci
2064514f5e3Sopenharmony_ci    bool IsCompatibleWithAOTFile()
2074514f5e3Sopenharmony_ci    {
2084514f5e3Sopenharmony_ci        // Can be null when AP file path is empty
2094514f5e3Sopenharmony_ci        if (header_ == nullptr) {
2104514f5e3Sopenharmony_ci            return false;
2114514f5e3Sopenharmony_ci        }
2124514f5e3Sopenharmony_ci        return header_->IsCompatibleWithAOTFile();
2134514f5e3Sopenharmony_ci    }
2144514f5e3Sopenharmony_ci
2154514f5e3Sopenharmony_ciprivate:
2164514f5e3Sopenharmony_ci    bool Load(const std::shared_ptr<PGOAbcFilePool> &externalAbcFilePool);
2174514f5e3Sopenharmony_ci    bool Verify(uint32_t checksum);
2184514f5e3Sopenharmony_ci
2194514f5e3Sopenharmony_ci    bool LoadAPBinaryFile(int prot = PAGE_PROT_READ);
2204514f5e3Sopenharmony_ci    void UnLoadAPBinaryFile();
2214514f5e3Sopenharmony_ci    CString PUBLIC_API GetNormalizedFileDesc(const JSPandaFile *jsPandaFile) const;
2224514f5e3Sopenharmony_ci    void LoadAbcIdPool(const std::shared_ptr<PGOAbcFilePool> &externalAbcFilePool, PGOContext &context,
2234514f5e3Sopenharmony_ci                       void *addr);
2244514f5e3Sopenharmony_ci
2254514f5e3Sopenharmony_ci    bool isLoaded_ {false};
2264514f5e3Sopenharmony_ci    bool isVerifySuccess_ {false};
2274514f5e3Sopenharmony_ci    std::string inPath_;
2284514f5e3Sopenharmony_ci    uint32_t hotnessThreshold_ {0};
2294514f5e3Sopenharmony_ci    PGOProfilerHeader *header_ {nullptr};
2304514f5e3Sopenharmony_ci    PGOPandaFileInfos pandaFileInfos_;
2314514f5e3Sopenharmony_ci    std::shared_ptr<PGOAbcFilePool> abcFilePool_;
2324514f5e3Sopenharmony_ci    bool externalAbcFilePool_ {false};
2334514f5e3Sopenharmony_ci    std::shared_ptr<PGORecordDetailInfos> recordDetailInfos_;
2344514f5e3Sopenharmony_ci    std::unique_ptr<PGORecordSimpleInfos> recordSimpleInfos_;
2354514f5e3Sopenharmony_ci    MemMap fileMapAddr_;
2364514f5e3Sopenharmony_ci};
2374514f5e3Sopenharmony_ci} // namespace panda::ecmascript::pgo
2384514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_PGO_PROFILE_DECODER_H
239