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/builtins/builtins_number_stub_builder.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include "ecmascript/builtins/builtins_number.h" 194514f5e3Sopenharmony_ci#include "ecmascript/compiler/new_object_stub_builder.h" 204514f5e3Sopenharmony_ci#include "ecmascript/compiler/stub_builder-inl.h" 214514f5e3Sopenharmony_ci#include "ecmascript/js_arguments.h" 224514f5e3Sopenharmony_ci#include "ecmascript/js_primitive_ref.h" 234514f5e3Sopenharmony_ci#include "ecmascript/tagged_dictionary.h" 244514f5e3Sopenharmony_ci 254514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu { 264514f5e3Sopenharmony_civoid BuiltinsNumberStubBuilder::ParseFloat(Variable *result, Label *exit, Label *slowPath) 274514f5e3Sopenharmony_ci{ 284514f5e3Sopenharmony_ci auto env = GetEnvironment(); 294514f5e3Sopenharmony_ci Label definedMsg(env); 304514f5e3Sopenharmony_ci Label undefinedMsg(env); 314514f5e3Sopenharmony_ci GateRef msg = GetCallArg0(numArgs_); 324514f5e3Sopenharmony_ci BRANCH(TaggedIsUndefined(msg), &undefinedMsg, &definedMsg); 334514f5e3Sopenharmony_ci Bind(&undefinedMsg); 344514f5e3Sopenharmony_ci { 354514f5e3Sopenharmony_ci *result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE)); 364514f5e3Sopenharmony_ci Jump(exit); 374514f5e3Sopenharmony_ci } 384514f5e3Sopenharmony_ci Bind(&definedMsg); 394514f5e3Sopenharmony_ci { 404514f5e3Sopenharmony_ci Label heapObj(env); 414514f5e3Sopenharmony_ci Label stringObj(env); 424514f5e3Sopenharmony_ci BRANCH(TaggedIsHeapObject(msg), &heapObj, slowPath); 434514f5e3Sopenharmony_ci Bind(&heapObj); 444514f5e3Sopenharmony_ci BRANCH(IsString(msg), &stringObj, slowPath); 454514f5e3Sopenharmony_ci Bind(&stringObj); 464514f5e3Sopenharmony_ci { 474514f5e3Sopenharmony_ci *result = CallNGCRuntime(glue_, RTSTUB_ID(NumberHelperStringToDouble), { msg }); 484514f5e3Sopenharmony_ci Jump(exit); 494514f5e3Sopenharmony_ci } 504514f5e3Sopenharmony_ci } 514514f5e3Sopenharmony_ci} 524514f5e3Sopenharmony_ci 534514f5e3Sopenharmony_civoid BuiltinsNumberStubBuilder::ParseInt(Variable *result, Label *exit, Label *slowPath) 544514f5e3Sopenharmony_ci{ 554514f5e3Sopenharmony_ci auto env = GetEnvironment(); 564514f5e3Sopenharmony_ci Label msgIsString(env); 574514f5e3Sopenharmony_ci Label radixIsSpecial(env); 584514f5e3Sopenharmony_ci Label radixIsSpecialInt(env); 594514f5e3Sopenharmony_ci 604514f5e3Sopenharmony_ci DEFVARIABLE(radix, VariableType::INT32(), Int32(0)); 614514f5e3Sopenharmony_ci GateRef msg = GetCallArg0(numArgs_); 624514f5e3Sopenharmony_ci GateRef arg2 = GetCallArg1(numArgs_); 634514f5e3Sopenharmony_ci // ToString maybe throw exception. 644514f5e3Sopenharmony_ci Branch(TaggedIsString(msg), &msgIsString, slowPath); 654514f5e3Sopenharmony_ci Bind(&msgIsString); 664514f5e3Sopenharmony_ci Branch(TaggedIsUndefined(arg2), &radixIsSpecialInt, &radixIsSpecial); 674514f5e3Sopenharmony_ci 684514f5e3Sopenharmony_ci Bind(&radixIsSpecial); 694514f5e3Sopenharmony_ci { 704514f5e3Sopenharmony_ci Label radixIsInt(env); 714514f5e3Sopenharmony_ci // ToInt maybe throw exception. 724514f5e3Sopenharmony_ci Branch(TaggedIsInt(arg2), &radixIsInt, slowPath); 734514f5e3Sopenharmony_ci Bind(&radixIsInt); 744514f5e3Sopenharmony_ci { 754514f5e3Sopenharmony_ci radix = GetInt32OfTInt(arg2); 764514f5e3Sopenharmony_ci Jump(&radixIsSpecialInt); 774514f5e3Sopenharmony_ci } 784514f5e3Sopenharmony_ci } 794514f5e3Sopenharmony_ci Bind(&radixIsSpecialInt); 804514f5e3Sopenharmony_ci { 814514f5e3Sopenharmony_ci *result = CallNGCRuntime(glue_, RTSTUB_ID(StringToNumber), { msg, *radix }); 824514f5e3Sopenharmony_ci Jump(exit); 834514f5e3Sopenharmony_ci } 844514f5e3Sopenharmony_ci} 854514f5e3Sopenharmony_ci 864514f5e3Sopenharmony_civoid BuiltinsNumberStubBuilder::IsFinite(Variable *result, Label *exit, Label *slowPath) 874514f5e3Sopenharmony_ci{ 884514f5e3Sopenharmony_ci auto env = GetEnvironment(); 894514f5e3Sopenharmony_ci GateRef number = GetCallArg0(numArgs_); 904514f5e3Sopenharmony_ci 914514f5e3Sopenharmony_ci // In this method, we actually don't need slow path. 924514f5e3Sopenharmony_ci // The following code is for passing the verification phase. 934514f5e3Sopenharmony_ci Label noSlowPath(env); 944514f5e3Sopenharmony_ci BRANCH(False(), slowPath, &noSlowPath); 954514f5e3Sopenharmony_ci Bind(&noSlowPath); 964514f5e3Sopenharmony_ci 974514f5e3Sopenharmony_ci Label retTrue(env); 984514f5e3Sopenharmony_ci Label retFalse(env); 994514f5e3Sopenharmony_ci 1004514f5e3Sopenharmony_ci Label isNotInt(env); 1014514f5e3Sopenharmony_ci BRANCH(TaggedIsInt(number), &retTrue, &isNotInt); 1024514f5e3Sopenharmony_ci Bind(&isNotInt); 1034514f5e3Sopenharmony_ci { 1044514f5e3Sopenharmony_ci Label isDouble(env); 1054514f5e3Sopenharmony_ci BRANCH(TaggedIsDouble(number), &isDouble, &retFalse); 1064514f5e3Sopenharmony_ci Bind(&isDouble); 1074514f5e3Sopenharmony_ci { 1084514f5e3Sopenharmony_ci GateRef f = GetDoubleOfTDouble(number); 1094514f5e3Sopenharmony_ci BRANCH(DoubleIsNanOrInf(f), &retFalse, &retTrue); 1104514f5e3Sopenharmony_ci } 1114514f5e3Sopenharmony_ci } 1124514f5e3Sopenharmony_ci 1134514f5e3Sopenharmony_ci Bind(&retTrue); 1144514f5e3Sopenharmony_ci { 1154514f5e3Sopenharmony_ci *result = TaggedTrue(); 1164514f5e3Sopenharmony_ci Jump(exit); 1174514f5e3Sopenharmony_ci } 1184514f5e3Sopenharmony_ci Bind(&retFalse); 1194514f5e3Sopenharmony_ci { 1204514f5e3Sopenharmony_ci *result = TaggedFalse(); 1214514f5e3Sopenharmony_ci Jump(exit); 1224514f5e3Sopenharmony_ci } 1234514f5e3Sopenharmony_ci} 1244514f5e3Sopenharmony_ci 1254514f5e3Sopenharmony_civoid BuiltinsNumberStubBuilder::IsNaN(Variable *result, Label *exit, Label *slowPath) 1264514f5e3Sopenharmony_ci{ 1274514f5e3Sopenharmony_ci auto env = GetEnvironment(); 1284514f5e3Sopenharmony_ci GateRef number = GetCallArg0(numArgs_); 1294514f5e3Sopenharmony_ci 1304514f5e3Sopenharmony_ci // In this method, we actually don't need slow path. 1314514f5e3Sopenharmony_ci // The following code is for passing the verification phase. 1324514f5e3Sopenharmony_ci Label noSlowPath(env); 1334514f5e3Sopenharmony_ci BRANCH(False(), slowPath, &noSlowPath); 1344514f5e3Sopenharmony_ci Bind(&noSlowPath); 1354514f5e3Sopenharmony_ci 1364514f5e3Sopenharmony_ci Label retTrue(env); 1374514f5e3Sopenharmony_ci Label retFalse(env); 1384514f5e3Sopenharmony_ci 1394514f5e3Sopenharmony_ci Label isDouble(env); 1404514f5e3Sopenharmony_ci BRANCH(TaggedIsDouble(number), &isDouble, &retFalse); 1414514f5e3Sopenharmony_ci Bind(&isDouble); 1424514f5e3Sopenharmony_ci BRANCH(DoubleIsNAN(GetDoubleOfTDouble(number)), &retTrue, &retFalse); 1434514f5e3Sopenharmony_ci 1444514f5e3Sopenharmony_ci Bind(&retTrue); 1454514f5e3Sopenharmony_ci { 1464514f5e3Sopenharmony_ci *result = TaggedTrue(); 1474514f5e3Sopenharmony_ci Jump(exit); 1484514f5e3Sopenharmony_ci } 1494514f5e3Sopenharmony_ci Bind(&retFalse); 1504514f5e3Sopenharmony_ci { 1514514f5e3Sopenharmony_ci *result = TaggedFalse(); 1524514f5e3Sopenharmony_ci Jump(exit); 1534514f5e3Sopenharmony_ci } 1544514f5e3Sopenharmony_ci} 1554514f5e3Sopenharmony_ci 1564514f5e3Sopenharmony_civoid BuiltinsNumberStubBuilder::IsInteger(Variable *result, Label *exit, Label *slowPath) 1574514f5e3Sopenharmony_ci{ 1584514f5e3Sopenharmony_ci auto env = GetEnvironment(); 1594514f5e3Sopenharmony_ci GateRef number = GetCallArg0(numArgs_); 1604514f5e3Sopenharmony_ci 1614514f5e3Sopenharmony_ci // In this method, we actually don't need slow path. 1624514f5e3Sopenharmony_ci // The following code is for passing the verification phase. 1634514f5e3Sopenharmony_ci Label noSlowPath(env); 1644514f5e3Sopenharmony_ci BRANCH(False(), slowPath, &noSlowPath); 1654514f5e3Sopenharmony_ci Bind(&noSlowPath); 1664514f5e3Sopenharmony_ci 1674514f5e3Sopenharmony_ci Label retTrue(env); 1684514f5e3Sopenharmony_ci Label retFalse(env); 1694514f5e3Sopenharmony_ci 1704514f5e3Sopenharmony_ci Label isNotInt(env); 1714514f5e3Sopenharmony_ci BRANCH(TaggedIsInt(number), &retTrue, &isNotInt); 1724514f5e3Sopenharmony_ci Bind(&isNotInt); 1734514f5e3Sopenharmony_ci { 1744514f5e3Sopenharmony_ci Label isDouble(env); 1754514f5e3Sopenharmony_ci BRANCH(TaggedIsDouble(number), &isDouble, &retFalse); 1764514f5e3Sopenharmony_ci Bind(&isDouble); 1774514f5e3Sopenharmony_ci BRANCH(DoubleIsInteger(GetDoubleOfTDouble(number)), &retTrue, &retFalse); 1784514f5e3Sopenharmony_ci } 1794514f5e3Sopenharmony_ci 1804514f5e3Sopenharmony_ci Bind(&retTrue); 1814514f5e3Sopenharmony_ci { 1824514f5e3Sopenharmony_ci *result = TaggedTrue(); 1834514f5e3Sopenharmony_ci Jump(exit); 1844514f5e3Sopenharmony_ci } 1854514f5e3Sopenharmony_ci Bind(&retFalse); 1864514f5e3Sopenharmony_ci { 1874514f5e3Sopenharmony_ci *result = TaggedFalse(); 1884514f5e3Sopenharmony_ci Jump(exit); 1894514f5e3Sopenharmony_ci } 1904514f5e3Sopenharmony_ci} 1914514f5e3Sopenharmony_ci 1924514f5e3Sopenharmony_civoid BuiltinsNumberStubBuilder::IsSafeInteger(Variable *result, Label *exit, Label *slowPath) 1934514f5e3Sopenharmony_ci{ 1944514f5e3Sopenharmony_ci auto env = GetEnvironment(); 1954514f5e3Sopenharmony_ci GateRef number = GetCallArg0(numArgs_); 1964514f5e3Sopenharmony_ci 1974514f5e3Sopenharmony_ci // In this method, we actually don't need slow path. 1984514f5e3Sopenharmony_ci // The following code is for passing the verification phase. 1994514f5e3Sopenharmony_ci Label noSlowPath(env); 2004514f5e3Sopenharmony_ci BRANCH(False(), slowPath, &noSlowPath); 2014514f5e3Sopenharmony_ci Bind(&noSlowPath); 2024514f5e3Sopenharmony_ci 2034514f5e3Sopenharmony_ci Label retTrue(env); 2044514f5e3Sopenharmony_ci Label retFalse(env); 2054514f5e3Sopenharmony_ci 2064514f5e3Sopenharmony_ci Label isNotInt(env); 2074514f5e3Sopenharmony_ci BRANCH(TaggedIsInt(number), &retTrue, &isNotInt); 2084514f5e3Sopenharmony_ci Bind(&isNotInt); 2094514f5e3Sopenharmony_ci { 2104514f5e3Sopenharmony_ci Label isDouble(env); 2114514f5e3Sopenharmony_ci BRANCH(TaggedIsDouble(number), &isDouble, &retFalse); 2124514f5e3Sopenharmony_ci Bind(&isDouble); 2134514f5e3Sopenharmony_ci { 2144514f5e3Sopenharmony_ci Label isNotNanOrInf(env); 2154514f5e3Sopenharmony_ci GateRef f = GetDoubleOfTDouble(number); 2164514f5e3Sopenharmony_ci BRANCH(DoubleIsNanOrInf(f), &retFalse, &isNotNanOrInf); 2174514f5e3Sopenharmony_ci Bind(&isNotNanOrInf); 2184514f5e3Sopenharmony_ci { 2194514f5e3Sopenharmony_ci Label checkSafe(env); 2204514f5e3Sopenharmony_ci GateRef truncated = ChangeInt32ToFloat64(TruncFloatToInt64(f)); 2214514f5e3Sopenharmony_ci BRANCH(DoubleEqual(f, truncated), &checkSafe, &retFalse); 2224514f5e3Sopenharmony_ci Bind(&checkSafe); 2234514f5e3Sopenharmony_ci BRANCH(DoubleLessThanOrEqual(DoubleAbs(f), Double(base::MAX_SAFE_INTEGER)), &retTrue, &retFalse); 2244514f5e3Sopenharmony_ci } 2254514f5e3Sopenharmony_ci } 2264514f5e3Sopenharmony_ci } 2274514f5e3Sopenharmony_ci 2284514f5e3Sopenharmony_ci Bind(&retTrue); 2294514f5e3Sopenharmony_ci { 2304514f5e3Sopenharmony_ci *result = TaggedTrue(); 2314514f5e3Sopenharmony_ci Jump(exit); 2324514f5e3Sopenharmony_ci } 2334514f5e3Sopenharmony_ci Bind(&retFalse); 2344514f5e3Sopenharmony_ci { 2354514f5e3Sopenharmony_ci *result = TaggedFalse(); 2364514f5e3Sopenharmony_ci Jump(exit); 2374514f5e3Sopenharmony_ci } 2384514f5e3Sopenharmony_ci} 2394514f5e3Sopenharmony_ci 2404514f5e3Sopenharmony_civoid BuiltinsNumberStubBuilder::GenNumberConstructor(GateRef nativeCode, GateRef func, GateRef newTarget) 2414514f5e3Sopenharmony_ci{ 2424514f5e3Sopenharmony_ci auto env = GetEnvironment(); 2434514f5e3Sopenharmony_ci DEFVARIABLE(res, VariableType::JS_ANY(), Undefined()); 2444514f5e3Sopenharmony_ci DEFVARIABLE(numberValue, VariableType::JS_ANY(), IntToTaggedPtr(IntPtr(0))); 2454514f5e3Sopenharmony_ci Label thisCollectionObj(env); 2464514f5e3Sopenharmony_ci Label slowPath(env); 2474514f5e3Sopenharmony_ci Label slowPath1(env); 2484514f5e3Sopenharmony_ci Label exit(env); 2494514f5e3Sopenharmony_ci 2504514f5e3Sopenharmony_ci Label hasArg(env); 2514514f5e3Sopenharmony_ci Label numberCreate(env); 2524514f5e3Sopenharmony_ci Label newTargetIsHeapObject(env); 2534514f5e3Sopenharmony_ci BRANCH(TaggedIsHeapObject(newTarget), &newTargetIsHeapObject, &slowPath); 2544514f5e3Sopenharmony_ci Bind(&newTargetIsHeapObject); 2554514f5e3Sopenharmony_ci BRANCH(Int64GreaterThan(numArgs_, IntPtr(0)), &hasArg, &numberCreate); 2564514f5e3Sopenharmony_ci Bind(&hasArg); 2574514f5e3Sopenharmony_ci { 2584514f5e3Sopenharmony_ci GateRef value = GetArgFromArgv(Int32(0)); 2594514f5e3Sopenharmony_ci Label number(env); 2604514f5e3Sopenharmony_ci BRANCH(TaggedIsNumber(value), &number, &slowPath); 2614514f5e3Sopenharmony_ci Bind(&number); 2624514f5e3Sopenharmony_ci { 2634514f5e3Sopenharmony_ci numberValue = value; 2644514f5e3Sopenharmony_ci res = value; 2654514f5e3Sopenharmony_ci Jump(&numberCreate); 2664514f5e3Sopenharmony_ci } 2674514f5e3Sopenharmony_ci } 2684514f5e3Sopenharmony_ci 2694514f5e3Sopenharmony_ci Bind(&numberCreate); 2704514f5e3Sopenharmony_ci Label newObj(env); 2714514f5e3Sopenharmony_ci Label newTargetIsJSFunction(env); 2724514f5e3Sopenharmony_ci BRANCH(TaggedIsUndefined(newTarget), &exit, &newObj); 2734514f5e3Sopenharmony_ci Bind(&newObj); 2744514f5e3Sopenharmony_ci { 2754514f5e3Sopenharmony_ci BRANCH(IsJSFunction(newTarget), &newTargetIsJSFunction, &slowPath); 2764514f5e3Sopenharmony_ci Bind(&newTargetIsJSFunction); 2774514f5e3Sopenharmony_ci { 2784514f5e3Sopenharmony_ci Label intialHClassIsHClass(env); 2794514f5e3Sopenharmony_ci GateRef intialHClass = Load(VariableType::JS_ANY(), newTarget, 2804514f5e3Sopenharmony_ci IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET)); 2814514f5e3Sopenharmony_ci BRANCH(IsJSHClass(intialHClass), &intialHClassIsHClass, &slowPath1); 2824514f5e3Sopenharmony_ci Bind(&intialHClassIsHClass); 2834514f5e3Sopenharmony_ci { 2844514f5e3Sopenharmony_ci NewObjectStubBuilder newBuilder(this); 2854514f5e3Sopenharmony_ci newBuilder.SetParameters(glue_, 0); 2864514f5e3Sopenharmony_ci Label afterNew(env); 2874514f5e3Sopenharmony_ci newBuilder.NewJSObject(&res, &afterNew, intialHClass); 2884514f5e3Sopenharmony_ci Bind(&afterNew); 2894514f5e3Sopenharmony_ci { 2904514f5e3Sopenharmony_ci GateRef valueOffset = IntPtr(JSPrimitiveRef::VALUE_OFFSET); 2914514f5e3Sopenharmony_ci Store(VariableType::INT64(), glue_, *res, valueOffset, *numberValue); 2924514f5e3Sopenharmony_ci Jump(&exit); 2934514f5e3Sopenharmony_ci } 2944514f5e3Sopenharmony_ci } 2954514f5e3Sopenharmony_ci Bind(&slowPath1); 2964514f5e3Sopenharmony_ci { 2974514f5e3Sopenharmony_ci GateRef argv = GetArgv(); 2984514f5e3Sopenharmony_ci res = CallBuiltinRuntimeWithNewTarget(glue_, 2994514f5e3Sopenharmony_ci { glue_, nativeCode, func, thisValue_, numArgs_, argv, newTarget }); 3004514f5e3Sopenharmony_ci Jump(&exit); 3014514f5e3Sopenharmony_ci } 3024514f5e3Sopenharmony_ci } 3034514f5e3Sopenharmony_ci } 3044514f5e3Sopenharmony_ci 3054514f5e3Sopenharmony_ci Bind(&slowPath); 3064514f5e3Sopenharmony_ci { 3074514f5e3Sopenharmony_ci GateRef argv = GetArgv(); 3084514f5e3Sopenharmony_ci res = CallBuiltinRuntime(glue_, { glue_, nativeCode, func, thisValue_, numArgs_, argv }, true); 3094514f5e3Sopenharmony_ci Jump(&exit); 3104514f5e3Sopenharmony_ci } 3114514f5e3Sopenharmony_ci Bind(&exit); 3124514f5e3Sopenharmony_ci Return(*res); 3134514f5e3Sopenharmony_ci} 3144514f5e3Sopenharmony_ci 3154514f5e3Sopenharmony_civoid BuiltinsNumberStubBuilder::ToString(Variable *result, Label *exit, Label *slowPath) 3164514f5e3Sopenharmony_ci{ 3174514f5e3Sopenharmony_ci auto env = GetEnvironment(); 3184514f5e3Sopenharmony_ci Label definedMsg(env); 3194514f5e3Sopenharmony_ci Label undefinedMsg(env); 3204514f5e3Sopenharmony_ci Label thisIsInt(env); 3214514f5e3Sopenharmony_ci Label msgIsInt(env); 3224514f5e3Sopenharmony_ci BRANCH(TaggedIsInt(thisValue_), &thisIsInt, slowPath); 3234514f5e3Sopenharmony_ci Bind(&thisIsInt); 3244514f5e3Sopenharmony_ci GateRef thisValueInt = GetInt32OfTInt(thisValue_); 3254514f5e3Sopenharmony_ci GateRef msg = GetCallArg0(numArgs_); 3264514f5e3Sopenharmony_ci BRANCH(TaggedIsUndefined(msg), &undefinedMsg, &definedMsg); 3274514f5e3Sopenharmony_ci Bind(&undefinedMsg); 3284514f5e3Sopenharmony_ci { 3294514f5e3Sopenharmony_ci *result = NumberToString(thisValueInt, Int32(10)); // 10: means radix 3304514f5e3Sopenharmony_ci Jump(exit); 3314514f5e3Sopenharmony_ci } 3324514f5e3Sopenharmony_ci Bind(&definedMsg); 3334514f5e3Sopenharmony_ci BRANCH(TaggedIsInt(msg), &msgIsInt, slowPath); 3344514f5e3Sopenharmony_ci Bind(&msgIsInt); 3354514f5e3Sopenharmony_ci { 3364514f5e3Sopenharmony_ci Label throwError(env); 3374514f5e3Sopenharmony_ci Label notThrowError(env); 3384514f5e3Sopenharmony_ci GateRef msgValue = GetInt32OfTInt(msg); 3394514f5e3Sopenharmony_ci GateRef outOfRange = BitOr(Int32LessThan(msgValue, Int32(base::MIN_RADIX)), 3404514f5e3Sopenharmony_ci Int32GreaterThan(msgValue, Int32(base::MAX_RADIX))); 3414514f5e3Sopenharmony_ci BRANCH(outOfRange, &throwError, ¬ThrowError); 3424514f5e3Sopenharmony_ci Bind(&throwError); 3434514f5e3Sopenharmony_ci { 3444514f5e3Sopenharmony_ci GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InvalidRadixLength)); 3454514f5e3Sopenharmony_ci CallRuntime(glue_, RTSTUB_ID(ThrowRangeError), { IntToTaggedInt(taggedId) }); 3464514f5e3Sopenharmony_ci Jump(exit); 3474514f5e3Sopenharmony_ci } 3484514f5e3Sopenharmony_ci Bind(¬ThrowError); 3494514f5e3Sopenharmony_ci { 3504514f5e3Sopenharmony_ci *result = NumberToString(thisValueInt, msgValue); 3514514f5e3Sopenharmony_ci Jump(exit); 3524514f5e3Sopenharmony_ci } 3534514f5e3Sopenharmony_ci } 3544514f5e3Sopenharmony_ci} 3554514f5e3Sopenharmony_ci 3564514f5e3Sopenharmony_ciGateRef BuiltinsNumberStubBuilder::NumberToString(GateRef number, GateRef radix) 3574514f5e3Sopenharmony_ci{ 3584514f5e3Sopenharmony_ci auto env = GetEnvironment(); 3594514f5e3Sopenharmony_ci Label subentry(env); 3604514f5e3Sopenharmony_ci env->SubCfgEntry(&subentry); 3614514f5e3Sopenharmony_ci DEFVARIABLE(result, VariableType::JS_POINTER(), Hole()); 3624514f5e3Sopenharmony_ci DEFVARIABLE(n, VariableType::INT32(), number); 3634514f5e3Sopenharmony_ci 3644514f5e3Sopenharmony_ci Label exit(env); 3654514f5e3Sopenharmony_ci Label numIsNegative(env); 3664514f5e3Sopenharmony_ci Label numNotNegative(env); 3674514f5e3Sopenharmony_ci Label afterFast(env); 3684514f5e3Sopenharmony_ci Label afterNew(env); 3694514f5e3Sopenharmony_ci GateRef isNegative = Int32LessThan(number, Int32(0)); 3704514f5e3Sopenharmony_ci BRANCH(isNegative, &numIsNegative, &numNotNegative); 3714514f5e3Sopenharmony_ci Bind(&numIsNegative); 3724514f5e3Sopenharmony_ci { 3734514f5e3Sopenharmony_ci n = Int32Sub(Int32(0), *n); 3744514f5e3Sopenharmony_ci Jump(&afterFast); 3754514f5e3Sopenharmony_ci } 3764514f5e3Sopenharmony_ci Bind(&numNotNegative); 3774514f5e3Sopenharmony_ci { 3784514f5e3Sopenharmony_ci Label thisIsZero(env); 3794514f5e3Sopenharmony_ci Label thisNotZero(env); 3804514f5e3Sopenharmony_ci Label thisIsSingle(env); 3814514f5e3Sopenharmony_ci Label thisNotSingle(env); 3824514f5e3Sopenharmony_ci BRANCH(Int32Equal(number, Int32(0)), &thisIsZero, &thisNotZero); 3834514f5e3Sopenharmony_ci Bind(&thisIsZero); 3844514f5e3Sopenharmony_ci { 3854514f5e3Sopenharmony_ci result = GetGlobalConstantValue(VariableType::JS_POINTER(), glue_, ConstantIndex::ZERO_INDEX); 3864514f5e3Sopenharmony_ci Jump(&exit); 3874514f5e3Sopenharmony_ci } 3884514f5e3Sopenharmony_ci Bind(&thisNotZero); 3894514f5e3Sopenharmony_ci { 3904514f5e3Sopenharmony_ci BRANCH(Int32LessThan(number, radix), &thisIsSingle, &afterFast); 3914514f5e3Sopenharmony_ci Bind(&thisIsSingle); 3924514f5e3Sopenharmony_ci GateRef singleCharTable = GetSingleCharTable(glue_); 3934514f5e3Sopenharmony_ci GateRef index = ToCharCode(number); 3944514f5e3Sopenharmony_ci result = GetValueFromTaggedArray(singleCharTable, index); 3954514f5e3Sopenharmony_ci Jump(&exit); 3964514f5e3Sopenharmony_ci } 3974514f5e3Sopenharmony_ci } 3984514f5e3Sopenharmony_ci Bind(&afterFast); 3994514f5e3Sopenharmony_ci { 4004514f5e3Sopenharmony_ci DEFVARIABLE(temp, VariableType::INT32(), *n); 4014514f5e3Sopenharmony_ci DEFVARIABLE(length, VariableType::INT32(), Int32(0)); 4024514f5e3Sopenharmony_ci Label lenAddOne(env); 4034514f5e3Sopenharmony_ci Label lenNotAddOne(env); 4044514f5e3Sopenharmony_ci BRANCH(isNegative, &lenAddOne, &lenNotAddOne); 4054514f5e3Sopenharmony_ci Bind(&lenAddOne); 4064514f5e3Sopenharmony_ci { 4074514f5e3Sopenharmony_ci length = Int32Add(*length, Int32(1)); 4084514f5e3Sopenharmony_ci Jump(&lenNotAddOne); 4094514f5e3Sopenharmony_ci } 4104514f5e3Sopenharmony_ci Bind(&lenNotAddOne); 4114514f5e3Sopenharmony_ci { 4124514f5e3Sopenharmony_ci Label loopHead(env); 4134514f5e3Sopenharmony_ci Label loopEnd(env); 4144514f5e3Sopenharmony_ci Label next(env); 4154514f5e3Sopenharmony_ci Label loopExit(env); 4164514f5e3Sopenharmony_ci Jump(&loopHead); 4174514f5e3Sopenharmony_ci LoopBegin(&loopHead); 4184514f5e3Sopenharmony_ci { 4194514f5e3Sopenharmony_ci BRANCH(Int32GreaterThan(*temp, Int32(0)), &next, &loopExit); 4204514f5e3Sopenharmony_ci Bind(&next); 4214514f5e3Sopenharmony_ci { 4224514f5e3Sopenharmony_ci temp = Int32Div(*temp, radix); 4234514f5e3Sopenharmony_ci length = Int32Add(*length, Int32(1)); 4244514f5e3Sopenharmony_ci Jump(&loopEnd); 4254514f5e3Sopenharmony_ci } 4264514f5e3Sopenharmony_ci } 4274514f5e3Sopenharmony_ci Bind(&loopEnd); 4284514f5e3Sopenharmony_ci LoopEnd(&loopHead, env, glue_); 4294514f5e3Sopenharmony_ci Bind(&loopExit); 4304514f5e3Sopenharmony_ci { 4314514f5e3Sopenharmony_ci NewObjectStubBuilder newBuilder(this); 4324514f5e3Sopenharmony_ci newBuilder.SetParameters(glue_, 0); 4334514f5e3Sopenharmony_ci newBuilder.AllocLineStringObject(&result, &afterNew, *length, true); 4344514f5e3Sopenharmony_ci Bind(&afterNew); 4354514f5e3Sopenharmony_ci { 4364514f5e3Sopenharmony_ci GateRef dst = ChangeTaggedPointerToInt64(PtrAdd(*result, IntPtr(LineEcmaString::DATA_OFFSET))); 4374514f5e3Sopenharmony_ci DEFVARIABLE(cursor, VariableType::INT32(), Int32Sub(*length, Int32(1))); 4384514f5e3Sopenharmony_ci DEFVARIABLE(digit, VariableType::INT32(), Int32(0)); 4394514f5e3Sopenharmony_ci DEFVARIABLE(dstTmp, VariableType::NATIVE_POINTER(), dst); 4404514f5e3Sopenharmony_ci dstTmp = PtrAdd(*dstTmp, PtrMul(ZExtInt32ToPtr(*cursor), IntPtr(sizeof(uint8_t)))); 4414514f5e3Sopenharmony_ci Label loopHead1(env); 4424514f5e3Sopenharmony_ci Label loopEnd1(env); 4434514f5e3Sopenharmony_ci Label next1(env); 4444514f5e3Sopenharmony_ci Label loopExit1(env); 4454514f5e3Sopenharmony_ci Jump(&loopHead1); 4464514f5e3Sopenharmony_ci LoopBegin(&loopHead1); 4474514f5e3Sopenharmony_ci { 4484514f5e3Sopenharmony_ci BRANCH(Int32GreaterThan(*n, Int32(0)), &next1, &loopExit1); 4494514f5e3Sopenharmony_ci Bind(&next1); 4504514f5e3Sopenharmony_ci { 4514514f5e3Sopenharmony_ci digit = Int32Mod(*n, radix); 4524514f5e3Sopenharmony_ci n = Int32Div(*n, radix); 4534514f5e3Sopenharmony_ci GateRef digitChar = ToCharCode(*digit); 4544514f5e3Sopenharmony_ci Store(VariableType::INT8(), glue_, *dstTmp, IntPtr(0), TruncInt32ToInt8(digitChar)); 4554514f5e3Sopenharmony_ci cursor = Int32Sub(*cursor, Int32(1)); 4564514f5e3Sopenharmony_ci Jump(&loopEnd1); 4574514f5e3Sopenharmony_ci } 4584514f5e3Sopenharmony_ci } 4594514f5e3Sopenharmony_ci Bind(&loopEnd1); 4604514f5e3Sopenharmony_ci dstTmp = PtrSub(*dstTmp, IntPtr(sizeof(uint8_t))); 4614514f5e3Sopenharmony_ci // Work with low level buffers, we can't call GC. Loop is simple, no more 32 iteration. 4624514f5e3Sopenharmony_ci // Ability using GC at the end of loop require add additional calculate pointer to data of string 4634514f5e3Sopenharmony_ci // on each iteration. 4644514f5e3Sopenharmony_ci LoopEnd(&loopHead1); 4654514f5e3Sopenharmony_ci Bind(&loopExit1); 4664514f5e3Sopenharmony_ci { 4674514f5e3Sopenharmony_ci Label strInsertSign(env); 4684514f5e3Sopenharmony_ci Label strNotInsertSign(env); 4694514f5e3Sopenharmony_ci BRANCH(isNegative, &strInsertSign, &exit); 4704514f5e3Sopenharmony_ci Bind(&strInsertSign); 4714514f5e3Sopenharmony_ci { 4724514f5e3Sopenharmony_ci dstTmp = PtrSub(*dstTmp, IntPtr(sizeof(uint8_t))); 4734514f5e3Sopenharmony_ci Store(VariableType::INT8(), glue_, dst, IntPtr(0), Int8(45)); // 45: means '-' 4744514f5e3Sopenharmony_ci Jump(&exit); 4754514f5e3Sopenharmony_ci } 4764514f5e3Sopenharmony_ci } 4774514f5e3Sopenharmony_ci } 4784514f5e3Sopenharmony_ci } 4794514f5e3Sopenharmony_ci } 4804514f5e3Sopenharmony_ci } 4814514f5e3Sopenharmony_ci Bind(&exit); 4824514f5e3Sopenharmony_ci auto ret = *result; 4834514f5e3Sopenharmony_ci env->SubCfgExit(); 4844514f5e3Sopenharmony_ci return ret; 4854514f5e3Sopenharmony_ci} 4864514f5e3Sopenharmony_ci} // namespace panda::ecmascript::kungfu 487