14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2023 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/compiler/lexical_env_specialization_pass.h"
174514f5e3Sopenharmony_ci#include "ecmascript/compiler/bytecodes.h"
184514f5e3Sopenharmony_ci#include "ecmascript/compiler/scheduler.h"
194514f5e3Sopenharmony_ci
204514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
214514f5e3Sopenharmony_civoid LexicalEnvSpecializationPass::Initialize()
224514f5e3Sopenharmony_ci{
234514f5e3Sopenharmony_ci    dependChains_.resize(circuit_->GetMaxGateId() + 1, nullptr); // 1: +1 for size
244514f5e3Sopenharmony_ci    GateRef entry = acc_.GetDependRoot();
254514f5e3Sopenharmony_ci    VisitDependEntry(entry);
264514f5e3Sopenharmony_ci}
274514f5e3Sopenharmony_ci
284514f5e3Sopenharmony_ciGateRef LexicalEnvSpecializationPass::VisitDependEntry(GateRef gate)
294514f5e3Sopenharmony_ci{
304514f5e3Sopenharmony_ci    auto empty = new (chunk_) DependChains(chunk_);
314514f5e3Sopenharmony_ci    return UpdateDependChain(gate, empty);
324514f5e3Sopenharmony_ci}
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_ciGateRef LexicalEnvSpecializationPass::VisitGate(GateRef gate)
354514f5e3Sopenharmony_ci{
364514f5e3Sopenharmony_ci    auto opcode = acc_.GetOpCode(gate);
374514f5e3Sopenharmony_ci    switch (opcode) {
384514f5e3Sopenharmony_ci        case OpCode::JS_BYTECODE: {
394514f5e3Sopenharmony_ci            EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
404514f5e3Sopenharmony_ci            if (Bytecodes::IsLdLexVarOp(ecmaOpcode)) {
414514f5e3Sopenharmony_ci                return TrySpecializeLdLexVar(gate);
424514f5e3Sopenharmony_ci            }
434514f5e3Sopenharmony_ci            return VisitOther(gate);
444514f5e3Sopenharmony_ci        }
454514f5e3Sopenharmony_ci        case OpCode::DEPEND_SELECTOR:
464514f5e3Sopenharmony_ci            return VisitDependSelector(gate);
474514f5e3Sopenharmony_ci        default:
484514f5e3Sopenharmony_ci            if (acc_.GetDependCount(gate) == 1) { // 1: depend in is 1
494514f5e3Sopenharmony_ci                return VisitOther(gate);
504514f5e3Sopenharmony_ci            }
514514f5e3Sopenharmony_ci    }
524514f5e3Sopenharmony_ci    return Circuit::NullGate();
534514f5e3Sopenharmony_ci}
544514f5e3Sopenharmony_ci
554514f5e3Sopenharmony_ciGateRef LexicalEnvSpecializationPass::VisitOther(GateRef gate)
564514f5e3Sopenharmony_ci{
574514f5e3Sopenharmony_ci    ASSERT(acc_.GetDependCount(gate) >= 1);
584514f5e3Sopenharmony_ci    auto depIn = acc_.GetDep(gate);
594514f5e3Sopenharmony_ci    auto dependChain = GetDependChain(depIn);
604514f5e3Sopenharmony_ci    if (dependChain == nullptr) {
614514f5e3Sopenharmony_ci        return Circuit::NullGate();
624514f5e3Sopenharmony_ci    }
634514f5e3Sopenharmony_ci    dependChain = dependChain->UpdateNode(gate);
644514f5e3Sopenharmony_ci    return UpdateDependChain(gate, dependChain);
654514f5e3Sopenharmony_ci}
664514f5e3Sopenharmony_ci
674514f5e3Sopenharmony_ciGateRef LexicalEnvSpecializationPass::VisitDependSelector(GateRef gate)
684514f5e3Sopenharmony_ci{
694514f5e3Sopenharmony_ci    auto state = acc_.GetState(gate);
704514f5e3Sopenharmony_ci    if (acc_.IsLoopHead(state)) {
714514f5e3Sopenharmony_ci        // use loop head as depend chain
724514f5e3Sopenharmony_ci        return VisitOther(gate);
734514f5e3Sopenharmony_ci    }
744514f5e3Sopenharmony_ci
754514f5e3Sopenharmony_ci    auto dependCount = acc_.GetDependCount(gate);
764514f5e3Sopenharmony_ci    for (size_t i = 0; i < dependCount; ++i) {
774514f5e3Sopenharmony_ci        auto depend = acc_.GetDep(gate, i);
784514f5e3Sopenharmony_ci        auto dependChain = GetDependChain(depend);
794514f5e3Sopenharmony_ci        if (dependChain == nullptr) {
804514f5e3Sopenharmony_ci            return Circuit::NullGate();
814514f5e3Sopenharmony_ci        }
824514f5e3Sopenharmony_ci    }
834514f5e3Sopenharmony_ci
844514f5e3Sopenharmony_ci    // all depend done.
854514f5e3Sopenharmony_ci    auto depend = acc_.GetDep(gate);
864514f5e3Sopenharmony_ci    auto dependChain = GetDependChain(depend);
874514f5e3Sopenharmony_ci    DependChains* copy = new (chunk_) DependChains(chunk_);
884514f5e3Sopenharmony_ci    copy->CopyFrom(dependChain);
894514f5e3Sopenharmony_ci    for (size_t i = 1; i < dependCount; ++i) { // 1: second in
904514f5e3Sopenharmony_ci        auto dependIn = acc_.GetDep(gate, i);
914514f5e3Sopenharmony_ci        auto tempChain = GetDependChain(dependIn);
924514f5e3Sopenharmony_ci        copy->Merge(tempChain);
934514f5e3Sopenharmony_ci    }
944514f5e3Sopenharmony_ci    HasNotdomStLexVarOrCall(gate, copy->GetHeadGate());
954514f5e3Sopenharmony_ci    return UpdateDependChain(gate, copy);
964514f5e3Sopenharmony_ci}
974514f5e3Sopenharmony_ci
984514f5e3Sopenharmony_ciGateRef LexicalEnvSpecializationPass::UpdateDependChain(GateRef gate, DependChains* dependChain)
994514f5e3Sopenharmony_ci{
1004514f5e3Sopenharmony_ci    ASSERT(dependChain != nullptr);
1014514f5e3Sopenharmony_ci    auto oldDependChain = GetDependChain(gate);
1024514f5e3Sopenharmony_ci    if (dependChain->Equals(oldDependChain)) {
1034514f5e3Sopenharmony_ci        return Circuit::NullGate();
1044514f5e3Sopenharmony_ci    }
1054514f5e3Sopenharmony_ci    dependChains_[acc_.GetId(gate)] = dependChain;
1064514f5e3Sopenharmony_ci    return gate;
1074514f5e3Sopenharmony_ci}
1084514f5e3Sopenharmony_ci
1094514f5e3Sopenharmony_ciGateRef LexicalEnvSpecializationPass::TrySpecializeLdLexVar(GateRef gate)
1104514f5e3Sopenharmony_ci{
1114514f5e3Sopenharmony_ci    ASSERT(acc_.GetDependCount(gate) == 1);
1124514f5e3Sopenharmony_ci    auto depIn = acc_.GetDep(gate);
1134514f5e3Sopenharmony_ci    auto dependChain = GetDependChain(depIn);
1144514f5e3Sopenharmony_ci    // dependChain is null
1154514f5e3Sopenharmony_ci    if (dependChain == nullptr) {
1164514f5e3Sopenharmony_ci        return Circuit::NullGate();
1174514f5e3Sopenharmony_ci    }
1184514f5e3Sopenharmony_ci    auto stlexvarGate = LookupStLexvarNode(dependChain, gate);
1194514f5e3Sopenharmony_ci    if (stlexvarGate != Circuit::NullGate()) {
1204514f5e3Sopenharmony_ci        return acc_.GetValueIn(stlexvarGate, 3); // 3: stlexvar value in
1214514f5e3Sopenharmony_ci    }
1224514f5e3Sopenharmony_ci
1234514f5e3Sopenharmony_ci    // update gate, for others elimination
1244514f5e3Sopenharmony_ci    dependChain = dependChain->UpdateNode(gate);
1254514f5e3Sopenharmony_ci    return UpdateDependChain(gate, dependChain);
1264514f5e3Sopenharmony_ci}
1274514f5e3Sopenharmony_ci
1284514f5e3Sopenharmony_cibool LexicalEnvSpecializationPass::SearchStLexVar(GateRef gate, GateRef ldLexVar, GateRef &result)
1294514f5e3Sopenharmony_ci{
1304514f5e3Sopenharmony_ci    if (HasNotDomIllegalOp(gate)) {
1314514f5e3Sopenharmony_ci        result = ldLexVar;
1324514f5e3Sopenharmony_ci        return false;
1334514f5e3Sopenharmony_ci    }
1344514f5e3Sopenharmony_ci
1354514f5e3Sopenharmony_ci    if (acc_.GetOpCode(gate) != OpCode::JS_BYTECODE) {
1364514f5e3Sopenharmony_ci        return false;
1374514f5e3Sopenharmony_ci    }
1384514f5e3Sopenharmony_ci
1394514f5e3Sopenharmony_ci    EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
1404514f5e3Sopenharmony_ci    if (Bytecodes::IsStLexVarOp(ecmaOpcode)) {
1414514f5e3Sopenharmony_ci        if (CheckStLexVar(gate, ldLexVar)) {
1424514f5e3Sopenharmony_ci            result = gate;
1434514f5e3Sopenharmony_ci            specializeId_.emplace_back(acc_.GetId(ldLexVar));
1444514f5e3Sopenharmony_ci            return true;
1454514f5e3Sopenharmony_ci        }
1464514f5e3Sopenharmony_ci        return false;
1474514f5e3Sopenharmony_ci    }
1484514f5e3Sopenharmony_ci
1494514f5e3Sopenharmony_ci    if (Bytecodes::IsCallOrAccessorOp(ecmaOpcode)) {
1504514f5e3Sopenharmony_ci        result = ldLexVar;
1514514f5e3Sopenharmony_ci        return false;
1524514f5e3Sopenharmony_ci    }
1534514f5e3Sopenharmony_ci
1544514f5e3Sopenharmony_ci    return false;
1554514f5e3Sopenharmony_ci}
1564514f5e3Sopenharmony_ci
1574514f5e3Sopenharmony_cibool LexicalEnvSpecializationPass::CheckStLexVar(GateRef gate, GateRef ldldLexVar)
1584514f5e3Sopenharmony_ci{
1594514f5e3Sopenharmony_ci    int32_t ldLevel = static_cast<int32_t>(acc_.TryGetValue(acc_.GetValueIn(ldldLexVar, 0)));
1604514f5e3Sopenharmony_ci    int32_t ldSlot = static_cast<int32_t>(acc_.TryGetValue(acc_.GetValueIn(ldldLexVar, 1))); // 1: slot
1614514f5e3Sopenharmony_ci
1624514f5e3Sopenharmony_ci    int32_t stLevel = static_cast<int32_t>(acc_.TryGetValue(acc_.GetValueIn(gate, 0)));
1634514f5e3Sopenharmony_ci    int32_t stSlot = static_cast<int32_t>(acc_.TryGetValue(acc_.GetValueIn(gate, 1))); // 1: slot
1644514f5e3Sopenharmony_ci    if (stSlot != ldSlot) {
1654514f5e3Sopenharmony_ci        return false;
1664514f5e3Sopenharmony_ci    }
1674514f5e3Sopenharmony_ci    int32_t depth = 0;
1684514f5e3Sopenharmony_ci    GateRef ldEnv = acc_.GetValueIn(ldldLexVar, 2);
1694514f5e3Sopenharmony_ci    GateRef stEnv = acc_.GetValueIn(gate, 2);
1704514f5e3Sopenharmony_ci    if (caclulateDistanceToTarget(ldEnv, stEnv, depth)) {
1714514f5e3Sopenharmony_ci        return (ldLevel == stLevel + depth);
1724514f5e3Sopenharmony_ci    }
1734514f5e3Sopenharmony_ci
1744514f5e3Sopenharmony_ci    depth = 0;
1754514f5e3Sopenharmony_ci    if (caclulateDistanceToTarget(stEnv, ldEnv, depth)) {
1764514f5e3Sopenharmony_ci        return (ldLevel + depth == stLevel);
1774514f5e3Sopenharmony_ci    }
1784514f5e3Sopenharmony_ci    return false;
1794514f5e3Sopenharmony_ci}
1804514f5e3Sopenharmony_ci
1814514f5e3Sopenharmony_cibool LexicalEnvSpecializationPass::caclulateDistanceToTarget(GateRef startEnv, GateRef targetEnv, int32_t &dis)
1824514f5e3Sopenharmony_ci{
1834514f5e3Sopenharmony_ci    GateRef curEnv = startEnv;
1844514f5e3Sopenharmony_ci    while (true) {
1854514f5e3Sopenharmony_ci        if (curEnv == targetEnv) {
1864514f5e3Sopenharmony_ci            return true;
1874514f5e3Sopenharmony_ci        }
1884514f5e3Sopenharmony_ci        if (acc_.GetOpCode(curEnv) == OpCode::GET_ENV) {
1894514f5e3Sopenharmony_ci            return false;
1904514f5e3Sopenharmony_ci        }
1914514f5e3Sopenharmony_ci        if (acc_.GetOpCode(curEnv) != OpCode::JS_BYTECODE) {
1924514f5e3Sopenharmony_ci            return false;
1934514f5e3Sopenharmony_ci        }
1944514f5e3Sopenharmony_ci        EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(curEnv);
1954514f5e3Sopenharmony_ci        if (ecmaOpcode != EcmaOpcode::POPLEXENV) {
1964514f5e3Sopenharmony_ci            ++dis;
1974514f5e3Sopenharmony_ci        } else {
1984514f5e3Sopenharmony_ci            --dis;
1994514f5e3Sopenharmony_ci        }
2004514f5e3Sopenharmony_ci        ASSERT(acc_.GetNumValueIn(curEnv) > 0);
2014514f5e3Sopenharmony_ci        curEnv = acc_.GetValueIn(curEnv, acc_.GetNumValueIn(curEnv) - 1); // 1: env value in
2024514f5e3Sopenharmony_ci    }
2034514f5e3Sopenharmony_ci    return false;
2044514f5e3Sopenharmony_ci}
2054514f5e3Sopenharmony_ci
2064514f5e3Sopenharmony_civoid LexicalEnvSpecializationPass::HasNotdomStLexVarOrCall(GateRef gate, GateRef next)
2074514f5e3Sopenharmony_ci{
2084514f5e3Sopenharmony_ci    ASSERT(acc_.GetOpCode(gate) == OpCode::DEPEND_SELECTOR);
2094514f5e3Sopenharmony_ci    ChunkVector<GateRef> vec(chunk_);
2104514f5e3Sopenharmony_ci    ChunkVector<GateRef> visited(chunk_);
2114514f5e3Sopenharmony_ci    vec.emplace_back(gate);
2124514f5e3Sopenharmony_ci    while (!vec.empty()) {
2134514f5e3Sopenharmony_ci        GateRef current = vec.back();
2144514f5e3Sopenharmony_ci        visited.emplace_back(current);
2154514f5e3Sopenharmony_ci        vec.pop_back();
2164514f5e3Sopenharmony_ci        if (current != next) {
2174514f5e3Sopenharmony_ci            if (acc_.GetOpCode(current) == OpCode::JS_BYTECODE) {
2184514f5e3Sopenharmony_ci                LookUpNotDomStLexVarOrCall(current, next);
2194514f5e3Sopenharmony_ci            }
2204514f5e3Sopenharmony_ci            for (size_t i = 0; i < acc_.GetDependCount(current); i++) {
2214514f5e3Sopenharmony_ci                GateRef dependIn = acc_.GetDep(current, i);
2224514f5e3Sopenharmony_ci                if (!std::count(visited.begin(), visited.end(), dependIn)) {
2234514f5e3Sopenharmony_ci                    vec.emplace_back(dependIn);
2244514f5e3Sopenharmony_ci                }
2254514f5e3Sopenharmony_ci            }
2264514f5e3Sopenharmony_ci        }
2274514f5e3Sopenharmony_ci    }
2284514f5e3Sopenharmony_ci}
2294514f5e3Sopenharmony_ci
2304514f5e3Sopenharmony_civoid LexicalEnvSpecializationPass::LookUpNotDomStLexVarOrCall(GateRef current, GateRef next)
2314514f5e3Sopenharmony_ci{
2324514f5e3Sopenharmony_ci    EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(current);
2334514f5e3Sopenharmony_ci    if (Bytecodes::IsStLexVarOp(ecmaOpcode)) {
2344514f5e3Sopenharmony_ci        if (current != next) {
2354514f5e3Sopenharmony_ci            auto iter = notdomStlexvar_.find(next);
2364514f5e3Sopenharmony_ci            if (iter == notdomStlexvar_.end()) {
2374514f5e3Sopenharmony_ci                notdomStlexvar_[next] = current;
2384514f5e3Sopenharmony_ci            }
2394514f5e3Sopenharmony_ci        }
2404514f5e3Sopenharmony_ci    }
2414514f5e3Sopenharmony_ci
2424514f5e3Sopenharmony_ci    if (Bytecodes::IsCallOrAccessorOp(ecmaOpcode)) {
2434514f5e3Sopenharmony_ci        if (current != next) {
2444514f5e3Sopenharmony_ci            auto iter = notDomCall_.find(next);
2454514f5e3Sopenharmony_ci            if (iter == notDomCall_.end()) {
2464514f5e3Sopenharmony_ci                notDomCall_[next] = current;
2474514f5e3Sopenharmony_ci            }
2484514f5e3Sopenharmony_ci        }
2494514f5e3Sopenharmony_ci    }
2504514f5e3Sopenharmony_ci}
2514514f5e3Sopenharmony_ci
2524514f5e3Sopenharmony_cibool LexicalEnvSpecializationPass::HasNotDomIllegalOp(GateRef gate)
2534514f5e3Sopenharmony_ci{
2544514f5e3Sopenharmony_ci    if (HasNotDomStLexvar(gate)) {
2554514f5e3Sopenharmony_ci        return true;
2564514f5e3Sopenharmony_ci    }
2574514f5e3Sopenharmony_ci
2584514f5e3Sopenharmony_ci    if (HasNotDomCall(gate)) {
2594514f5e3Sopenharmony_ci        return true;
2604514f5e3Sopenharmony_ci    }
2614514f5e3Sopenharmony_ci
2624514f5e3Sopenharmony_ci    return false;
2634514f5e3Sopenharmony_ci}
2644514f5e3Sopenharmony_ci
2654514f5e3Sopenharmony_cibool LexicalEnvSpecializationPass::HasNotDomStLexvar(GateRef gate)
2664514f5e3Sopenharmony_ci{
2674514f5e3Sopenharmony_ci    auto iter = notdomStlexvar_.find(gate);
2684514f5e3Sopenharmony_ci    if (iter != notdomStlexvar_.end()) {
2694514f5e3Sopenharmony_ci        return true;
2704514f5e3Sopenharmony_ci    }
2714514f5e3Sopenharmony_ci    return false;
2724514f5e3Sopenharmony_ci}
2734514f5e3Sopenharmony_ci
2744514f5e3Sopenharmony_cibool LexicalEnvSpecializationPass::HasNotDomCall(GateRef gate)
2754514f5e3Sopenharmony_ci{
2764514f5e3Sopenharmony_ci    auto iter = notDomCall_.find(gate);
2774514f5e3Sopenharmony_ci    if (iter != notDomCall_.end()) {
2784514f5e3Sopenharmony_ci        return true;
2794514f5e3Sopenharmony_ci    }
2804514f5e3Sopenharmony_ci    return false;
2814514f5e3Sopenharmony_ci}
2824514f5e3Sopenharmony_ci
2834514f5e3Sopenharmony_ciGateRef LexicalEnvSpecializationPass::LookupStLexvarNode(DependChains* dependChain, GateRef gate)
2844514f5e3Sopenharmony_ci{
2854514f5e3Sopenharmony_ci    GateRef result = Circuit::NullGate();
2864514f5e3Sopenharmony_ci    for (auto iter = dependChain->begin(); iter != dependChain->end(); ++iter) {
2874514f5e3Sopenharmony_ci        GateRef curGate = iter.GetCurrentGate();
2884514f5e3Sopenharmony_ci        if (SearchStLexVar(curGate, gate, result)) {
2894514f5e3Sopenharmony_ci            return curGate;
2904514f5e3Sopenharmony_ci        } else {
2914514f5e3Sopenharmony_ci            if (result == gate) {
2924514f5e3Sopenharmony_ci                return Circuit::NullGate();
2934514f5e3Sopenharmony_ci            }
2944514f5e3Sopenharmony_ci        }
2954514f5e3Sopenharmony_ci    }
2964514f5e3Sopenharmony_ci    return Circuit::NullGate();
2974514f5e3Sopenharmony_ci}
2984514f5e3Sopenharmony_ci
2994514f5e3Sopenharmony_civoid LexicalEnvSpecializationPass::PrintSpecializeId()
3004514f5e3Sopenharmony_ci{
3014514f5e3Sopenharmony_ci    if (enableLog_) {
3024514f5e3Sopenharmony_ci        LOG_COMPILER(INFO) << "\033[34m" << "================="
3034514f5e3Sopenharmony_ci                           << " specialize ldlexvar gate id "
3044514f5e3Sopenharmony_ci                           << "=================" << "\033[0m";
3054514f5e3Sopenharmony_ci        for (auto id : specializeId_) {
3064514f5e3Sopenharmony_ci            LOG_COMPILER(INFO) << "ldlexvar id: " << id;
3074514f5e3Sopenharmony_ci        }
3084514f5e3Sopenharmony_ci        LOG_COMPILER(INFO) << "\033[34m" << "===========================================================" << "\033[0m";
3094514f5e3Sopenharmony_ci    }
3104514f5e3Sopenharmony_ci}
3114514f5e3Sopenharmony_ci
3124514f5e3Sopenharmony_ciGateRef GetEnvSpecializationPass::VisitGate(GateRef gate)
3134514f5e3Sopenharmony_ci{
3144514f5e3Sopenharmony_ci    auto opcode = acc_.GetOpCode(gate);
3154514f5e3Sopenharmony_ci    if (opcode == OpCode::GET_ENV && acc_.GetOpCode(acc_.GetValueIn(gate, 0)) != OpCode::ARG) {
3164514f5e3Sopenharmony_ci        GateRef func = acc_.GetValueIn(gate, 0);
3174514f5e3Sopenharmony_ci        if (acc_.GetOpCode(func) == OpCode::JS_BYTECODE) {
3184514f5e3Sopenharmony_ci            return TryGetReplaceEnv(func);
3194514f5e3Sopenharmony_ci        }
3204514f5e3Sopenharmony_ci    }
3214514f5e3Sopenharmony_ci    return Circuit::NullGate();
3224514f5e3Sopenharmony_ci}
3234514f5e3Sopenharmony_ci
3244514f5e3Sopenharmony_ci
3254514f5e3Sopenharmony_ciGateRef GetEnvSpecializationPass::TryGetReplaceEnv(GateRef func)
3264514f5e3Sopenharmony_ci{
3274514f5e3Sopenharmony_ci    ASSERT(acc_.GetNumValueIn(func) >= 1);
3284514f5e3Sopenharmony_ci    EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(func);
3294514f5e3Sopenharmony_ci    switch (ecmaOpcode) {
3304514f5e3Sopenharmony_ci        case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8:
3314514f5e3Sopenharmony_ci        case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8:
3324514f5e3Sopenharmony_ci        case EcmaOpcode::DEFINEMETHOD_IMM8_ID16_IMM8:
3334514f5e3Sopenharmony_ci        case EcmaOpcode::DEFINEMETHOD_IMM16_ID16_IMM8: {
3344514f5e3Sopenharmony_ci            GateRef replacement = acc_.GetValueIn(func, acc_.GetNumValueIn(func) - 1); // 1: last value in
3354514f5e3Sopenharmony_ci            return replacement;
3364514f5e3Sopenharmony_ci        }
3374514f5e3Sopenharmony_ci        default:
3384514f5e3Sopenharmony_ci            return Circuit::NullGate();
3394514f5e3Sopenharmony_ci    }
3404514f5e3Sopenharmony_ci    return Circuit::NullGate();
3414514f5e3Sopenharmony_ci}
3424514f5e3Sopenharmony_ci}