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#ifndef ECMASCRIPT_DFX_VMSTAT_OPT_CODE_PROFILER_H
164514f5e3Sopenharmony_ci#define ECMASCRIPT_DFX_VMSTAT_OPT_CODE_PROFILER_H
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/compiler/bytecodes.h"
194514f5e3Sopenharmony_ci#include "ecmascript/compiler/ecma_opcode_des.h"
204514f5e3Sopenharmony_ci#include "ecmascript/compiler/share_opcodes.h"
214514f5e3Sopenharmony_ci#include <set>
224514f5e3Sopenharmony_ci
234514f5e3Sopenharmony_ci// bcIndex   bytecode   count    fast    slow    typerate
244514f5e3Sopenharmony_ci// ====================(print all)=======================
254514f5e3Sopenharmony_ci// ........
264514f5e3Sopenharmony_ci// ======================================================
274514f5e3Sopenharmony_ci// total
284514f5e3Sopenharmony_ci
294514f5e3Sopenharmony_ci// tip: not print if count below 10000
304514f5e3Sopenharmony_ci// ====================(top1 method: name, methodId)=====
314514f5e3Sopenharmony_ci// .......
324514f5e3Sopenharmony_ci// (bcIndex   bytecode   count    fast    slow    typerate)
334514f5e3Sopenharmony_ci// .......
344514f5e3Sopenharmony_ci// ======================================================
354514f5e3Sopenharmony_ci
364514f5e3Sopenharmony_ci// ====================(top2 method: name)===============
374514f5e3Sopenharmony_ci// .......
384514f5e3Sopenharmony_ci// ======================================================
394514f5e3Sopenharmony_ci
404514f5e3Sopenharmony_ci// .......
414514f5e3Sopenharmony_ci
424514f5e3Sopenharmony_ci// ====================(top10 method: name)==============
434514f5e3Sopenharmony_ci// .......
444514f5e3Sopenharmony_ci// ======================================================
454514f5e3Sopenharmony_ci
464514f5e3Sopenharmony_ci// methodId, abcId, bcIndex, Value1(opcode, fastcount, slowcount),Value2(methodName, totalcount)
474514f5e3Sopenharmony_ci// key: methodId, abcId
484514f5e3Sopenharmony_ci// std::map<key, <bcIndex, Value1>>
494514f5e3Sopenharmony_ci// std::map<key, Value2>
504514f5e3Sopenharmony_ci
514514f5e3Sopenharmony_cinamespace panda::ecmascript {
524514f5e3Sopenharmony_ciclass OptCodeProfiler {
534514f5e3Sopenharmony_cipublic:
544514f5e3Sopenharmony_ci    using EcmaOpcode = kungfu::EcmaOpcode;
554514f5e3Sopenharmony_ci
564514f5e3Sopenharmony_ci    enum Mode {
574514f5e3Sopenharmony_ci        TYPED_PATH,
584514f5e3Sopenharmony_ci        SLOW_PATH,
594514f5e3Sopenharmony_ci    };
604514f5e3Sopenharmony_ci
614514f5e3Sopenharmony_ci    struct Value {
624514f5e3Sopenharmony_ci        Value() : typedPathValue(0), slowPathValue(0) {}
634514f5e3Sopenharmony_ci
644514f5e3Sopenharmony_ci        uint64_t TypedPathCount() const
654514f5e3Sopenharmony_ci        {
664514f5e3Sopenharmony_ci            return typedPathValue;
674514f5e3Sopenharmony_ci        }
684514f5e3Sopenharmony_ci
694514f5e3Sopenharmony_ci        uint64_t SlowPathCount() const
704514f5e3Sopenharmony_ci        {
714514f5e3Sopenharmony_ci            return slowPathValue;
724514f5e3Sopenharmony_ci        }
734514f5e3Sopenharmony_ci
744514f5e3Sopenharmony_ci        uint64_t Count() const
754514f5e3Sopenharmony_ci        {
764514f5e3Sopenharmony_ci            return typedPathValue + slowPathValue;
774514f5e3Sopenharmony_ci        }
784514f5e3Sopenharmony_ci
794514f5e3Sopenharmony_ci        void ResetStat()
804514f5e3Sopenharmony_ci        {
814514f5e3Sopenharmony_ci            typedPathValue = 0;
824514f5e3Sopenharmony_ci            slowPathValue = 0;
834514f5e3Sopenharmony_ci        }
844514f5e3Sopenharmony_ci
854514f5e3Sopenharmony_ci        uint64_t typedPathValue;
864514f5e3Sopenharmony_ci        uint64_t slowPathValue;
874514f5e3Sopenharmony_ci    };
884514f5e3Sopenharmony_ci
894514f5e3Sopenharmony_ci    struct Key {
904514f5e3Sopenharmony_ci        Key(uint32_t abcId, uint32_t methodId)
914514f5e3Sopenharmony_ci        {
924514f5e3Sopenharmony_ci            abcAndMethodId_ = (((uint64_t)abcId) << 32) + methodId; // 32: 32bit
934514f5e3Sopenharmony_ci        }
944514f5e3Sopenharmony_ci
954514f5e3Sopenharmony_ci        Key(uint64_t key) : abcAndMethodId_(key) {};
964514f5e3Sopenharmony_ci
974514f5e3Sopenharmony_ci        uint32_t GetAbcId() const
984514f5e3Sopenharmony_ci        {
994514f5e3Sopenharmony_ci            return (uint32_t) (abcAndMethodId_ >> 32); // 32: 32bit
1004514f5e3Sopenharmony_ci        }
1014514f5e3Sopenharmony_ci
1024514f5e3Sopenharmony_ci        uint32_t GetMethodId() const
1034514f5e3Sopenharmony_ci        {
1044514f5e3Sopenharmony_ci            return (uint32_t) abcAndMethodId_;
1054514f5e3Sopenharmony_ci        }
1064514f5e3Sopenharmony_ci
1074514f5e3Sopenharmony_ci        uint64_t Value() const
1084514f5e3Sopenharmony_ci        {
1094514f5e3Sopenharmony_ci            return abcAndMethodId_;
1104514f5e3Sopenharmony_ci        }
1114514f5e3Sopenharmony_ci
1124514f5e3Sopenharmony_ci        uint64_t abcAndMethodId_;
1134514f5e3Sopenharmony_ci    };
1144514f5e3Sopenharmony_ci
1154514f5e3Sopenharmony_ci    struct Name {
1164514f5e3Sopenharmony_ci        Name(std::string name) : methodName_(name), totalCount_(1) {}
1174514f5e3Sopenharmony_ci
1184514f5e3Sopenharmony_ci        uint64_t Count() const
1194514f5e3Sopenharmony_ci        {
1204514f5e3Sopenharmony_ci            return totalCount_;
1214514f5e3Sopenharmony_ci        }
1224514f5e3Sopenharmony_ci
1234514f5e3Sopenharmony_ci        void Inc()
1244514f5e3Sopenharmony_ci        {
1254514f5e3Sopenharmony_ci            totalCount_ = totalCount_ + 1;
1264514f5e3Sopenharmony_ci        }
1274514f5e3Sopenharmony_ci
1284514f5e3Sopenharmony_ci        std::string GetName() const
1294514f5e3Sopenharmony_ci        {
1304514f5e3Sopenharmony_ci            return methodName_;
1314514f5e3Sopenharmony_ci        }
1324514f5e3Sopenharmony_ci
1334514f5e3Sopenharmony_ci        std::string methodName_;
1344514f5e3Sopenharmony_ci        uint64_t totalCount_;
1354514f5e3Sopenharmony_ci    };
1364514f5e3Sopenharmony_ci
1374514f5e3Sopenharmony_ci    struct Record {
1384514f5e3Sopenharmony_ci        Record(EcmaOpcode opcode) : opcode_(opcode), fast_(0), slow_(0) {}
1394514f5e3Sopenharmony_ci
1404514f5e3Sopenharmony_ci        uint64_t Count() const
1414514f5e3Sopenharmony_ci        {
1424514f5e3Sopenharmony_ci            return fast_ + slow_;
1434514f5e3Sopenharmony_ci        }
1444514f5e3Sopenharmony_ci
1454514f5e3Sopenharmony_ci        uint64_t GetFast() const
1464514f5e3Sopenharmony_ci        {
1474514f5e3Sopenharmony_ci            return fast_;
1484514f5e3Sopenharmony_ci        }
1494514f5e3Sopenharmony_ci
1504514f5e3Sopenharmony_ci        uint64_t GetSlow() const
1514514f5e3Sopenharmony_ci        {
1524514f5e3Sopenharmony_ci            return slow_;
1534514f5e3Sopenharmony_ci        }
1544514f5e3Sopenharmony_ci
1554514f5e3Sopenharmony_ci        EcmaOpcode GetOpCode() const
1564514f5e3Sopenharmony_ci        {
1574514f5e3Sopenharmony_ci            return opcode_;
1584514f5e3Sopenharmony_ci        }
1594514f5e3Sopenharmony_ci
1604514f5e3Sopenharmony_ci        void IncFast()
1614514f5e3Sopenharmony_ci        {
1624514f5e3Sopenharmony_ci            fast_ = fast_ + 1;
1634514f5e3Sopenharmony_ci        }
1644514f5e3Sopenharmony_ci
1654514f5e3Sopenharmony_ci        void IncSlow()
1664514f5e3Sopenharmony_ci        {
1674514f5e3Sopenharmony_ci            slow_ = slow_ + 1;
1684514f5e3Sopenharmony_ci        }
1694514f5e3Sopenharmony_ci
1704514f5e3Sopenharmony_ci        EcmaOpcode opcode_;
1714514f5e3Sopenharmony_ci        uint64_t fast_;
1724514f5e3Sopenharmony_ci        uint64_t slow_;
1734514f5e3Sopenharmony_ci    };
1744514f5e3Sopenharmony_ci
1754514f5e3Sopenharmony_ci    OptCodeProfiler()
1764514f5e3Sopenharmony_ci    {
1774514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_OPT_CODE_PROFILER
1784514f5e3Sopenharmony_ci        profMap_ = {
1794514f5e3Sopenharmony_ci#define BYTECODE_PROF_MAP(name) { kungfu::EcmaOpcode::name, OptCodeProfiler::Value() },
1804514f5e3Sopenharmony_ci    ECMA_OPCODE_LIST(BYTECODE_PROF_MAP)
1814514f5e3Sopenharmony_ci#undef BYTECODE_PROF_MAP
1824514f5e3Sopenharmony_ci        };
1834514f5e3Sopenharmony_ci#endif
1844514f5e3Sopenharmony_ci    }
1854514f5e3Sopenharmony_ci
1864514f5e3Sopenharmony_ci    ~OptCodeProfiler();
1874514f5e3Sopenharmony_ci
1884514f5e3Sopenharmony_ci    void Update(JSHandle<JSTaggedValue> &func, int bcIndex, EcmaOpcode opcode, Mode mode);
1894514f5e3Sopenharmony_ci
1904514f5e3Sopenharmony_ci    void PrintAndReset();
1914514f5e3Sopenharmony_ci
1924514f5e3Sopenharmony_ci    using BcRecord = std::map<int, Record>;
1934514f5e3Sopenharmony_ciprivate:
1944514f5e3Sopenharmony_ci    void FilterMethodToPrint();
1954514f5e3Sopenharmony_ci    void PrintMethodRecord(Key key, std::string methodName);
1964514f5e3Sopenharmony_ci    void ResetMethodInfo()
1974514f5e3Sopenharmony_ci    {
1984514f5e3Sopenharmony_ci        methodIdToRecord_.clear();
1994514f5e3Sopenharmony_ci        methodIdToName_.clear();
2004514f5e3Sopenharmony_ci    }
2014514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_JIT_WARMUP_PROFILER == 0
2024514f5e3Sopenharmony_ci    int printMehodCount_ {10};
2034514f5e3Sopenharmony_ci#endif
2044514f5e3Sopenharmony_ci    std::map<EcmaOpcode, Value> profMap_;
2054514f5e3Sopenharmony_ci    std::map<uint64_t, BcRecord> methodIdToRecord_;
2064514f5e3Sopenharmony_ci    std::map<uint64_t, Name> methodIdToName_;
2074514f5e3Sopenharmony_ci    std::vector<CString> abcNames_;
2084514f5e3Sopenharmony_ci};
2094514f5e3Sopenharmony_ci
2104514f5e3Sopenharmony_ciclass TypedOpProfiler {
2114514f5e3Sopenharmony_cipublic:
2124514f5e3Sopenharmony_ci    using OpCode = kungfu::OpCode;
2134514f5e3Sopenharmony_ci
2144514f5e3Sopenharmony_ci    TypedOpProfiler()
2154514f5e3Sopenharmony_ci    {
2164514f5e3Sopenharmony_ci        strOpMap_ = {
2174514f5e3Sopenharmony_ci#define DECLARE_GATE_OPCODE(NAME, OP, R, S, D, V) \
2184514f5e3Sopenharmony_ci        { #OP, OpCode::OP },
2194514f5e3Sopenharmony_ci
2204514f5e3Sopenharmony_ci    MCR_IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_OPCODE)
2214514f5e3Sopenharmony_ci    MCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_OPCODE)
2224514f5e3Sopenharmony_ci    MCR_GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_OPCODE)
2234514f5e3Sopenharmony_ci    MCR_GATE_META_DATA_LIST_WITH_VALUE(DECLARE_GATE_OPCODE)
2244514f5e3Sopenharmony_ci    MCR_GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_OPCODE)
2254514f5e3Sopenharmony_ci    MCR_GATE_META_DATA_LIST_WITH_GATE_TYPE(DECLARE_GATE_OPCODE)
2264514f5e3Sopenharmony_ci    MCR_GATE_META_DATA_LIST_WITH_VALUE_IN(DECLARE_GATE_OPCODE)
2274514f5e3Sopenharmony_ci#undef DECLARE_GATE_OPCODE
2284514f5e3Sopenharmony_ci        };
2294514f5e3Sopenharmony_ci
2304514f5e3Sopenharmony_ci        profMap_ = {
2314514f5e3Sopenharmony_ci#define DECLARE_GATE_OPCODE(NAME, OP, R, S, D, V) \
2324514f5e3Sopenharmony_ci        { OpCode::OP, 0 },
2334514f5e3Sopenharmony_ci
2344514f5e3Sopenharmony_ci    MCR_IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_OPCODE)
2354514f5e3Sopenharmony_ci    MCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_OPCODE)
2364514f5e3Sopenharmony_ci    MCR_GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_OPCODE)
2374514f5e3Sopenharmony_ci    MCR_GATE_META_DATA_LIST_WITH_VALUE(DECLARE_GATE_OPCODE)
2384514f5e3Sopenharmony_ci    MCR_GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_OPCODE)
2394514f5e3Sopenharmony_ci    MCR_GATE_META_DATA_LIST_WITH_GATE_TYPE(DECLARE_GATE_OPCODE)
2404514f5e3Sopenharmony_ci    MCR_GATE_META_DATA_LIST_WITH_VALUE_IN(DECLARE_GATE_OPCODE)
2414514f5e3Sopenharmony_ci#undef DECLARE_GATE_OPCODE
2424514f5e3Sopenharmony_ci        };
2434514f5e3Sopenharmony_ci    }
2444514f5e3Sopenharmony_ci
2454514f5e3Sopenharmony_ci    void Update(OpCode opcode)
2464514f5e3Sopenharmony_ci    {
2474514f5e3Sopenharmony_ci        auto it = profMap_.find(opcode);
2484514f5e3Sopenharmony_ci        if (it != profMap_.end()) {
2494514f5e3Sopenharmony_ci            it->second++;
2504514f5e3Sopenharmony_ci            recordOp_.insert(opcode);
2514514f5e3Sopenharmony_ci        }
2524514f5e3Sopenharmony_ci    }
2534514f5e3Sopenharmony_ci
2544514f5e3Sopenharmony_ci    void Print(std::string opStr)
2554514f5e3Sopenharmony_ci    {
2564514f5e3Sopenharmony_ci        auto it = strOpMap_.find(opStr);
2574514f5e3Sopenharmony_ci        if (it != strOpMap_.end()) {
2584514f5e3Sopenharmony_ci            LOG_TRACE(INFO) << "Opcode: " << it->first << " Count:"
2594514f5e3Sopenharmony_ci                            << profMap_.at(it->second);
2604514f5e3Sopenharmony_ci        }
2614514f5e3Sopenharmony_ci    }
2624514f5e3Sopenharmony_ci
2634514f5e3Sopenharmony_ci    void Clear()
2644514f5e3Sopenharmony_ci    {
2654514f5e3Sopenharmony_ci        for (OpCode op : recordOp_) {
2664514f5e3Sopenharmony_ci            profMap_.at(op) = 0;
2674514f5e3Sopenharmony_ci        }
2684514f5e3Sopenharmony_ci        recordOp_.clear();
2694514f5e3Sopenharmony_ci    }
2704514f5e3Sopenharmony_ci
2714514f5e3Sopenharmony_ciprivate:
2724514f5e3Sopenharmony_ci    std::map<std::string, OpCode> strOpMap_;
2734514f5e3Sopenharmony_ci    std::map<OpCode, uint64_t> profMap_;
2744514f5e3Sopenharmony_ci    std::set<OpCode> recordOp_ {};
2754514f5e3Sopenharmony_ci};
2764514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
2774514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_DFX_VMSTAT_OPT_CODE_PROFILER_H
278