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, ¬NumberBranch); 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(¬NumberBranch); 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, ¬Number); 5034514f5e3Sopenharmony_ci builder_.Bind(&isNumber); 5044514f5e3Sopenharmony_ci { 5054514f5e3Sopenharmony_ci result = param; 5064514f5e3Sopenharmony_ci builder_.Jump(&exit); 5074514f5e3Sopenharmony_ci } 5084514f5e3Sopenharmony_ci builder_.Bind(¬Number); 5094514f5e3Sopenharmony_ci { 5104514f5e3Sopenharmony_ci Label isString(env); 5114514f5e3Sopenharmony_ci Label notString(env); 5124514f5e3Sopenharmony_ci BRANCH_CIR(builder_.TaggedIsString(param), &isString, ¬String); 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, ¬String); 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(¬String); 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