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#include "ecmascript/compiler/builtins_lowering.h"
174514f5e3Sopenharmony_ci#include "ecmascript/global_env.h"
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
204514f5e3Sopenharmony_civoid BuiltinLowering::LowerTypedCallBuitin(GateRef gate)
214514f5e3Sopenharmony_ci{
224514f5e3Sopenharmony_ci    Environment env(gate, circuit_, &builder_);
234514f5e3Sopenharmony_ci    auto valuesIn = acc_.GetNumValueIn(gate);
244514f5e3Sopenharmony_ci    ASSERT(valuesIn >= 1);
254514f5e3Sopenharmony_ci    auto idGate = acc_.GetValueIn(gate, valuesIn - 1);
264514f5e3Sopenharmony_ci    auto id = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(idGate));
274514f5e3Sopenharmony_ci    switch (id) {
284514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(StringLocaleCompare):
294514f5e3Sopenharmony_ci            LowerTypedLocaleCompare(gate);
304514f5e3Sopenharmony_ci            break;
314514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(ArraySort):
324514f5e3Sopenharmony_ci            LowerTypedArraySort(gate);
334514f5e3Sopenharmony_ci            break;
344514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(JsonStringify):
354514f5e3Sopenharmony_ci            LowerTypedStringify(gate);
364514f5e3Sopenharmony_ci            break;
374514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(MapProtoIterator):
384514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(SetProtoIterator):
394514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(StringProtoIterator):
404514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(ArrayProtoIterator):
414514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(TypeArrayProtoIterator):
424514f5e3Sopenharmony_ci            LowerBuiltinIterator(gate, id);
434514f5e3Sopenharmony_ci            break;
444514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(MapIteratorProtoNext):
454514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(SetIteratorProtoNext):
464514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(StringIteratorProtoNext):
474514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(ArrayIteratorProtoNext):
484514f5e3Sopenharmony_ci            LowerIteratorNext(gate, id);
494514f5e3Sopenharmony_ci            break;
504514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(IteratorProtoReturn):
514514f5e3Sopenharmony_ci            LowerIteratorReturn(gate, id);
524514f5e3Sopenharmony_ci            break;
534514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(NumberConstructor):
544514f5e3Sopenharmony_ci            LowerNumberConstructor(gate);
554514f5e3Sopenharmony_ci            break;
564514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(GlobalDecodeURIComponent):
574514f5e3Sopenharmony_ci            LowerGlobalDecodeURIComponent(gate);
584514f5e3Sopenharmony_ci            break;
594514f5e3Sopenharmony_ci        default:
604514f5e3Sopenharmony_ci            break;
614514f5e3Sopenharmony_ci    }
624514f5e3Sopenharmony_ci}
634514f5e3Sopenharmony_ci
644514f5e3Sopenharmony_civoid BuiltinLowering::LowerTypedFloor(GateRef gate)
654514f5e3Sopenharmony_ci{
664514f5e3Sopenharmony_ci    auto ret = TypedFloor(gate);
674514f5e3Sopenharmony_ci    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
684514f5e3Sopenharmony_ci}
694514f5e3Sopenharmony_ci
704514f5e3Sopenharmony_ciGateRef BuiltinLowering::TypedLocaleCompare(GateRef glue, GateRef gate, GateRef thisObj, GateRef thatObj)
714514f5e3Sopenharmony_ci{
724514f5e3Sopenharmony_ci    auto env = builder_.GetCurrentEnvironment();
734514f5e3Sopenharmony_ci    Label entry(&builder_);
744514f5e3Sopenharmony_ci    env->SubCfgEntry(&entry);
754514f5e3Sopenharmony_ci
764514f5e3Sopenharmony_ci    Label slowPath(&builder_);
774514f5e3Sopenharmony_ci    Label fastPath(&builder_);
784514f5e3Sopenharmony_ci    Label localeCompareGC(&builder_);
794514f5e3Sopenharmony_ci    Label exit(&builder_);
804514f5e3Sopenharmony_ci    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
814514f5e3Sopenharmony_ci
824514f5e3Sopenharmony_ci    GateRef isString = builder_.BothAreString(thisObj, thatObj);
834514f5e3Sopenharmony_ci    builder_.Branch(isString, &fastPath, &slowPath);
844514f5e3Sopenharmony_ci    builder_.Bind(&fastPath);
854514f5e3Sopenharmony_ci    {
864514f5e3Sopenharmony_ci        result = builder_.CallRuntime(glue, RTSTUB_ID(LocaleCompareCacheable), Gate::InvalidGateRef,
874514f5e3Sopenharmony_ci            { builder_.Undefined(), thisObj, thatObj }, gate);
884514f5e3Sopenharmony_ci        GateRef status = builder_.TaggedIsUndefined(*result);
894514f5e3Sopenharmony_ci        builder_.Branch(status, &localeCompareGC, &exit, BranchWeight::ONE_WEIGHT, BranchWeight::STRONG_WEIGHT,
904514f5e3Sopenharmony_ci            "TypedLocaleCompare");
914514f5e3Sopenharmony_ci        builder_.Bind(&localeCompareGC);
924514f5e3Sopenharmony_ci        {
934514f5e3Sopenharmony_ci            result = builder_.CallRuntime(glue, RTSTUB_ID(LocaleCompareWithGc), Gate::InvalidGateRef,
944514f5e3Sopenharmony_ci                { builder_.Undefined(), thisObj, thatObj, builder_.Undefined() }, gate);
954514f5e3Sopenharmony_ci            builder_.Jump(&exit);
964514f5e3Sopenharmony_ci        }
974514f5e3Sopenharmony_ci    }
984514f5e3Sopenharmony_ci    builder_.Bind(&slowPath);
994514f5e3Sopenharmony_ci    {
1004514f5e3Sopenharmony_ci        result = LowerCallRuntime(glue, gate, RTSTUB_ID(LocaleCompare),
1014514f5e3Sopenharmony_ci            { thisObj, thatObj, builder_.Undefined(), builder_.Undefined()});
1024514f5e3Sopenharmony_ci        builder_.Jump(&exit);
1034514f5e3Sopenharmony_ci    }
1044514f5e3Sopenharmony_ci    builder_.Bind(&exit);
1054514f5e3Sopenharmony_ci    auto ret = *result;
1064514f5e3Sopenharmony_ci    env->SubCfgExit();
1074514f5e3Sopenharmony_ci    return ret;
1084514f5e3Sopenharmony_ci}
1094514f5e3Sopenharmony_ci
1104514f5e3Sopenharmony_ciGateRef BuiltinLowering::TypedFloor(GateRef gate)
1114514f5e3Sopenharmony_ci{
1124514f5e3Sopenharmony_ci    auto env = builder_.GetCurrentEnvironment();
1134514f5e3Sopenharmony_ci    Label entry(&builder_);
1144514f5e3Sopenharmony_ci    env->SubCfgEntry(&entry);
1154514f5e3Sopenharmony_ci
1164514f5e3Sopenharmony_ci    Label numberBranch(&builder_);
1174514f5e3Sopenharmony_ci    Label notNumberBranch(&builder_);
1184514f5e3Sopenharmony_ci    Label exit(&builder_);
1194514f5e3Sopenharmony_ci
1204514f5e3Sopenharmony_ci    GateRef para1 = acc_.GetValueIn(gate, 0);
1214514f5e3Sopenharmony_ci    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
1224514f5e3Sopenharmony_ci
1234514f5e3Sopenharmony_ci    BRANCH_CIR(builder_.TaggedIsNumber(para1), &numberBranch, &notNumberBranch);
1244514f5e3Sopenharmony_ci    builder_.Bind(&numberBranch);
1254514f5e3Sopenharmony_ci    {
1264514f5e3Sopenharmony_ci        GateRef value = builder_.GetDoubleOfTNumber(para1);
1274514f5e3Sopenharmony_ci        Label IsNan(&builder_);
1284514f5e3Sopenharmony_ci        Label NotNan(&builder_);
1294514f5e3Sopenharmony_ci        GateRef condition = builder_.DoubleIsNAN(value);
1304514f5e3Sopenharmony_ci        BRANCH_CIR(condition, &IsNan, &NotNan);
1314514f5e3Sopenharmony_ci        builder_.Bind(&NotNan);
1324514f5e3Sopenharmony_ci        {
1334514f5e3Sopenharmony_ci            GateRef glue = acc_.GetGlueFromArgList();
1344514f5e3Sopenharmony_ci            int index = RTSTUB_ID(FloatFloor);
1354514f5e3Sopenharmony_ci            GateRef floor = builder_.CallNGCRuntime(glue, index, Gate::InvalidGateRef, {value}, gate);
1364514f5e3Sopenharmony_ci            result = builder_.DoubleToTaggedDoublePtr(floor);
1374514f5e3Sopenharmony_ci            builder_.Jump(&exit);
1384514f5e3Sopenharmony_ci        }
1394514f5e3Sopenharmony_ci        builder_.Bind(&IsNan);
1404514f5e3Sopenharmony_ci        {
1414514f5e3Sopenharmony_ci            result = builder_.DoubleToTaggedDoublePtr(builder_.Double(base::NAN_VALUE));
1424514f5e3Sopenharmony_ci            builder_.Jump(&exit);
1434514f5e3Sopenharmony_ci        }
1444514f5e3Sopenharmony_ci    }
1454514f5e3Sopenharmony_ci    builder_.Bind(&notNumberBranch);
1464514f5e3Sopenharmony_ci    {
1474514f5e3Sopenharmony_ci        builder_.Jump(&exit);
1484514f5e3Sopenharmony_ci    }
1494514f5e3Sopenharmony_ci
1504514f5e3Sopenharmony_ci    builder_.Bind(&exit);
1514514f5e3Sopenharmony_ci    auto ret = *result;
1524514f5e3Sopenharmony_ci    env->SubCfgExit();
1534514f5e3Sopenharmony_ci    return ret;
1544514f5e3Sopenharmony_ci}
1554514f5e3Sopenharmony_ci
1564514f5e3Sopenharmony_ciGateRef BuiltinLowering::IntToTaggedIntPtr(GateRef x)
1574514f5e3Sopenharmony_ci{
1584514f5e3Sopenharmony_ci    GateRef val = builder_.SExtInt32ToInt64(x);
1594514f5e3Sopenharmony_ci    return builder_.ToTaggedIntPtr(val);
1604514f5e3Sopenharmony_ci}
1614514f5e3Sopenharmony_ci
1624514f5e3Sopenharmony_ciGateRef BuiltinLowering::LowerCallRuntime(GateRef glue, GateRef gate, int index, const std::vector<GateRef> &args,
1634514f5e3Sopenharmony_ci                                          bool useLabel)
1644514f5e3Sopenharmony_ci{
1654514f5e3Sopenharmony_ci    const std::string name = RuntimeStubCSigns::GetRTName(index);
1664514f5e3Sopenharmony_ci    if (useLabel) {
1674514f5e3Sopenharmony_ci        GateRef result = builder_.CallRuntime(glue, index, Gate::InvalidGateRef, args, gate, name.c_str());
1684514f5e3Sopenharmony_ci        return result;
1694514f5e3Sopenharmony_ci    } else {
1704514f5e3Sopenharmony_ci        const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
1714514f5e3Sopenharmony_ci        GateRef target = builder_.IntPtr(index);
1724514f5e3Sopenharmony_ci        GateRef result = builder_.Call(cs, glue, target, builder_.GetDepend(), args, gate, name.c_str());
1734514f5e3Sopenharmony_ci        return result;
1744514f5e3Sopenharmony_ci    }
1754514f5e3Sopenharmony_ci}
1764514f5e3Sopenharmony_ci
1774514f5e3Sopenharmony_civoid BuiltinLowering::ReplaceHirWithValue(GateRef hirGate, GateRef value, bool noThrow)
1784514f5e3Sopenharmony_ci{
1794514f5e3Sopenharmony_ci    if (!noThrow) {
1804514f5e3Sopenharmony_ci        GateRef state = builder_.GetState();
1814514f5e3Sopenharmony_ci        // copy depend-wire of hirGate to value
1824514f5e3Sopenharmony_ci        GateRef depend = builder_.GetDepend();
1834514f5e3Sopenharmony_ci        // exception value
1844514f5e3Sopenharmony_ci        GateRef exceptionVal = builder_.ExceptionConstant();
1854514f5e3Sopenharmony_ci        // compare with trampolines result
1864514f5e3Sopenharmony_ci        GateRef equal = builder_.Equal(value, exceptionVal);
1874514f5e3Sopenharmony_ci        auto ifBranch = builder_.Branch(state, equal, 1, BranchWeight::DEOPT_WEIGHT, "checkException");
1884514f5e3Sopenharmony_ci
1894514f5e3Sopenharmony_ci        GateRef ifTrue = builder_.IfTrue(ifBranch);
1904514f5e3Sopenharmony_ci        GateRef ifFalse = builder_.IfFalse(ifBranch);
1914514f5e3Sopenharmony_ci        GateRef eDepend = builder_.DependRelay(ifTrue, depend);
1924514f5e3Sopenharmony_ci        GateRef sDepend = builder_.DependRelay(ifFalse, depend);
1934514f5e3Sopenharmony_ci        StateDepend success(ifFalse, sDepend);
1944514f5e3Sopenharmony_ci        StateDepend exception(ifTrue, eDepend);
1954514f5e3Sopenharmony_ci        acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value);
1964514f5e3Sopenharmony_ci    } else {
1974514f5e3Sopenharmony_ci        acc_.ReplaceHirDirectly(hirGate, builder_.GetStateDepend(), value);
1984514f5e3Sopenharmony_ci    }
1994514f5e3Sopenharmony_ci}
2004514f5e3Sopenharmony_ci
2014514f5e3Sopenharmony_civoid BuiltinLowering::LowerTypedLocaleCompare(GateRef gate)
2024514f5e3Sopenharmony_ci{
2034514f5e3Sopenharmony_ci    GateRef glue = acc_.GetGlueFromArgList();
2044514f5e3Sopenharmony_ci
2054514f5e3Sopenharmony_ci    size_t index = 0;
2064514f5e3Sopenharmony_ci    GateRef thisObj = acc_.GetValueIn(gate, index++);
2074514f5e3Sopenharmony_ci    GateRef thatObj = acc_.GetValueIn(gate, index++);
2084514f5e3Sopenharmony_ci
2094514f5e3Sopenharmony_ci    static constexpr size_t NUM_OF_ARGS = 4;
2104514f5e3Sopenharmony_ci    ASSERT(acc_.GetNumValueIn(gate) > 0);
2114514f5e3Sopenharmony_ci    size_t argsIn = acc_.GetNumValueIn(gate) - 1;
2124514f5e3Sopenharmony_ci    GateRef result = Circuit::NullGate();
2134514f5e3Sopenharmony_ci    if (argsIn == 2) { // 2: string.localeCompare(string)
2144514f5e3Sopenharmony_ci        // If the number of args is two, it must satisfy conditions for cache optimization.
2154514f5e3Sopenharmony_ci        // The cache of icu collator if locale is undefined
2164514f5e3Sopenharmony_ci        result = TypedLocaleCompare(glue, gate, thisObj, thatObj);
2174514f5e3Sopenharmony_ci    } else {
2184514f5e3Sopenharmony_ci        // willdo: Implement cache fastpath
2194514f5e3Sopenharmony_ci        std::vector<GateRef> args = { thisObj, thatObj };
2204514f5e3Sopenharmony_ci        ASSERT(argsIn <= NUM_OF_ARGS);
2214514f5e3Sopenharmony_ci        args.reserve(NUM_OF_ARGS);
2224514f5e3Sopenharmony_ci        while (index < argsIn) {
2234514f5e3Sopenharmony_ci            GateRef arg = acc_.GetValueIn(gate, index++);
2244514f5e3Sopenharmony_ci            args.emplace_back(arg);
2254514f5e3Sopenharmony_ci        }
2264514f5e3Sopenharmony_ci        while (index < NUM_OF_ARGS) {
2274514f5e3Sopenharmony_ci            args.emplace_back(builder_.Undefined());
2284514f5e3Sopenharmony_ci            index++;
2294514f5e3Sopenharmony_ci        }
2304514f5e3Sopenharmony_ci        result = LowerCallRuntime(glue, gate, RTSTUB_ID(LocaleCompare), args);
2314514f5e3Sopenharmony_ci    }
2324514f5e3Sopenharmony_ci    ReplaceHirWithValue(gate, result);
2334514f5e3Sopenharmony_ci}
2344514f5e3Sopenharmony_ci
2354514f5e3Sopenharmony_civoid BuiltinLowering::LowerTypedArraySort(GateRef gate)
2364514f5e3Sopenharmony_ci{
2374514f5e3Sopenharmony_ci    GateRef glue = acc_.GetGlueFromArgList();
2384514f5e3Sopenharmony_ci    GateRef thisObj = acc_.GetValueIn(gate, 0);
2394514f5e3Sopenharmony_ci    GateRef result = LowerCallRuntime(glue, gate, RTSTUB_ID(ArraySort), { thisObj });
2404514f5e3Sopenharmony_ci    ReplaceHirWithValue(gate, result);
2414514f5e3Sopenharmony_ci}
2424514f5e3Sopenharmony_ci
2434514f5e3Sopenharmony_ciGateRef BuiltinLowering::LowerCallTargetCheck(Environment *env, GateRef gate)
2444514f5e3Sopenharmony_ci{
2454514f5e3Sopenharmony_ci    builder_.SetEnvironment(env);
2464514f5e3Sopenharmony_ci    GateRef idGate = acc_.GetValueIn(gate, 1);
2474514f5e3Sopenharmony_ci    BuiltinsStubCSigns::ID id = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(idGate));
2484514f5e3Sopenharmony_ci    switch (id) {
2494514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::MapProtoIterator:
2504514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::SetProtoIterator:
2514514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::StringProtoIterator:
2524514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::ArrayProtoIterator:
2534514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::TypeArrayProtoIterator: {
2544514f5e3Sopenharmony_ci            return LowerCallTargetCheckWithDetector(gate, id);
2554514f5e3Sopenharmony_ci        }
2564514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::DateGetTime:
2574514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::MapClear:
2584514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::MapDelete:
2594514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::MapGet:
2604514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::MapHas:
2614514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::SetAdd:
2624514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::SetClear:
2634514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::SetDelete:
2644514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::SetHas: {
2654514f5e3Sopenharmony_ci            return LowerCallTargetCheckWithObjectType(gate, id);
2664514f5e3Sopenharmony_ci        }
2674514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::BigIntConstructor:
2684514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::NumberConstructor: {
2694514f5e3Sopenharmony_ci            return LowerCallTargetCheckWithGlobalEnv(gate, id);
2704514f5e3Sopenharmony_ci        }
2714514f5e3Sopenharmony_ci        default: {
2724514f5e3Sopenharmony_ci            return LowerCallTargetCheckDefault(gate, id);
2734514f5e3Sopenharmony_ci        }
2744514f5e3Sopenharmony_ci    }
2754514f5e3Sopenharmony_ci}
2764514f5e3Sopenharmony_ci
2774514f5e3Sopenharmony_ciGateRef BuiltinLowering::LowerCallTargetCheckDefault(GateRef gate, BuiltinsStubCSigns::ID id)
2784514f5e3Sopenharmony_ci{
2794514f5e3Sopenharmony_ci    GateRef constantFunction = builder_.GetGlobalConstantValue(GET_TYPED_CONSTANT_INDEX(id));
2804514f5e3Sopenharmony_ci    GateRef function = acc_.GetValueIn(gate, 0); // 0: function
2814514f5e3Sopenharmony_ci    return builder_.Equal(function, constantFunction);
2824514f5e3Sopenharmony_ci}
2834514f5e3Sopenharmony_ci
2844514f5e3Sopenharmony_ciGateRef BuiltinLowering::LowerCallTargetCheckWithGlobalEnv(GateRef gate, BuiltinsStubCSigns::ID id)
2854514f5e3Sopenharmony_ci{
2864514f5e3Sopenharmony_ci    GateRef glueGlobalEnv = builder_.GetGlobalEnv();
2874514f5e3Sopenharmony_ci    GateRef globalFunction =
2884514f5e3Sopenharmony_ci        builder_.GetGlobalEnvObj(glueGlobalEnv, GET_TYPED_GLOBAL_ENV_INDEX(id));
2894514f5e3Sopenharmony_ci    GateRef target = acc_.GetValueIn(gate, 0); // 0:target
2904514f5e3Sopenharmony_ci    return builder_.Equal(target, globalFunction);
2914514f5e3Sopenharmony_ci}
2924514f5e3Sopenharmony_ci
2934514f5e3Sopenharmony_ciGateRef BuiltinLowering::LowerCallTargetCheckWithDetector(GateRef gate, BuiltinsStubCSigns::ID id)
2944514f5e3Sopenharmony_ci{
2954514f5e3Sopenharmony_ci    JSType expectType = JSType::INVALID;
2964514f5e3Sopenharmony_ci    uint16_t detectorIndex = 0;
2974514f5e3Sopenharmony_ci    switch (id) {
2984514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::MapProtoIterator: {
2994514f5e3Sopenharmony_ci            expectType = JSType::JS_MAP;
3004514f5e3Sopenharmony_ci            detectorIndex = GlobalEnv::MAP_ITERATOR_DETECTOR_INDEX;
3014514f5e3Sopenharmony_ci            break;
3024514f5e3Sopenharmony_ci        }
3034514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::SetProtoIterator: {
3044514f5e3Sopenharmony_ci            expectType = JSType::JS_SET;
3054514f5e3Sopenharmony_ci            detectorIndex = GlobalEnv::SET_ITERATOR_DETECTOR_INDEX;
3064514f5e3Sopenharmony_ci            break;
3074514f5e3Sopenharmony_ci        }
3084514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::StringProtoIterator: {
3094514f5e3Sopenharmony_ci            expectType = JSType::STRING_FIRST;
3104514f5e3Sopenharmony_ci            detectorIndex = GlobalEnv::STRING_ITERATOR_DETECTOR_INDEX;
3114514f5e3Sopenharmony_ci            break;
3124514f5e3Sopenharmony_ci        }
3134514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::ArrayProtoIterator: {
3144514f5e3Sopenharmony_ci            expectType = JSType::JS_ARRAY;
3154514f5e3Sopenharmony_ci            detectorIndex = GlobalEnv::ARRAY_ITERATOR_DETECTOR_INDEX;
3164514f5e3Sopenharmony_ci            break;
3174514f5e3Sopenharmony_ci        }
3184514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::TypeArrayProtoIterator: {
3194514f5e3Sopenharmony_ci            expectType = JSType::JS_TYPED_ARRAY_FIRST;
3204514f5e3Sopenharmony_ci            detectorIndex = GlobalEnv::TYPED_ARRAY_ITERATOR_DETECTOR_INDEX;
3214514f5e3Sopenharmony_ci            break;
3224514f5e3Sopenharmony_ci        }
3234514f5e3Sopenharmony_ci        default: {
3244514f5e3Sopenharmony_ci            LOG_COMPILER(FATAL) << "this branch is unreachable";
3254514f5e3Sopenharmony_ci            UNREACHABLE();
3264514f5e3Sopenharmony_ci        }
3274514f5e3Sopenharmony_ci    }
3284514f5e3Sopenharmony_ci    GateRef obj = acc_.GetValueIn(gate, 2);  // 2: iterator obj
3294514f5e3Sopenharmony_ci    return LogicAndBuilder(builder_.GetCurrentEnvironment())
3304514f5e3Sopenharmony_ci        .And(builder_.TaggedIsHeapObjectOp(obj))
3314514f5e3Sopenharmony_ci        .And(builder_.IsSpecificObjectType(obj, expectType))
3324514f5e3Sopenharmony_ci        .And(builder_.IsMarkerCellValid(builder_.GetGlobalEnvObj(builder_.GetGlobalEnv(), detectorIndex)))
3334514f5e3Sopenharmony_ci        .Done();
3344514f5e3Sopenharmony_ci}
3354514f5e3Sopenharmony_ci
3364514f5e3Sopenharmony_ciGateRef BuiltinLowering::LowerCallTargetCheckWithObjectType(GateRef gate, BuiltinsStubCSigns::ID id)
3374514f5e3Sopenharmony_ci{
3384514f5e3Sopenharmony_ci    JSType expectType = JSType::INVALID;
3394514f5e3Sopenharmony_ci    switch (id) {
3404514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::MapClear:
3414514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::MapDelete:
3424514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::MapGet:
3434514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::MapHas: {
3444514f5e3Sopenharmony_ci            expectType = JSType::JS_MAP;
3454514f5e3Sopenharmony_ci            break;
3464514f5e3Sopenharmony_ci        }
3474514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::SetAdd:
3484514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::SetClear:
3494514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::SetDelete:
3504514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::SetHas: {
3514514f5e3Sopenharmony_ci            expectType = JSType::JS_SET;
3524514f5e3Sopenharmony_ci            break;
3534514f5e3Sopenharmony_ci        }
3544514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::DateGetTime: {
3554514f5e3Sopenharmony_ci            expectType = JSType::JS_DATE;
3564514f5e3Sopenharmony_ci            break;
3574514f5e3Sopenharmony_ci        }
3584514f5e3Sopenharmony_ci        default: {
3594514f5e3Sopenharmony_ci            LOG_COMPILER(FATAL) << "this branch is unreachable";
3604514f5e3Sopenharmony_ci            UNREACHABLE();
3614514f5e3Sopenharmony_ci        }
3624514f5e3Sopenharmony_ci    }
3634514f5e3Sopenharmony_ci    GateRef obj = acc_.GetValueIn(gate, 2);  // 2: receiver obj
3644514f5e3Sopenharmony_ci    return LogicAndBuilder(builder_.GetCurrentEnvironment())
3654514f5e3Sopenharmony_ci        .And(builder_.TaggedIsHeapObjectOp(obj))
3664514f5e3Sopenharmony_ci        .And(builder_.IsSpecificObjectType(obj, expectType))
3674514f5e3Sopenharmony_ci        .And(LowerCallTargetCheckDefault(gate, id))
3684514f5e3Sopenharmony_ci        .Done();
3694514f5e3Sopenharmony_ci}
3704514f5e3Sopenharmony_ci
3714514f5e3Sopenharmony_ciGateRef BuiltinLowering::CheckPara(GateRef gate, GateRef funcCheck)
3724514f5e3Sopenharmony_ci{
3734514f5e3Sopenharmony_ci    GateRef idGate = acc_.GetValueIn(gate, 1);
3744514f5e3Sopenharmony_ci    BuiltinsStubCSigns::ID id = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(idGate));
3754514f5e3Sopenharmony_ci    if (IS_TYPED_INLINE_BUILTINS_ID(id)) {
3764514f5e3Sopenharmony_ci        // Don't need check param. Param was checked before
3774514f5e3Sopenharmony_ci        return funcCheck;
3784514f5e3Sopenharmony_ci    }
3794514f5e3Sopenharmony_ci    switch (id) {
3804514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::StringLocaleCompare:
3814514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::ArraySort:
3824514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::JsonStringify:
3834514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::MapProtoIterator:
3844514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::SetProtoIterator:
3854514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::StringProtoIterator:
3864514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::ArrayProtoIterator:
3874514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::TypeArrayProtoIterator:
3884514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::MapIteratorProtoNext:
3894514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::SetIteratorProtoNext:
3904514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::StringIteratorProtoNext:
3914514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::ArrayIteratorProtoNext:
3924514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::IteratorProtoReturn:
3934514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::NumberConstructor:
3944514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::TypedArrayEntries:
3954514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::TypedArrayKeys:
3964514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::TypedArrayValues:
3974514f5e3Sopenharmony_ci        case BuiltinsStubCSigns::ID::GlobalDecodeURIComponent:
3984514f5e3Sopenharmony_ci            // Don't need check para
3994514f5e3Sopenharmony_ci            return funcCheck;
4004514f5e3Sopenharmony_ci        default: {
4014514f5e3Sopenharmony_ci            LOG_COMPILER(FATAL) << "this branch is unreachable";
4024514f5e3Sopenharmony_ci            UNREACHABLE();
4034514f5e3Sopenharmony_ci        }
4044514f5e3Sopenharmony_ci    }
4054514f5e3Sopenharmony_ci}
4064514f5e3Sopenharmony_ci
4074514f5e3Sopenharmony_civoid BuiltinLowering::LowerTypedStringify(GateRef gate)
4084514f5e3Sopenharmony_ci{
4094514f5e3Sopenharmony_ci    GateRef glue = acc_.GetGlueFromArgList();
4104514f5e3Sopenharmony_ci    GateRef value = acc_.GetValueIn(gate, 1);
4114514f5e3Sopenharmony_ci    std::vector<GateRef> args;
4124514f5e3Sopenharmony_ci    args.emplace_back(value);
4134514f5e3Sopenharmony_ci    GateRef result = LowerCallRuntime(glue, gate, RTSTUB_ID(FastStringify), args);
4144514f5e3Sopenharmony_ci    ReplaceHirWithValue(gate, result);
4154514f5e3Sopenharmony_ci}
4164514f5e3Sopenharmony_ci
4174514f5e3Sopenharmony_civoid BuiltinLowering::LowerBuiltinIterator(GateRef gate, BuiltinsStubCSigns::ID id)
4184514f5e3Sopenharmony_ci{
4194514f5e3Sopenharmony_ci    GateRef glue = acc_.GetGlueFromArgList();
4204514f5e3Sopenharmony_ci    GateRef obj = acc_.GetValueIn(gate, 0);
4214514f5e3Sopenharmony_ci    GateRef result = Circuit::NullGate();
4224514f5e3Sopenharmony_ci    switch (id) {
4234514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(MapProtoIterator): {
4244514f5e3Sopenharmony_ci            result = builder_.CallStub(glue, gate, CommonStubCSigns::CreateJSMapIterator, { glue, obj });
4254514f5e3Sopenharmony_ci            break;
4264514f5e3Sopenharmony_ci        }
4274514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(SetProtoIterator): {
4284514f5e3Sopenharmony_ci            result = builder_.CallStub(glue, gate, CommonStubCSigns::CreateJSSetIterator, { glue, obj });
4294514f5e3Sopenharmony_ci            break;
4304514f5e3Sopenharmony_ci        }
4314514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(StringProtoIterator): {
4324514f5e3Sopenharmony_ci            result = LowerCallRuntime(glue, gate, RTSTUB_ID(CreateStringIterator), { obj }, true);
4334514f5e3Sopenharmony_ci            break;
4344514f5e3Sopenharmony_ci        }
4354514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(ArrayProtoIterator): {
4364514f5e3Sopenharmony_ci            result = LowerCallRuntime(glue, gate, RTSTUB_ID(NewJSArrayIterator), { obj }, true);
4374514f5e3Sopenharmony_ci            break;
4384514f5e3Sopenharmony_ci        }
4394514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(TypeArrayProtoIterator): {
4404514f5e3Sopenharmony_ci            result = LowerCallRuntime(glue, gate, RTSTUB_ID(NewJSTypedArrayIterator), { obj }, true);
4414514f5e3Sopenharmony_ci            break;
4424514f5e3Sopenharmony_ci        }
4434514f5e3Sopenharmony_ci        default:
4444514f5e3Sopenharmony_ci            UNREACHABLE();
4454514f5e3Sopenharmony_ci    }
4464514f5e3Sopenharmony_ci    ReplaceHirWithValue(gate, result);
4474514f5e3Sopenharmony_ci}
4484514f5e3Sopenharmony_ci
4494514f5e3Sopenharmony_civoid BuiltinLowering::LowerIteratorNext(GateRef gate, BuiltinsStubCSigns::ID id)
4504514f5e3Sopenharmony_ci{
4514514f5e3Sopenharmony_ci    GateRef glue = acc_.GetGlueFromArgList();
4524514f5e3Sopenharmony_ci    GateRef thisObj = acc_.GetValueIn(gate, 0);
4534514f5e3Sopenharmony_ci    GateRef result = Circuit::NullGate();
4544514f5e3Sopenharmony_ci    switch (id) {
4554514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(MapIteratorProtoNext): {
4564514f5e3Sopenharmony_ci            result = LowerCallRuntime(glue, gate, RTSTUB_ID(MapIteratorNext), { thisObj }, true);
4574514f5e3Sopenharmony_ci            break;
4584514f5e3Sopenharmony_ci        }
4594514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(SetIteratorProtoNext): {
4604514f5e3Sopenharmony_ci            result = LowerCallRuntime(glue, gate, RTSTUB_ID(SetIteratorNext), { thisObj }, true);
4614514f5e3Sopenharmony_ci            break;
4624514f5e3Sopenharmony_ci        }
4634514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(StringIteratorProtoNext): {
4644514f5e3Sopenharmony_ci            result = builder_.CallStub(glue, gate, CommonStubCSigns::StringIteratorNext, { glue, thisObj });
4654514f5e3Sopenharmony_ci            break;
4664514f5e3Sopenharmony_ci        }
4674514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(ArrayIteratorProtoNext): {
4684514f5e3Sopenharmony_ci            result = LowerCallRuntime(glue, gate, RTSTUB_ID(ArrayIteratorNext), { thisObj }, true);
4694514f5e3Sopenharmony_ci            break;
4704514f5e3Sopenharmony_ci        }
4714514f5e3Sopenharmony_ci        default:
4724514f5e3Sopenharmony_ci            UNREACHABLE();
4734514f5e3Sopenharmony_ci    }
4744514f5e3Sopenharmony_ci    ReplaceHirWithValue(gate, result);
4754514f5e3Sopenharmony_ci}
4764514f5e3Sopenharmony_ci
4774514f5e3Sopenharmony_civoid BuiltinLowering::LowerIteratorReturn(GateRef gate, BuiltinsStubCSigns::ID id)
4784514f5e3Sopenharmony_ci{
4794514f5e3Sopenharmony_ci    GateRef glue = acc_.GetGlueFromArgList();
4804514f5e3Sopenharmony_ci    GateRef thisObj = acc_.GetValueIn(gate, 0);
4814514f5e3Sopenharmony_ci    GateRef result = Circuit::NullGate();
4824514f5e3Sopenharmony_ci    switch (id) {
4834514f5e3Sopenharmony_ci        case BUILTINS_STUB_ID(IteratorProtoReturn): {
4844514f5e3Sopenharmony_ci            result = LowerCallRuntime(glue, gate, RTSTUB_ID(IteratorReturn), { thisObj }, true);
4854514f5e3Sopenharmony_ci            break;
4864514f5e3Sopenharmony_ci        }
4874514f5e3Sopenharmony_ci        default:
4884514f5e3Sopenharmony_ci            UNREACHABLE();
4894514f5e3Sopenharmony_ci    }
4904514f5e3Sopenharmony_ci    ReplaceHirWithValue(gate, result);
4914514f5e3Sopenharmony_ci}
4924514f5e3Sopenharmony_ci
4934514f5e3Sopenharmony_civoid BuiltinLowering::LowerNumberConstructor(GateRef gate)
4944514f5e3Sopenharmony_ci{
4954514f5e3Sopenharmony_ci    auto env = builder_.GetCurrentEnvironment();
4964514f5e3Sopenharmony_ci
4974514f5e3Sopenharmony_ci    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), IntToTaggedIntPtr(builder_.Int32(0)));
4984514f5e3Sopenharmony_ci    GateRef param = acc_.GetValueIn(gate, 0);
4994514f5e3Sopenharmony_ci    Label exit(env);
5004514f5e3Sopenharmony_ci    Label isNumber(env);
5014514f5e3Sopenharmony_ci    Label notNumber(env);
5024514f5e3Sopenharmony_ci    BRANCH_CIR(builder_.TaggedIsNumber(param), &isNumber, &notNumber);
5034514f5e3Sopenharmony_ci    builder_.Bind(&isNumber);
5044514f5e3Sopenharmony_ci    {
5054514f5e3Sopenharmony_ci        result = param;
5064514f5e3Sopenharmony_ci        builder_.Jump(&exit);
5074514f5e3Sopenharmony_ci    }
5084514f5e3Sopenharmony_ci    builder_.Bind(&notNumber);
5094514f5e3Sopenharmony_ci    {
5104514f5e3Sopenharmony_ci        Label isString(env);
5114514f5e3Sopenharmony_ci        Label notString(env);
5124514f5e3Sopenharmony_ci        BRANCH_CIR(builder_.TaggedIsString(param), &isString, &notString);
5134514f5e3Sopenharmony_ci        builder_.Bind(&isString);
5144514f5e3Sopenharmony_ci        {
5154514f5e3Sopenharmony_ci            Label nonZeroLength(env);
5164514f5e3Sopenharmony_ci            auto length = builder_.GetLengthFromString(param);
5174514f5e3Sopenharmony_ci            BRANCH_CIR(builder_.Equal(length, builder_.Int32(0)), &exit, &nonZeroLength);
5184514f5e3Sopenharmony_ci            builder_.Bind(&nonZeroLength);
5194514f5e3Sopenharmony_ci            Label isInteger(env);
5204514f5e3Sopenharmony_ci            BRANCH_CIR(builder_.IsIntegerString(param), &isInteger, &notString);
5214514f5e3Sopenharmony_ci            builder_.Bind(&isInteger);
5224514f5e3Sopenharmony_ci            {
5234514f5e3Sopenharmony_ci                result = IntToTaggedIntPtr(builder_.GetRawHashFromString(param));
5244514f5e3Sopenharmony_ci                builder_.Jump(&exit);
5254514f5e3Sopenharmony_ci            }
5264514f5e3Sopenharmony_ci        }
5274514f5e3Sopenharmony_ci        builder_.Bind(&notString);
5284514f5e3Sopenharmony_ci        {
5294514f5e3Sopenharmony_ci            GateRef glue = acc_.GetGlueFromArgList();
5304514f5e3Sopenharmony_ci            result = LowerCallRuntime(glue, gate, RTSTUB_ID(ToNumericConvertBigInt), { param }, true);
5314514f5e3Sopenharmony_ci            builder_.Jump(&exit);
5324514f5e3Sopenharmony_ci        }
5334514f5e3Sopenharmony_ci    }
5344514f5e3Sopenharmony_ci    builder_.Bind(&exit);
5354514f5e3Sopenharmony_ci    ReplaceHirWithValue(gate, *result);
5364514f5e3Sopenharmony_ci}
5374514f5e3Sopenharmony_ci
5384514f5e3Sopenharmony_civoid BuiltinLowering::LowerGlobalDecodeURIComponent(GateRef gate)
5394514f5e3Sopenharmony_ci{
5404514f5e3Sopenharmony_ci    GateRef glue = acc_.GetGlueFromArgList();
5414514f5e3Sopenharmony_ci    GateRef param = acc_.GetValueIn(gate, 0);
5424514f5e3Sopenharmony_ci    GateRef result = LowerCallRuntime(glue, gate, RTSTUB_ID(DecodeURIComponent), { param }, true);
5434514f5e3Sopenharmony_ci    ReplaceHirWithValue(gate, result);
5444514f5e3Sopenharmony_ci}
5454514f5e3Sopenharmony_ci}  // namespace panda::ecmascript::kungfu
546