14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021-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#ifndef ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include <algorithm>
204514f5e3Sopenharmony_ci#include <tuple>
214514f5e3Sopenharmony_ci#include <utility>
224514f5e3Sopenharmony_ci#include <vector>
234514f5e3Sopenharmony_ci
244514f5e3Sopenharmony_ci#include "ecmascript/compiler/argument_accessor.h"
254514f5e3Sopenharmony_ci#include "ecmascript/compiler/bytecode_info_collector.h"
264514f5e3Sopenharmony_ci#include "ecmascript/compiler/bytecodes.h"
274514f5e3Sopenharmony_ci#include "ecmascript/compiler/circuit.h"
284514f5e3Sopenharmony_ci#include "ecmascript/compiler/ecma_opcode_des.h"
294514f5e3Sopenharmony_ci#include "ecmascript/compiler/frame_states.h"
304514f5e3Sopenharmony_ci#include "ecmascript/compiler/pgo_type/pgo_type_recorder.h"
314514f5e3Sopenharmony_ci#include "ecmascript/jit/jit_profiler.h"
324514f5e3Sopenharmony_ci#include "ecmascript/jspandafile/js_pandafile.h"
334514f5e3Sopenharmony_ci#include "ecmascript/jspandafile/method_literal.h"
344514f5e3Sopenharmony_ci#include "libpandafile/index_accessor.h"
354514f5e3Sopenharmony_ci
364514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
374514f5e3Sopenharmony_cistruct ExceptionItem {
384514f5e3Sopenharmony_ci    uint8_t* startPc;
394514f5e3Sopenharmony_ci    uint8_t* endPc;
404514f5e3Sopenharmony_ci    std::vector<uint8_t*> catches;
414514f5e3Sopenharmony_ci
424514f5e3Sopenharmony_ci    ExceptionItem(uint8_t* startPc, uint8_t* endPc, std::vector<uint8_t*> catches)
434514f5e3Sopenharmony_ci        : startPc(startPc), endPc(endPc), catches(catches) {}
444514f5e3Sopenharmony_ci};
454514f5e3Sopenharmony_ci
464514f5e3Sopenharmony_ciusing ExceptionInfo = std::vector<ExceptionItem>;
474514f5e3Sopenharmony_ci
484514f5e3Sopenharmony_ciclass RegionItem {
494514f5e3Sopenharmony_cipublic:
504514f5e3Sopenharmony_ci    static constexpr uint32_t INVALID_BC_INDEX = static_cast<uint32_t>(-1);
514514f5e3Sopenharmony_ci    bool operator<(const RegionItem &rhs) const
524514f5e3Sopenharmony_ci    {
534514f5e3Sopenharmony_ci        return this->startBcIndex_ < rhs.startBcIndex_;
544514f5e3Sopenharmony_ci    }
554514f5e3Sopenharmony_ci
564514f5e3Sopenharmony_ci    bool operator>(const RegionItem &rhs) const
574514f5e3Sopenharmony_ci    {
584514f5e3Sopenharmony_ci        return this->startBcIndex_ > rhs.startBcIndex_;
594514f5e3Sopenharmony_ci    }
604514f5e3Sopenharmony_ci
614514f5e3Sopenharmony_ci    bool operator==(const RegionItem &rhs) const
624514f5e3Sopenharmony_ci    {
634514f5e3Sopenharmony_ci        return this->startBcIndex_ == rhs.startBcIndex_;
644514f5e3Sopenharmony_ci    }
654514f5e3Sopenharmony_ci
664514f5e3Sopenharmony_ci    RegionItem(uint32_t startBcIndex, bool isHeadBlock)
674514f5e3Sopenharmony_ci        : startBcIndex_(startBcIndex), isHeadBlock_(isHeadBlock) {}
684514f5e3Sopenharmony_ci
694514f5e3Sopenharmony_ci    uint32_t GetStartBcIndex() const
704514f5e3Sopenharmony_ci    {
714514f5e3Sopenharmony_ci        return startBcIndex_;
724514f5e3Sopenharmony_ci    }
734514f5e3Sopenharmony_ci
744514f5e3Sopenharmony_ci    uint32_t IsHeadBlock() const
754514f5e3Sopenharmony_ci    {
764514f5e3Sopenharmony_ci        return isHeadBlock_;
774514f5e3Sopenharmony_ci    }
784514f5e3Sopenharmony_ciprivate:
794514f5e3Sopenharmony_ci    uint32_t startBcIndex_ { INVALID_BC_INDEX };
804514f5e3Sopenharmony_ci    bool isHeadBlock_ { false };
814514f5e3Sopenharmony_ci    friend class RegionsInfo;
824514f5e3Sopenharmony_ci};
834514f5e3Sopenharmony_ci
844514f5e3Sopenharmony_cistruct BytecodeSplitItem {
854514f5e3Sopenharmony_ci    BytecodeSplitItem(uint32_t start, uint32_t pred)
864514f5e3Sopenharmony_ci        : startBcIndex(start), predBcIndex(pred) {}
874514f5e3Sopenharmony_ci    uint32_t startBcIndex { RegionItem::INVALID_BC_INDEX };
884514f5e3Sopenharmony_ci    uint32_t predBcIndex { RegionItem::INVALID_BC_INDEX };
894514f5e3Sopenharmony_ci};
904514f5e3Sopenharmony_ci
914514f5e3Sopenharmony_ciclass RegionsInfo {
924514f5e3Sopenharmony_cipublic:
934514f5e3Sopenharmony_ci    void InsertJump(uint32_t bcIndex, uint32_t predBcIndex, bool isJumpImm)
944514f5e3Sopenharmony_ci    {
954514f5e3Sopenharmony_ci        InsertBlockItem(bcIndex, false);
964514f5e3Sopenharmony_ci        auto fallThrogth = bcIndex - 1; // 1: fall through
974514f5e3Sopenharmony_ci        // isJumpImm will not generate fall through
984514f5e3Sopenharmony_ci        if (isJumpImm || fallThrogth != predBcIndex) {
994514f5e3Sopenharmony_ci            InsertSplitItem(bcIndex, predBcIndex);
1004514f5e3Sopenharmony_ci        }
1014514f5e3Sopenharmony_ci    }
1024514f5e3Sopenharmony_ci
1034514f5e3Sopenharmony_ci    void InsertHead(uint32_t bcIndex)
1044514f5e3Sopenharmony_ci    {
1054514f5e3Sopenharmony_ci        InsertBlockItem(bcIndex, true);
1064514f5e3Sopenharmony_ci    }
1074514f5e3Sopenharmony_ci
1084514f5e3Sopenharmony_ci    void InsertSplit(uint32_t bcIndex)
1094514f5e3Sopenharmony_ci    {
1104514f5e3Sopenharmony_ci        InsertBlockItem(bcIndex, false);
1114514f5e3Sopenharmony_ci    }
1124514f5e3Sopenharmony_ci
1134514f5e3Sopenharmony_ci    size_t FindBBIndexByBcIndex(uint32_t bcIndex) const
1144514f5e3Sopenharmony_ci    {
1154514f5e3Sopenharmony_ci        auto findFunc = [] (uint32_t value, const RegionItem &item) {
1164514f5e3Sopenharmony_ci            return value < item.startBcIndex_;
1174514f5e3Sopenharmony_ci        };
1184514f5e3Sopenharmony_ci        const auto &it = std::upper_bound(blockItems_.begin(),
1194514f5e3Sopenharmony_ci            blockItems_.end(), bcIndex, findFunc);
1204514f5e3Sopenharmony_ci        if (it == blockItems_.end()) {
1214514f5e3Sopenharmony_ci            return blockItems_.size();
1224514f5e3Sopenharmony_ci        }
1234514f5e3Sopenharmony_ci        // blockItems_[0]'s value is 0, bcIndex must be: bcIndex > blockItems_.begin()
1244514f5e3Sopenharmony_ci        return std::distance(blockItems_.begin(), it);
1254514f5e3Sopenharmony_ci    }
1264514f5e3Sopenharmony_ci
1274514f5e3Sopenharmony_ci    const std::vector<BytecodeSplitItem> &GetSplitItems() const
1284514f5e3Sopenharmony_ci    {
1294514f5e3Sopenharmony_ci        return splitItems_;
1304514f5e3Sopenharmony_ci    }
1314514f5e3Sopenharmony_ci
1324514f5e3Sopenharmony_ci    const std::set<RegionItem> &GetBlockItems() const
1334514f5e3Sopenharmony_ci    {
1344514f5e3Sopenharmony_ci        return blockItems_;
1354514f5e3Sopenharmony_ci    }
1364514f5e3Sopenharmony_ciprivate:
1374514f5e3Sopenharmony_ci    void InsertBlockItem(uint32_t bcIndex, bool isHeadBlock)
1384514f5e3Sopenharmony_ci    {
1394514f5e3Sopenharmony_ci        auto result = blockItems_.insert(RegionItem { bcIndex, isHeadBlock });
1404514f5e3Sopenharmony_ci        if (!result.second && isHeadBlock) {
1414514f5e3Sopenharmony_ci            blockItems_.erase(result.first);
1424514f5e3Sopenharmony_ci            blockItems_.insert(RegionItem { bcIndex, isHeadBlock });
1434514f5e3Sopenharmony_ci        }
1444514f5e3Sopenharmony_ci    }
1454514f5e3Sopenharmony_ci
1464514f5e3Sopenharmony_ci    void InsertSplitItem(uint32_t bcIndex, uint32_t predBcIndex)
1474514f5e3Sopenharmony_ci    {
1484514f5e3Sopenharmony_ci        splitItems_.emplace_back(BytecodeSplitItem { bcIndex, predBcIndex });
1494514f5e3Sopenharmony_ci    }
1504514f5e3Sopenharmony_ci    std::set<RegionItem> blockItems_ {};
1514514f5e3Sopenharmony_ci    std::vector<BytecodeSplitItem> splitItems_ {};
1524514f5e3Sopenharmony_ci};
1534514f5e3Sopenharmony_ci
1544514f5e3Sopenharmony_cistruct BytecodeRegion {
1554514f5e3Sopenharmony_ci    size_t id {0};
1564514f5e3Sopenharmony_ci    uint32_t start {0};
1574514f5e3Sopenharmony_ci    uint32_t end {0};
1584514f5e3Sopenharmony_ci    ChunkVector<BytecodeRegion *> preds; // List of predessesor blocks
1594514f5e3Sopenharmony_ci    ChunkVector<BytecodeRegion *> succs; // List of successors blocks
1604514f5e3Sopenharmony_ci    ChunkVector<BytecodeRegion *> trys; // List of trys blocks
1614514f5e3Sopenharmony_ci    ChunkVector<BytecodeRegion *> catches; // List of catches blocks
1624514f5e3Sopenharmony_ci    ChunkSet<size_t> loopBacks;
1634514f5e3Sopenharmony_ci    size_t numOfLoopBack {0};
1644514f5e3Sopenharmony_ci    size_t numOfStatePreds {0};
1654514f5e3Sopenharmony_ci    size_t loopNumber {0};
1664514f5e3Sopenharmony_ci    size_t loopIndex {0};
1674514f5e3Sopenharmony_ci    ChunkVector<std::tuple<size_t, size_t, bool>> expandedPreds;
1684514f5e3Sopenharmony_ci    GateRef dependCache {Circuit::NullGate()};
1694514f5e3Sopenharmony_ci    BytecodeIterator bytecodeIterator_ {};
1704514f5e3Sopenharmony_ci    BytecodeRegion(Chunk* chunk) : preds(chunk), succs(chunk),
1714514f5e3Sopenharmony_ci        trys(chunk), catches(chunk), loopBacks(chunk), expandedPreds(chunk)
1724514f5e3Sopenharmony_ci    {
1734514f5e3Sopenharmony_ci    }
1744514f5e3Sopenharmony_ci
1754514f5e3Sopenharmony_ci    BytecodeIterator &GetBytecodeIterator()
1764514f5e3Sopenharmony_ci    {
1774514f5e3Sopenharmony_ci        return bytecodeIterator_;
1784514f5e3Sopenharmony_ci    }
1794514f5e3Sopenharmony_ci
1804514f5e3Sopenharmony_ci    bool operator <(const BytecodeRegion &target) const
1814514f5e3Sopenharmony_ci    {
1824514f5e3Sopenharmony_ci        return id < target.id;
1834514f5e3Sopenharmony_ci    }
1844514f5e3Sopenharmony_ci
1854514f5e3Sopenharmony_ci    void SortCatches()
1864514f5e3Sopenharmony_ci    {
1874514f5e3Sopenharmony_ci        if (catches.size() > 1) {
1884514f5e3Sopenharmony_ci            std::sort(catches.begin(), catches.end(), [](BytecodeRegion *first, BytecodeRegion *second) {
1894514f5e3Sopenharmony_ci                return first->start < second->start;
1904514f5e3Sopenharmony_ci            });
1914514f5e3Sopenharmony_ci        }
1924514f5e3Sopenharmony_ci    }
1934514f5e3Sopenharmony_ci
1944514f5e3Sopenharmony_ci    void EraseThisBlock(ChunkVector<BytecodeRegion *> &blocks)
1954514f5e3Sopenharmony_ci    {
1964514f5e3Sopenharmony_ci        auto it = std::find(blocks.begin(), blocks.end(), this);
1974514f5e3Sopenharmony_ci        if (it != blocks.end()) {
1984514f5e3Sopenharmony_ci            blocks.erase(it);
1994514f5e3Sopenharmony_ci        }
2004514f5e3Sopenharmony_ci    }
2014514f5e3Sopenharmony_ci
2024514f5e3Sopenharmony_ci    bool IsEmptryBlock() const
2034514f5e3Sopenharmony_ci    {
2044514f5e3Sopenharmony_ci        return end == static_cast<uint32_t>(BytecodeIterator::INVALID_INDEX);
2054514f5e3Sopenharmony_ci    }
2064514f5e3Sopenharmony_ci
2074514f5e3Sopenharmony_ci    bool IsLoopBack(const BytecodeRegion &bb) const
2084514f5e3Sopenharmony_ci    {
2094514f5e3Sopenharmony_ci        return loopBacks.find(bb.id) != loopBacks.end();
2104514f5e3Sopenharmony_ci    }
2114514f5e3Sopenharmony_ci};
2124514f5e3Sopenharmony_ci
2134514f5e3Sopenharmony_ciusing BytecodeGraph = ChunkVector<BytecodeRegion*>;
2144514f5e3Sopenharmony_ci
2154514f5e3Sopenharmony_ciclass BytecodeCircuitBuilder {
2164514f5e3Sopenharmony_cipublic:
2174514f5e3Sopenharmony_ci    BytecodeCircuitBuilder(const JSPandaFile *jsPandaFile,
2184514f5e3Sopenharmony_ci                           const MethodLiteral *methodLiteral,
2194514f5e3Sopenharmony_ci                           const MethodPcInfo &methodPCInfo,
2204514f5e3Sopenharmony_ci                           Circuit *circuit,
2214514f5e3Sopenharmony_ci                           Bytecodes *bytecodes,
2224514f5e3Sopenharmony_ci                           bool enableLog,
2234514f5e3Sopenharmony_ci                           bool enableTypeLowering,
2244514f5e3Sopenharmony_ci                           std::string name,
2254514f5e3Sopenharmony_ci                           const CString &recordName,
2264514f5e3Sopenharmony_ci                           PGOProfilerDecoder *decoder,
2274514f5e3Sopenharmony_ci                           bool isInline,
2284514f5e3Sopenharmony_ci                           JITProfiler* jitProfiler = nullptr)
2294514f5e3Sopenharmony_ci        : circuit_(circuit), graph_(circuit->chunk()), file_(jsPandaFile),
2304514f5e3Sopenharmony_ci          method_(methodLiteral), gateAcc_(circuit), argAcc_(circuit, method_),
2314514f5e3Sopenharmony_ci          pgoTypeRecorder_(*decoder, jsPandaFile, method_->GetMethodId().GetOffset()),
2324514f5e3Sopenharmony_ci          enableLog_(enableLog), enableTypeLowering_(enableTypeLowering),
2334514f5e3Sopenharmony_ci          pcOffsets_(methodPCInfo.pcOffsets),
2344514f5e3Sopenharmony_ci          frameStateBuilder_(this, circuit, methodLiteral),
2354514f5e3Sopenharmony_ci          methodName_(name), recordName_(recordName),
2364514f5e3Sopenharmony_ci          bytecodes_(bytecodes),
2374514f5e3Sopenharmony_ci          loopHeaderGates_(circuit->chunk()),
2384514f5e3Sopenharmony_ci          preFrameState_(circuit_->GetRoot()),
2394514f5e3Sopenharmony_ci          preFrameArgs_(circuit_->GetRoot()),
2404514f5e3Sopenharmony_ci          isInline_(isInline),
2414514f5e3Sopenharmony_ci          methodId_(method_->GetMethodId().GetOffset())
2424514f5e3Sopenharmony_ci    {
2434514f5e3Sopenharmony_ci        if (jitProfiler != nullptr) {
2444514f5e3Sopenharmony_ci            pgoTypeRecorder_.InitMap(jitProfiler);
2454514f5e3Sopenharmony_ci        }
2464514f5e3Sopenharmony_ci    }
2474514f5e3Sopenharmony_ci    ~BytecodeCircuitBuilder() = default;
2484514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(BytecodeCircuitBuilder);
2494514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(BytecodeCircuitBuilder);
2504514f5e3Sopenharmony_ci    void PUBLIC_API BytecodeToCircuit();
2514514f5e3Sopenharmony_ci    void CollectRegionInfo(uint32_t bcIndex);
2524514f5e3Sopenharmony_ci
2534514f5e3Sopenharmony_ci    [[nodiscard]] Circuit* GetCircuit() const
2544514f5e3Sopenharmony_ci    {
2554514f5e3Sopenharmony_ci        return circuit_;
2564514f5e3Sopenharmony_ci    }
2574514f5e3Sopenharmony_ci
2584514f5e3Sopenharmony_ci    GateRef GetGateByBcIndex(uint32_t bcIndex) const
2594514f5e3Sopenharmony_ci    {
2604514f5e3Sopenharmony_ci        ASSERT(bcIndex < byteCodeToJSGates_.size());
2614514f5e3Sopenharmony_ci        if (byteCodeToJSGates_[bcIndex].size() > 0) {
2624514f5e3Sopenharmony_ci            ASSERT(byteCodeToJSGates_[bcIndex].size() == 1);
2634514f5e3Sopenharmony_ci            return byteCodeToJSGates_[bcIndex].at(0);
2644514f5e3Sopenharmony_ci        }
2654514f5e3Sopenharmony_ci        return Circuit::NullGate();
2664514f5e3Sopenharmony_ci    }
2674514f5e3Sopenharmony_ci
2684514f5e3Sopenharmony_ci    const std::vector<GateRef>& GetGatesByBcIndex(uint32_t bcIndex) const
2694514f5e3Sopenharmony_ci    {
2704514f5e3Sopenharmony_ci        ASSERT(bcIndex < byteCodeToJSGates_.size());
2714514f5e3Sopenharmony_ci        return byteCodeToJSGates_[bcIndex];
2724514f5e3Sopenharmony_ci    }
2734514f5e3Sopenharmony_ci
2744514f5e3Sopenharmony_ci    uint32_t GetBcIndexByGate(GateRef gate) const
2754514f5e3Sopenharmony_ci    {
2764514f5e3Sopenharmony_ci        return jsGatesToByteCode_.at(gate);
2774514f5e3Sopenharmony_ci    }
2784514f5e3Sopenharmony_ci
2794514f5e3Sopenharmony_ci    bool IsBcIndexByGate(GateRef gate) const
2804514f5e3Sopenharmony_ci    {
2814514f5e3Sopenharmony_ci        if (jsGatesToByteCode_.find(gate) == jsGatesToByteCode_.end()) {
2824514f5e3Sopenharmony_ci            return false;
2834514f5e3Sopenharmony_ci        }
2844514f5e3Sopenharmony_ci        return true;
2854514f5e3Sopenharmony_ci    }
2864514f5e3Sopenharmony_ci
2874514f5e3Sopenharmony_ci    void SetOsrOffset(int32_t offset)
2884514f5e3Sopenharmony_ci    {
2894514f5e3Sopenharmony_ci        osrOffset_ = offset;
2904514f5e3Sopenharmony_ci    }
2914514f5e3Sopenharmony_ci
2924514f5e3Sopenharmony_ci    bool NeedCheckSafePointAndStackOver() const
2934514f5e3Sopenharmony_ci    {
2944514f5e3Sopenharmony_ci        return !isInline_ && !method_->IsNoGC();
2954514f5e3Sopenharmony_ci    }
2964514f5e3Sopenharmony_ci
2974514f5e3Sopenharmony_ci    void UpdateBcIndexGate(GateRef gate, uint32_t bcIndex)
2984514f5e3Sopenharmony_ci    {
2994514f5e3Sopenharmony_ci        ASSERT(gateAcc_.GetOpCode(gate) == OpCode::JS_BYTECODE);
3004514f5e3Sopenharmony_ci        ASSERT(bcIndex < byteCodeToJSGates_.size());
3014514f5e3Sopenharmony_ci        byteCodeToJSGates_[bcIndex].emplace_back(gate);
3024514f5e3Sopenharmony_ci        jsGatesToByteCode_[gate] = bcIndex;
3034514f5e3Sopenharmony_ci    }
3044514f5e3Sopenharmony_ci
3054514f5e3Sopenharmony_ci    [[nodiscard]] const MethodLiteral* GetMethod() const
3064514f5e3Sopenharmony_ci    {
3074514f5e3Sopenharmony_ci        return method_;
3084514f5e3Sopenharmony_ci    }
3094514f5e3Sopenharmony_ci
3104514f5e3Sopenharmony_ci    [[nodiscard]] const JSPandaFile *GetJSPandaFile() const
3114514f5e3Sopenharmony_ci    {
3124514f5e3Sopenharmony_ci        return file_;
3134514f5e3Sopenharmony_ci    }
3144514f5e3Sopenharmony_ci
3154514f5e3Sopenharmony_ci    const std::string& GetMethodName() const
3164514f5e3Sopenharmony_ci    {
3174514f5e3Sopenharmony_ci        return methodName_;
3184514f5e3Sopenharmony_ci    }
3194514f5e3Sopenharmony_ci
3204514f5e3Sopenharmony_ci    bool IsLogEnabled() const
3214514f5e3Sopenharmony_ci    {
3224514f5e3Sopenharmony_ci        return enableLog_;
3234514f5e3Sopenharmony_ci    }
3244514f5e3Sopenharmony_ci
3254514f5e3Sopenharmony_ci    bool IsTypeLoweringEnabled() const
3264514f5e3Sopenharmony_ci    {
3274514f5e3Sopenharmony_ci        return enableTypeLowering_;
3284514f5e3Sopenharmony_ci    }
3294514f5e3Sopenharmony_ci
3304514f5e3Sopenharmony_ci    [[nodiscard]] const std::vector<GateRef>& GetAsyncRelatedGates() const
3314514f5e3Sopenharmony_ci    {
3324514f5e3Sopenharmony_ci        return suspendAndResumeGates_;
3334514f5e3Sopenharmony_ci    }
3344514f5e3Sopenharmony_ci
3354514f5e3Sopenharmony_ci    void UpdateAsyncRelatedGate(GateRef gate)
3364514f5e3Sopenharmony_ci    {
3374514f5e3Sopenharmony_ci        suspendAndResumeGates_.emplace_back(gate);
3384514f5e3Sopenharmony_ci    };
3394514f5e3Sopenharmony_ci
3404514f5e3Sopenharmony_ci    template <class Callback>
3414514f5e3Sopenharmony_ci    void EnumerateBlock(BytecodeRegion &bb, const Callback &cb)
3424514f5e3Sopenharmony_ci    {
3434514f5e3Sopenharmony_ci        auto &iterator = bb.GetBytecodeIterator();
3444514f5e3Sopenharmony_ci        iterator.GotoStart();
3454514f5e3Sopenharmony_ci        while (!iterator.Done()) {
3464514f5e3Sopenharmony_ci            auto &bytecodeInfo = iterator.GetBytecodeInfo();
3474514f5e3Sopenharmony_ci            bool ret = cb(bytecodeInfo);
3484514f5e3Sopenharmony_ci            if (!ret) {
3494514f5e3Sopenharmony_ci                break;
3504514f5e3Sopenharmony_ci            }
3514514f5e3Sopenharmony_ci            ++iterator;
3524514f5e3Sopenharmony_ci        }
3534514f5e3Sopenharmony_ci    }
3544514f5e3Sopenharmony_ci
3554514f5e3Sopenharmony_ci    BytecodeRegion &GetBasicBlockById(size_t id)
3564514f5e3Sopenharmony_ci    {
3574514f5e3Sopenharmony_ci        ASSERT(id < graph_.size());
3584514f5e3Sopenharmony_ci        return RegionAt(id);
3594514f5e3Sopenharmony_ci    }
3604514f5e3Sopenharmony_ci
3614514f5e3Sopenharmony_ci    void AddBasicBlock(BytecodeRegion* region)
3624514f5e3Sopenharmony_ci    {
3634514f5e3Sopenharmony_ci        graph_.emplace_back(region);
3644514f5e3Sopenharmony_ci    }
3654514f5e3Sopenharmony_ci
3664514f5e3Sopenharmony_ci    size_t GetBasicBlockCount() const
3674514f5e3Sopenharmony_ci    {
3684514f5e3Sopenharmony_ci        return graph_.size();
3694514f5e3Sopenharmony_ci    }
3704514f5e3Sopenharmony_ci
3714514f5e3Sopenharmony_ci    size_t GetPcOffset(const uint8_t *pc) const
3724514f5e3Sopenharmony_ci    {
3734514f5e3Sopenharmony_ci        return static_cast<size_t>(pc - method_->GetBytecodeArray());
3744514f5e3Sopenharmony_ci    }
3754514f5e3Sopenharmony_ci
3764514f5e3Sopenharmony_ci    size_t GetPcOffset(uint32_t bcIndex) const
3774514f5e3Sopenharmony_ci    {
3784514f5e3Sopenharmony_ci        const uint8_t* pc = GetPCByIndex(bcIndex);
3794514f5e3Sopenharmony_ci        return GetPcOffset(pc);
3804514f5e3Sopenharmony_ci    }
3814514f5e3Sopenharmony_ci
3824514f5e3Sopenharmony_ci    size_t GetPcOffsetByGate(GateRef gate) const
3834514f5e3Sopenharmony_ci    {
3844514f5e3Sopenharmony_ci        return GetPcOffset(jsGatesToByteCode_.at(gate));
3854514f5e3Sopenharmony_ci    }
3864514f5e3Sopenharmony_ci
3874514f5e3Sopenharmony_ci    std::vector<ElementsKind> GetElementsKindsForUser(GateRef gate) const
3884514f5e3Sopenharmony_ci    {
3894514f5e3Sopenharmony_ci        return pgoTypeRecorder_.GetElementsKindsForUser(GetPcOffsetByGate(gate));
3904514f5e3Sopenharmony_ci    }
3914514f5e3Sopenharmony_ci
3924514f5e3Sopenharmony_ci    PUBLIC_API std::vector<ElementsKind> GetTransitionElementsKindsForUser(GateRef gate) const
3934514f5e3Sopenharmony_ci    {
3944514f5e3Sopenharmony_ci        return pgoTypeRecorder_.GetTransitionElementsKindsForUser(GetPcOffsetByGate(gate));
3954514f5e3Sopenharmony_ci    }
3964514f5e3Sopenharmony_ci
3974514f5e3Sopenharmony_ci    ElementsKind GetElementsKindForCreater(GateRef gate) const
3984514f5e3Sopenharmony_ci    {
3994514f5e3Sopenharmony_ci        return pgoTypeRecorder_.GetElementsKindForCreater(gateAcc_.TryGetPcOffset(gate));
4004514f5e3Sopenharmony_ci    }
4014514f5e3Sopenharmony_ci
4024514f5e3Sopenharmony_ci    uint32_t GetArrayElementsLength(GateRef gate) const
4034514f5e3Sopenharmony_ci    {
4044514f5e3Sopenharmony_ci        return pgoTypeRecorder_.GetElementsLength(gateAcc_.TryGetPcOffset(gate));
4054514f5e3Sopenharmony_ci    }
4064514f5e3Sopenharmony_ci
4074514f5e3Sopenharmony_ci    RegionSpaceFlag GetRegionSpaceFlag(GateRef gate) const
4084514f5e3Sopenharmony_ci    {
4094514f5e3Sopenharmony_ci        return pgoTypeRecorder_.GetRegionSpaceFlag(gateAcc_.TryGetPcOffset(gate));
4104514f5e3Sopenharmony_ci    }
4114514f5e3Sopenharmony_ci
4124514f5e3Sopenharmony_ci    bool ShouldPGOTypeInfer(GateRef gate) const
4134514f5e3Sopenharmony_ci    {
4144514f5e3Sopenharmony_ci        return jsGatesToByteCode_.find(gate) != jsGatesToByteCode_.end();
4154514f5e3Sopenharmony_ci    }
4164514f5e3Sopenharmony_ci
4174514f5e3Sopenharmony_ci    size_t GetNumberVRegs() const
4184514f5e3Sopenharmony_ci    {
4194514f5e3Sopenharmony_ci        return static_cast<size_t>(method_->GetNumberVRegs());
4204514f5e3Sopenharmony_ci    }
4214514f5e3Sopenharmony_ci
4224514f5e3Sopenharmony_ci    size_t GetNumberVRegsWithEnv() const
4234514f5e3Sopenharmony_ci    {
4244514f5e3Sopenharmony_ci        return GetNumberVRegs() + 1; // 1: env variable
4254514f5e3Sopenharmony_ci    }
4264514f5e3Sopenharmony_ci
4274514f5e3Sopenharmony_ci    size_t GetEnvVregIdx() const
4284514f5e3Sopenharmony_ci    {
4294514f5e3Sopenharmony_ci        return GetNumberVRegs();
4304514f5e3Sopenharmony_ci    }
4314514f5e3Sopenharmony_ci
4324514f5e3Sopenharmony_ci    Bytecodes *GetBytecodes() const
4334514f5e3Sopenharmony_ci    {
4344514f5e3Sopenharmony_ci        return bytecodes_;
4354514f5e3Sopenharmony_ci    }
4364514f5e3Sopenharmony_ci
4374514f5e3Sopenharmony_ci    uint32_t GetLastBcIndex() const
4384514f5e3Sopenharmony_ci    {
4394514f5e3Sopenharmony_ci        ASSERT(pcOffsets_.size() > 0);
4404514f5e3Sopenharmony_ci        return static_cast<uint32_t>(pcOffsets_.size() - 1);
4414514f5e3Sopenharmony_ci    }
4424514f5e3Sopenharmony_ci
4434514f5e3Sopenharmony_ci    const uint8_t *GetPCByIndex(uint32_t index) const
4444514f5e3Sopenharmony_ci    {
4454514f5e3Sopenharmony_ci        ASSERT(index <= GetLastBcIndex());
4464514f5e3Sopenharmony_ci        return pcOffsets_[index];
4474514f5e3Sopenharmony_ci    }
4484514f5e3Sopenharmony_ci
4494514f5e3Sopenharmony_ci    const uint8_t *GetFirstPC() const
4504514f5e3Sopenharmony_ci    {
4514514f5e3Sopenharmony_ci        return GetPCByIndex(0);
4524514f5e3Sopenharmony_ci    }
4534514f5e3Sopenharmony_ci
4544514f5e3Sopenharmony_ci    const uint8_t *GetLastPC() const
4554514f5e3Sopenharmony_ci    {
4564514f5e3Sopenharmony_ci        return GetPCByIndex(GetLastBcIndex());
4574514f5e3Sopenharmony_ci    }
4584514f5e3Sopenharmony_ci
4594514f5e3Sopenharmony_ci    uint32_t FindBcIndexByPc(const uint8_t *pc) const
4604514f5e3Sopenharmony_ci    {
4614514f5e3Sopenharmony_ci        auto begin = pcOffsets_.begin();
4624514f5e3Sopenharmony_ci        auto end = pcOffsets_.end();
4634514f5e3Sopenharmony_ci        auto it = std::lower_bound(begin, end, pc);
4644514f5e3Sopenharmony_ci        ASSERT(it != end);
4654514f5e3Sopenharmony_ci        ASSERT(*it == pc);
4664514f5e3Sopenharmony_ci        return std::distance(begin, it);
4674514f5e3Sopenharmony_ci    }
4684514f5e3Sopenharmony_ci
4694514f5e3Sopenharmony_ci    const BytecodeInfo &GetBytecodeInfo(uint32_t index) const
4704514f5e3Sopenharmony_ci    {
4714514f5e3Sopenharmony_ci        return infoData_[index];
4724514f5e3Sopenharmony_ci    }
4734514f5e3Sopenharmony_ci
4744514f5e3Sopenharmony_ci    bool HasTryCatch() const
4754514f5e3Sopenharmony_ci    {
4764514f5e3Sopenharmony_ci        return hasTryCatch_;
4774514f5e3Sopenharmony_ci    }
4784514f5e3Sopenharmony_ci
4794514f5e3Sopenharmony_ci    bool EnableLoopOptimization() const
4804514f5e3Sopenharmony_ci    {
4814514f5e3Sopenharmony_ci        return (!HasTryCatch()) && frameStateBuilder_.HasLoop();
4824514f5e3Sopenharmony_ci    }
4834514f5e3Sopenharmony_ci
4844514f5e3Sopenharmony_ci    void RemoveUnreachableRegion();
4854514f5e3Sopenharmony_ci
4864514f5e3Sopenharmony_ci    GateRef GetFrameArgs() const
4874514f5e3Sopenharmony_ci    {
4884514f5e3Sopenharmony_ci        return argAcc_.GetFrameArgs();
4894514f5e3Sopenharmony_ci    }
4904514f5e3Sopenharmony_ci
4914514f5e3Sopenharmony_ci    GateRef GetPreFrameState() const
4924514f5e3Sopenharmony_ci    {
4934514f5e3Sopenharmony_ci        return preFrameState_;
4944514f5e3Sopenharmony_ci    }
4954514f5e3Sopenharmony_ci
4964514f5e3Sopenharmony_ci    void SetPreFrameState(GateRef gate)
4974514f5e3Sopenharmony_ci    {
4984514f5e3Sopenharmony_ci        preFrameState_ = gate;
4994514f5e3Sopenharmony_ci    }
5004514f5e3Sopenharmony_ci
5014514f5e3Sopenharmony_ci    GateRef GetPreFrameArgs() const
5024514f5e3Sopenharmony_ci    {
5034514f5e3Sopenharmony_ci        return preFrameArgs_;
5044514f5e3Sopenharmony_ci    }
5054514f5e3Sopenharmony_ci
5064514f5e3Sopenharmony_ci    void SetPreFrameArgs(GateRef gate)
5074514f5e3Sopenharmony_ci    {
5084514f5e3Sopenharmony_ci        preFrameArgs_ = gate;
5094514f5e3Sopenharmony_ci    }
5104514f5e3Sopenharmony_ci
5114514f5e3Sopenharmony_ci    inline bool IsEntryBlock(const size_t bbId) const
5124514f5e3Sopenharmony_ci    {
5134514f5e3Sopenharmony_ci        return bbId == 0;
5144514f5e3Sopenharmony_ci    }
5154514f5e3Sopenharmony_ci
5164514f5e3Sopenharmony_ci    inline bool IsFirstBasicBlock(const size_t bbId) const
5174514f5e3Sopenharmony_ci    {
5184514f5e3Sopenharmony_ci        return bbId == 1;
5194514f5e3Sopenharmony_ci    }
5204514f5e3Sopenharmony_ci
5214514f5e3Sopenharmony_ci    const PGOTypeRecorder *GetPGOTypeRecorder() const
5224514f5e3Sopenharmony_ci    {
5234514f5e3Sopenharmony_ci        return &pgoTypeRecorder_;
5244514f5e3Sopenharmony_ci    }
5254514f5e3Sopenharmony_ci
5264514f5e3Sopenharmony_ci    GateRef GetArgGate(const size_t currentVreg) const
5274514f5e3Sopenharmony_ci    {
5284514f5e3Sopenharmony_ci        return argAcc_.GetArgGate(currentVreg);
5294514f5e3Sopenharmony_ci    }
5304514f5e3Sopenharmony_ci
5314514f5e3Sopenharmony_ci    GateRef ArgGateNotExisted(const size_t currentVreg)
5324514f5e3Sopenharmony_ci    {
5334514f5e3Sopenharmony_ci        return argAcc_.ArgGateNotExisted(currentVreg);
5344514f5e3Sopenharmony_ci    }
5354514f5e3Sopenharmony_ci
5364514f5e3Sopenharmony_ci    ChunkVector<GateRef>& GetLoopHeaderGates()
5374514f5e3Sopenharmony_ci    {
5384514f5e3Sopenharmony_ci        return loopHeaderGates_;
5394514f5e3Sopenharmony_ci    }
5404514f5e3Sopenharmony_ci
5414514f5e3Sopenharmony_ci    size_t NumberOfLiveBlock() const
5424514f5e3Sopenharmony_ci    {
5434514f5e3Sopenharmony_ci        return numOfLiveBB_;
5444514f5e3Sopenharmony_ci    }
5454514f5e3Sopenharmony_ci
5464514f5e3Sopenharmony_ci    int32_t GetCurrentConstpoolId() const
5474514f5e3Sopenharmony_ci    {
5484514f5e3Sopenharmony_ci        panda_file::IndexAccessor indexAccessor(*file_->GetPandaFile(), panda_file::File::EntityId(methodId_));
5494514f5e3Sopenharmony_ci        return static_cast<int32_t>(indexAccessor.GetHeaderIndex());
5504514f5e3Sopenharmony_ci    }
5514514f5e3Sopenharmony_ci
5524514f5e3Sopenharmony_ci    void GetCurrentConstpool(GateRef jsFunc, GateRef &sharedConstPool, GateRef &unSharedConstPool)
5534514f5e3Sopenharmony_ci    {
5544514f5e3Sopenharmony_ci        int32_t constpoolId = GetCurrentConstpoolId();
5554514f5e3Sopenharmony_ci        if (gateAcc_.GetOpCode(preFrameArgs_) == OpCode::CIRCUIT_ROOT) {
5564514f5e3Sopenharmony_ci            sharedConstPool = circuit_->NewGate(circuit_->GetSharedConstPool(constpoolId), MachineType::I64, {jsFunc},
5574514f5e3Sopenharmony_ci                                                GateType::AnyType());
5584514f5e3Sopenharmony_ci            unSharedConstPool = circuit_->NewGate(circuit_->GetUnsharedConstPool(), MachineType::I64,
5594514f5e3Sopenharmony_ci                                                  {sharedConstPool}, GateType::AnyType());
5604514f5e3Sopenharmony_ci        }
5614514f5e3Sopenharmony_ci        GateRef frameArgs = preFrameArgs_;
5624514f5e3Sopenharmony_ci        GateRef preSharedConstPool = Circuit::NullGate();
5634514f5e3Sopenharmony_ci        GateRef preUnsharedConstPool = Circuit::NullGate();
5644514f5e3Sopenharmony_ci        int32_t preConstpoolId = 0;
5654514f5e3Sopenharmony_ci        while (gateAcc_.GetOpCode(frameArgs) != OpCode::CIRCUIT_ROOT) {
5664514f5e3Sopenharmony_ci            preSharedConstPool = gateAcc_.GetValueIn(frameArgs, static_cast<size_t>(FrameArgIdx::SHARED_CONST_POOL));
5674514f5e3Sopenharmony_ci            preUnsharedConstPool =
5684514f5e3Sopenharmony_ci                gateAcc_.GetValueIn(frameArgs, static_cast<size_t>(FrameArgIdx::UNSHARED_CONST_POOL));
5694514f5e3Sopenharmony_ci            preConstpoolId = static_cast<int32_t>(gateAcc_.GetConstpoolId(preSharedConstPool));
5704514f5e3Sopenharmony_ci            if (preConstpoolId == constpoolId) {
5714514f5e3Sopenharmony_ci                sharedConstPool = preSharedConstPool;
5724514f5e3Sopenharmony_ci                unSharedConstPool = preUnsharedConstPool;
5734514f5e3Sopenharmony_ci                break;
5744514f5e3Sopenharmony_ci            }
5754514f5e3Sopenharmony_ci            frameArgs = gateAcc_.GetFrameState(frameArgs);
5764514f5e3Sopenharmony_ci        }
5774514f5e3Sopenharmony_ci    }
5784514f5e3Sopenharmony_ci
5794514f5e3Sopenharmony_ci    void SetIrreducibleLoop()
5804514f5e3Sopenharmony_ci    {
5814514f5e3Sopenharmony_ci        isIrreducible_ = true;
5824514f5e3Sopenharmony_ci    }
5834514f5e3Sopenharmony_ci
5844514f5e3Sopenharmony_ci    bool HasIrreducibleLoop() const
5854514f5e3Sopenharmony_ci    {
5864514f5e3Sopenharmony_ci        return isIrreducible_;
5874514f5e3Sopenharmony_ci    }
5884514f5e3Sopenharmony_ci
5894514f5e3Sopenharmony_ci    void SetJitCompile()
5904514f5e3Sopenharmony_ci    {
5914514f5e3Sopenharmony_ci        isJitCompile_ = true;
5924514f5e3Sopenharmony_ci    }
5934514f5e3Sopenharmony_ci
5944514f5e3Sopenharmony_ci    bool IsJitCompile() const
5954514f5e3Sopenharmony_ci    {
5964514f5e3Sopenharmony_ci        return isJitCompile_;
5974514f5e3Sopenharmony_ci    }
5984514f5e3Sopenharmony_ci
5994514f5e3Sopenharmony_ci    void SetPreAnalysis()
6004514f5e3Sopenharmony_ci    {
6014514f5e3Sopenharmony_ci        preAnalysis_ = true;
6024514f5e3Sopenharmony_ci    }
6034514f5e3Sopenharmony_ci
6044514f5e3Sopenharmony_ci    bool IsPreAnalysis() const
6054514f5e3Sopenharmony_ci    {
6064514f5e3Sopenharmony_ci        return preAnalysis_;
6074514f5e3Sopenharmony_ci    }
6084514f5e3Sopenharmony_ci
6094514f5e3Sopenharmony_ci    bool NeedIrreducibleLoopCheck() const
6104514f5e3Sopenharmony_ci    {
6114514f5e3Sopenharmony_ci        return IsPreAnalysis() || IsJitCompile();
6124514f5e3Sopenharmony_ci    }
6134514f5e3Sopenharmony_ci
6144514f5e3Sopenharmony_ci    bool TerminateAnalysis() const
6154514f5e3Sopenharmony_ci    {
6164514f5e3Sopenharmony_ci        return IsPreAnalysis() || HasIrreducibleLoop();
6174514f5e3Sopenharmony_ci    }
6184514f5e3Sopenharmony_ci
6194514f5e3Sopenharmony_ci    bool IsOSR() const
6204514f5e3Sopenharmony_ci    {
6214514f5e3Sopenharmony_ci        return osrOffset_ != MachineCode::INVALID_OSR_OFFSET;
6224514f5e3Sopenharmony_ci    }
6234514f5e3Sopenharmony_ci
6244514f5e3Sopenharmony_ci    bool IsCacheBBOfOSRLoop(const BytecodeRegion &bb) const
6254514f5e3Sopenharmony_ci    {
6264514f5e3Sopenharmony_ci        return catchBBOfOSRLoop_.find(&bb) != catchBBOfOSRLoop_.end();
6274514f5e3Sopenharmony_ci    }
6284514f5e3Sopenharmony_ci
6294514f5e3Sopenharmony_ci    void ComputeNumOfLoopBack();
6304514f5e3Sopenharmony_ci
6314514f5e3Sopenharmony_ci    enum class MarkState : uint8_t {
6324514f5e3Sopenharmony_ci        UNVISITED = 0,
6334514f5e3Sopenharmony_ci        ON_STACK,
6344514f5e3Sopenharmony_ci        PENDING,
6354514f5e3Sopenharmony_ci        VISITED,
6364514f5e3Sopenharmony_ci        VISITED1,
6374514f5e3Sopenharmony_ci        UNVISITED1 = VISITED
6384514f5e3Sopenharmony_ci    };
6394514f5e3Sopenharmony_ci
6404514f5e3Sopenharmony_ci    struct VisitedInfo {
6414514f5e3Sopenharmony_ci        size_t needVisitIndex;
6424514f5e3Sopenharmony_ci        bool isVisitedCatchBlock = false;
6434514f5e3Sopenharmony_ci    };
6444514f5e3Sopenharmony_ci    bool IsAncestor(size_t nodeA, size_t nodeB);
6454514f5e3Sopenharmony_ci
6464514f5e3Sopenharmony_ciprivate:
6474514f5e3Sopenharmony_ci    void CollectTryCatchBlockInfo(ExceptionInfo &Exception);
6484514f5e3Sopenharmony_ci    void BuildCatchBlocks(const ExceptionInfo &Exception);
6494514f5e3Sopenharmony_ci    void BuildEntryBlock();
6504514f5e3Sopenharmony_ci    void BuildBasicBlock();
6514514f5e3Sopenharmony_ci    void BuildRegions(const ExceptionInfo &Exception);
6524514f5e3Sopenharmony_ci    // build circuit
6534514f5e3Sopenharmony_ci    void BuildCircuitArgs();
6544514f5e3Sopenharmony_ci    void BuildOSRArgs();
6554514f5e3Sopenharmony_ci    std::vector<GateRef> CreateGateInList(const BytecodeInfo &info, const GateMetaData *meta);
6564514f5e3Sopenharmony_ci    GateRef NewConst(const BytecodeInfo &info);
6574514f5e3Sopenharmony_ci    void NewJSGate(BytecodeRegion &bb);
6584514f5e3Sopenharmony_ci    void NewJump(BytecodeRegion &bbd);
6594514f5e3Sopenharmony_ci    GateRef NewReturn(BytecodeRegion &bb);
6604514f5e3Sopenharmony_ci    void NewByteCode(BytecodeRegion &bb);
6614514f5e3Sopenharmony_ci    void MergeThrowGate(BytecodeRegion &bb, uint32_t bcIndex);
6624514f5e3Sopenharmony_ci    void MergeExceptionGete(BytecodeRegion &bb, const BytecodeInfo& bytecodeInfo, uint32_t bcIndex);
6634514f5e3Sopenharmony_ci    void BuildSubCircuit();
6644514f5e3Sopenharmony_ci    bool FindOsrLoopHeadBB();
6654514f5e3Sopenharmony_ci    void GenDeoptAndReturnForOsrLoopExit(BytecodeRegion& osrLoopExitBB);
6664514f5e3Sopenharmony_ci    void CollectCacheBBforOSRLoop(BytecodeRegion *bb);
6674514f5e3Sopenharmony_ci    void HandleOsrLoopBody(BytecodeRegion &osrLoopBodyBB);
6684514f5e3Sopenharmony_ci    void BuildOsrCircuit();
6694514f5e3Sopenharmony_ci
6704514f5e3Sopenharmony_ci    void UpdateCFG();
6714514f5e3Sopenharmony_ci    void CollectTryPredsInfo();
6724514f5e3Sopenharmony_ci    void ClearUnreachableRegion(ChunkVector<BytecodeRegion*>& pendingList);
6734514f5e3Sopenharmony_ci    void RemoveUnusedPredsInfo(BytecodeRegion& bb);
6744514f5e3Sopenharmony_ci    void BuildCircuit();
6754514f5e3Sopenharmony_ci    void PrintGraph();
6764514f5e3Sopenharmony_ci    void PrintBBInfo();
6774514f5e3Sopenharmony_ci    void PrintGraph(const char* title);
6784514f5e3Sopenharmony_ci    void PrintBytecodeInfo(BytecodeRegion& region);
6794514f5e3Sopenharmony_ci    void PrintDefsitesInfo(const std::unordered_map<uint16_t, std::set<size_t>> &defsitesInfo);
6804514f5e3Sopenharmony_ci    void BuildRegionInfo();
6814514f5e3Sopenharmony_ci    void BuildFrameArgs();
6824514f5e3Sopenharmony_ci    void RemoveIfInRpoList(BytecodeRegion *bb);
6834514f5e3Sopenharmony_ci    void PerformDFS(const std::vector<size_t> &immDom, size_t listSize);
6844514f5e3Sopenharmony_ci    void ReducibilityCheck();
6854514f5e3Sopenharmony_ci    void ComputeImmediateDominators(const std::vector<size_t> &basicBlockList,
6864514f5e3Sopenharmony_ci                                    std::unordered_map<size_t, size_t> &dfsFatherIdx, std::vector<size_t> &immDom,
6874514f5e3Sopenharmony_ci                                    std::unordered_map<size_t, size_t> &bbDfsTimestampToIdx);
6884514f5e3Sopenharmony_ci    void ComputeDominatorTree(std::vector<size_t> &basicBlockList, std::vector<size_t> &immDom,
6894514f5e3Sopenharmony_ci        std::unordered_map<size_t, size_t> &bbDfsTimestampToIdx);
6904514f5e3Sopenharmony_ci
6914514f5e3Sopenharmony_ci    BytecodeRegion &RegionAt(size_t i)
6924514f5e3Sopenharmony_ci    {
6934514f5e3Sopenharmony_ci        return *graph_[i];
6944514f5e3Sopenharmony_ci    }
6954514f5e3Sopenharmony_ci
6964514f5e3Sopenharmony_ci    Circuit *circuit_;
6974514f5e3Sopenharmony_ci    std::vector<std::vector<GateRef>> byteCodeToJSGates_;
6984514f5e3Sopenharmony_ci    std::unordered_map<GateRef, size_t> jsGatesToByteCode_;
6994514f5e3Sopenharmony_ci    BytecodeGraph graph_;
7004514f5e3Sopenharmony_ci    const JSPandaFile *file_ {nullptr};
7014514f5e3Sopenharmony_ci    const MethodLiteral *method_ {nullptr};
7024514f5e3Sopenharmony_ci    GateAccessor gateAcc_;
7034514f5e3Sopenharmony_ci    ArgumentAccessor argAcc_;
7044514f5e3Sopenharmony_ci    PGOTypeRecorder pgoTypeRecorder_;
7054514f5e3Sopenharmony_ci    int32_t osrOffset_ {MachineCode::INVALID_OSR_OFFSET};
7064514f5e3Sopenharmony_ci    bool enableLog_ {false};
7074514f5e3Sopenharmony_ci    bool enableTypeLowering_ {false};
7084514f5e3Sopenharmony_ci    std::vector<GateRef> suspendAndResumeGates_ {};
7094514f5e3Sopenharmony_ci    std::vector<const uint8_t*> pcOffsets_;
7104514f5e3Sopenharmony_ci    FrameStateBuilder frameStateBuilder_;
7114514f5e3Sopenharmony_ci    std::string methodName_;
7124514f5e3Sopenharmony_ci    const CString &recordName_;
7134514f5e3Sopenharmony_ci    Bytecodes *bytecodes_;
7144514f5e3Sopenharmony_ci    RegionsInfo regionsInfo_{};
7154514f5e3Sopenharmony_ci    std::vector<BytecodeInfo> infoData_ {};
7164514f5e3Sopenharmony_ci    bool hasTryCatch_ {false};
7174514f5e3Sopenharmony_ci    ChunkVector<GateRef> loopHeaderGates_;
7184514f5e3Sopenharmony_ci    GateRef preFrameState_ {Circuit::NullGate()};
7194514f5e3Sopenharmony_ci    GateRef preFrameArgs_ {Circuit::NullGate()};
7204514f5e3Sopenharmony_ci    size_t numOfLiveBB_ {0};
7214514f5e3Sopenharmony_ci    bool isInline_ {false};
7224514f5e3Sopenharmony_ci    uint32_t methodId_ {0};
7234514f5e3Sopenharmony_ci    bool preAnalysis_ {false};
7244514f5e3Sopenharmony_ci    std::set<const BytecodeRegion *> catchBBOfOSRLoop_{};
7254514f5e3Sopenharmony_ci    bool isIrreducible_ {false};
7264514f5e3Sopenharmony_ci    bool isJitCompile_ {false};
7274514f5e3Sopenharmony_ci    CVector<size_t> timeIn_ {};
7284514f5e3Sopenharmony_ci    CVector<size_t> timeOut_ {};
7294514f5e3Sopenharmony_ci    std::unordered_map<size_t, size_t> bbIdToDfsTimestamp_ {};
7304514f5e3Sopenharmony_ci};
7314514f5e3Sopenharmony_ci}  // namespace panda::ecmascript::kungfu
7324514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
733