diff --git a/ecmascript/base/json_stringifier.cpp b/ecmascript/base/json_stringifier.cpp index 79682be22365f59d2583b9ca3653e6801a7c34e1..b10ccb33eb88ae9afbd329b80ec7e380d33522a0 100644 --- a/ecmascript/base/json_stringifier.cpp +++ b/ecmascript/base/json_stringifier.cpp @@ -287,7 +287,7 @@ JSTaggedValue JsonStringifier::GetSerializeValue(const JSHandle & JSTaggedValue tagValue = value.GetTaggedValue(); JSHandle undefined = thread_->GlobalConstants()->GetHandledUndefined(); // If Type(value) is Object, then - if (value->IsECMAObject()) { + if (value->IsECMAObject() || value->IsBigInt()) { // a. Let toJSON be Get(value, "toJSON"). JSHandle toJson = thread_->GlobalConstants()->GetHandledToJsonString(); JSHandle toJsonFun( @@ -370,13 +370,13 @@ JSTaggedValue JsonStringifier::SerializeJSONProperty(const JSHandle(valHandle))); - return tagValue; + THROW_TYPE_ERROR_AND_RETURN(thread_, "cannot serialize a BigInt", JSTaggedValue::Exception()); } default: { if (!tagValue.IsCallable()) { @@ -646,6 +646,8 @@ void JsonStringifier::SerializePrimitiveRef(const JSHandle &primi } } else if (primitive.IsBoolean()) { result_ += primitive.IsTrue() ? "true" : "false"; + } else if (primitive.IsBigInt()) { + THROW_TYPE_ERROR(thread_, "cannot serialize a BigInt"); } } diff --git a/ecmascript/builtins.cpp b/ecmascript/builtins.cpp index ad99651c508d542e3c80207798683a8908a9922b..52af795bc2bec1adba17ec52b4334550cb5cf847 100644 --- a/ecmascript/builtins.cpp +++ b/ecmascript/builtins.cpp @@ -273,14 +273,15 @@ void Builtins::Initialize(const JSHandle &env, JSThread *thread) if (env == vm_->GetGlobalEnv()) { InitializeAllTypeError(env, objFuncDynclass); InitializeSymbol(env, primRefObjDynclass); + InitializeBigInt(env, primRefObjDynclass); } else { // error and symbol need to be shared when initialize realm InitializeAllTypeErrorWithRealm(env); InitializeSymbolWithRealm(env, primRefObjDynclass); + InitializeBigIntWithRealm(env); } InitializeNumber(env, globalObject, primRefObjDynclass); - InitializeBigInt(env, objFuncDynclass); InitializeDate(env, objFuncDynclass); InitializeObject(env, objFuncPrototype, objectFunction); InitializeBoolean(env, primRefObjDynclass); @@ -769,12 +770,23 @@ void Builtins::InitializeNumber(const JSHandle &env, const JSHandleSetNumberFunction(thread_, numFunction); } +void Builtins::InitializeBigIntWithRealm(const JSHandle &realm) const +{ + [[maybe_unused]] EcmaHandleScope scope(thread_); + JSHandle env = vm_->GetGlobalEnv(); + realm->SetBigIntFunction(thread_, env->GetBigIntFunction()); + + JSHandle nameString(factory_->NewFromASCII("BigInt")); + JSHandle globalObject(thread_, realm->GetGlobalObject()); + PropertyDescriptor descriptor(thread_, env->GetBigIntFunction(), true, false, true); + JSObject::DefineOwnProperty(thread_, globalObject, nameString, descriptor); +} -void Builtins::InitializeBigInt(const JSHandle &env, const JSHandle &objFuncDynclass) const +void Builtins::InitializeBigInt(const JSHandle &env, const JSHandle &primRefObjDynclass) const { [[maybe_unused]] EcmaHandleScope scope(thread_); // BigInt.prototype - JSHandle bigIntFuncPrototype = factory_->NewJSObjectWithInit(objFuncDynclass); + JSHandle bigIntFuncPrototype = factory_->NewJSObjectWithInit(primRefObjDynclass); JSHandle bigIntFuncPrototypeValue(bigIntFuncPrototype); // BigInt.prototype_or_dynclass diff --git a/ecmascript/builtins.h b/ecmascript/builtins.h index e2b8abb2f03239bc6e4be36c55e46416fbc49707..aa7dbcb1781cec8dab6d575b94924062467a1cca 100644 --- a/ecmascript/builtins.h +++ b/ecmascript/builtins.h @@ -72,7 +72,10 @@ private: void InitializeNumber(const JSHandle &env, const JSHandle &globalObject, const JSHandle &primRefObjDynclass); - void InitializeBigInt(const JSHandle &env, const JSHandle &objFuncDynclass) const; + void InitializeBigInt(const JSHandle &env, const JSHandle &primRefObjDynclass) const; + + void InitializeBigIntWithRealm(const JSHandle &realm) const; + void InitializeDate(const JSHandle &env, const JSHandle &objFuncDynclass) const; void InitializeBoolean(const JSHandle &env, const JSHandle &primRefObjDynclass) const; diff --git a/ecmascript/builtins/tests/builtins_json_test.cpp b/ecmascript/builtins/tests/builtins_json_test.cpp index f35a145d779b7fd2b50f9ac82d14e222815ecd68..d82cd18c502657b759a9ca163a69f379cd59e416 100644 --- a/ecmascript/builtins/tests/builtins_json_test.cpp +++ b/ecmascript/builtins/tests/builtins_json_test.cpp @@ -569,11 +569,12 @@ HWTEST_F_L0(BuiltinsJsonTest, Stringify6) // Test for bigint object ecmaRuntimeCallInfo->SetCallArg(0, bigIntHandle.GetTaggedValue()); prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); - JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo.get()); - TestHelper::TearDownFrame(thread, prev); - CString str = ConvertToString(EcmaString::Cast(result.GetTaggedObject())); - ASSERT_TRUE(result.IsString()); - ASSERT_TRUE(EcmaString::StringsAreEqual(EcmaString::Cast(numericValue.GetTaggedValue().GetTaggedObject()), - EcmaString::Cast(result.GetTaggedObject()))); + [[maybe_unused]] JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo.get()); + bool hasPendingException = false; + if (thread->HasPendingException()) { + hasPendingException = true; + thread->ClearException(); + } + ASSERT_TRUE(hasPendingException); } } // namespace panda::test diff --git a/ecmascript/compiler/bc_call_signature.h b/ecmascript/compiler/bc_call_signature.h index 4a4245e64573035dd641701b54d64dc26d18196d..b8cbdd255dbf5f36cba478b098e03d6fccb38261 100644 --- a/ecmascript/compiler/bc_call_signature.h +++ b/ecmascript/compiler/bc_call_signature.h @@ -158,6 +158,7 @@ namespace panda::ecmascript::kungfu { T(HandleLdFunctionPref) \ T(HandleNewLexEnvWithNameDynPrefImm16Imm16) \ T(HandleLdBigIntPrefId32) \ + T(HandleToNumericPrefV8) \ T(HandleMovDynV8V8) \ T(HandleMovDynV16V16) \ T(HandleLdaStrId32) \ diff --git a/ecmascript/compiler/bytecode_circuit_builder.cpp b/ecmascript/compiler/bytecode_circuit_builder.cpp index 1401bae123a9ab10deaacd2e681dbbb64ccce1bc..ac41aba707ad501b11ca81dc1ea150835cc6f6c1 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.cpp +++ b/ecmascript/compiler/bytecode_circuit_builder.cpp @@ -1687,6 +1687,13 @@ BytecodeInfo BytecodeCircuitBuilder::GetBytecodeInfo(const uint8_t *pc) info.inputs.emplace_back(StringId(stringId)); break; } + case EcmaOpcode::TONUMERIC_PREF_V8: { + uint16_t v0 = READ_INST_8_1(); + info.accOut = true; + info.offset = BytecodeOffset::THREE; + info.inputs.emplace_back(VirtualRegister(v0)); + break; + } case EcmaOpcode::SUPERCALL_PREF_IMM16_V8: { uint16_t range = READ_INST_16_1(); uint16_t v0 = READ_INST_8_3(); diff --git a/ecmascript/compiler/interpreter_stub.cpp b/ecmascript/compiler/interpreter_stub.cpp index db20829a01e71c1d46dd9c5a9aa3f95fd42341bc..b938f9183bb80d2c00178bb33f39b8f992030827 100644 --- a/ecmascript/compiler/interpreter_stub.cpp +++ b/ecmascript/compiler/interpreter_stub.cpp @@ -5088,6 +5088,27 @@ DECLARE_ASM_HANDLER(HandleLdBigIntPrefId32) DISPATCH_WITH_ACC(PREF_ID32); } +DECLARE_ASM_HANDLER(HandleToNumericPrefV8) +{ + auto env = GetEnvironment(); + DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); + GateRef v0 = ReadInst8_1(pc); + GateRef value = GetVregValue(sp, ZExtInt8ToPtr(v0)); + GateRef res = CallRuntime(glue, RTSTUB_ID(ToNumeric), { value }); + Label isException(env); + Label notException(env); + Branch(TaggedIsException(res), &isException, ¬Exception); + Bind(&isException); + { + DISPATCH_LAST_WITH_ACC(); + } + Bind(¬Exception); + { + varAcc = res; + DISPATCH_WITH_ACC(PREF_V8); + } +} + DECLARE_ASM_HANDLER(HandleNewLexEnvWithNameDynPrefImm16Imm16) { auto env = GetEnvironment(); diff --git a/ecmascript/compiler/slowpath_lowering.cpp b/ecmascript/compiler/slowpath_lowering.cpp index 5072f21941ba7207ea5b1e588e15e81c1017a8ae..c030a89609ebedd8245afa1e35b68ad99951d0ba 100644 --- a/ecmascript/compiler/slowpath_lowering.cpp +++ b/ecmascript/compiler/slowpath_lowering.cpp @@ -469,6 +469,9 @@ void SlowPathLowering::Lower(GateRef gate) case LDBIGINT_PREF_ID32: LowerLdBigInt(gate, glue, jsFunc); break; + case TONUMERIC_PREF_V8: + LowerToNumeric(gate, glue); + break; case LDMODULEVAR_PREF_ID32_IMM8: LowerLdModuleVar(gate, glue); break; @@ -1411,6 +1414,14 @@ void SlowPathLowering::LowerLdBigInt(GateRef gate, GateRef glue, GateRef jsFunc) ReplaceHirToSubCfg(gate, result, successControl, failControl, true); } +void SlowPathLowering::LowerToNumeric(GateRef gate, GateRef glue) +{ + const int id = RTSTUB_ID(ToNumeric); + // 1: number of value inputs + ASSERT(acc_.GetNumValueIn(gate) == 1); + GateRef newGate = LowerCallRuntime(glue, id, {acc_.GetValueIn(gate, 0)}); + ReplaceHirToCall(gate, newGate); +} void SlowPathLowering::LowerLdModuleVar(GateRef gate, GateRef glue) { std::vector successControl; diff --git a/ecmascript/compiler/slowpath_lowering.h b/ecmascript/compiler/slowpath_lowering.h index a200bce201d1933f5350e4cdaea18e9b5ce67469..c64e1d387ffcdddf85c9456e98b06286b1ff9e3f 100644 --- a/ecmascript/compiler/slowpath_lowering.h +++ b/ecmascript/compiler/slowpath_lowering.h @@ -208,6 +208,7 @@ private: void LowerGetTemplateObject(GateRef gate, GateRef glue); void LowerSetObjectWithProto(GateRef gate, GateRef glue); void LowerLdBigInt(GateRef gate, GateRef glue, GateRef jsFunc); + void LowerToNumeric(GateRef gate, GateRef glue); void LowerLdModuleVar(GateRef gate, GateRef glue); void LowerGetModuleNamespace(GateRef gate, GateRef glue); void LowerGetIteratorNext(GateRef gate, GateRef glue); diff --git a/ecmascript/ecma_isa.yaml b/ecmascript/ecma_isa.yaml index 47f71d643a1d3974b2def05bf52ba57a2720b22c..88af7df49e79aa21b68b3d9b117b06fc71c4630b 100644 --- a/ecmascript/ecma_isa.yaml +++ b/ecmascript/ecma_isa.yaml @@ -600,3 +600,7 @@ groups: prefix: ecma format: [pref_op_id_32] properties: [string_id] + - sig: ecma.tonumeric v:in:top + acc: inout:top + prefix: ecma + format: [pref_op_v_8] \ No newline at end of file diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index e7c11799a3e59cd6f1b63073a134440c71245231..eb3a4d30496827aee3864f54cc94fe21d5dfbfdd 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -1144,7 +1144,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool LOG_INST() << "intrinsics::tonumber" << " v" << v0; JSTaggedValue value = GET_VREG_VALUE(v0); - if (value.IsNumber() || value.IsBigInt()) { + if (value.IsNumber()) { // fast path SET_ACC(value); } else { @@ -3459,6 +3459,18 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, ConstantPool SET_ACC(res); DISPATCH(BytecodeInstruction::Format::PREF_ID32); } + HANDLE_OPCODE(HANDLE_TONUMERIC_PREF_V8) { + uint16_t v0 = READ_INST_8_1(); + + LOG_INST() << "intrinsics::tonumeric" + << " v" << v0; + JSTaggedValue value = GET_VREG_VALUE(v0); + SAVE_PC(); + JSTaggedValue res = SlowRuntimeStub::ToNumeric(thread, value); + INTERPRETER_RETURN_IF_ABRUPT(res); + SET_ACC(res); + DISPATCH(BytecodeInstruction::Format::PREF_V8); + } HANDLE_OPCODE(HANDLE_SUPERCALL_PREF_IMM16_V8) { uint16_t range = READ_INST_16_1(); uint16_t v0 = READ_INST_8_3(); @@ -4038,6 +4050,7 @@ std::string GetEcmaOpcodeStr(EcmaOpcode opcode) {STOWNBYNAMEWITHNAMESET_PREF_ID32_V8, "STOWNBYNAMEWITHNAMESET"}, {LDFUNCTION_PREF, "LDFUNCTION"}, {LDBIGINT_PREF_ID32, "LDBIGINT"}, + {TONUMERIC_PREF_V8, "TONUMERIC"}, {MOV_DYN_V8_V8, "MOV_DYN"}, {MOV_DYN_V16_V16, "MOV_DYN"}, {LDA_STR_ID32, "LDA_STR"}, diff --git a/ecmascript/interpreter/interpreter.h b/ecmascript/interpreter/interpreter.h index d37e9b5be2415b6799c374f5cbc01e12ddb272eb..c24f3ee4a18b428d0d1322825368918b1b0cac8c 100644 --- a/ecmascript/interpreter/interpreter.h +++ b/ecmascript/interpreter/interpreter.h @@ -204,6 +204,7 @@ enum EcmaOpcode { LDFUNCTION_PREF, NEWLEXENVWITHNAMEDYN_PREF_IMM16_IMM16, LDBIGINT_PREF_ID32, + TONUMERIC_PREF_V8, MOV_DYN_V8_V8, MOV_DYN_V16_V16, LDA_STR_ID32, diff --git a/ecmascript/interpreter/interpreter_assembly.cpp b/ecmascript/interpreter/interpreter_assembly.cpp index 0c1411607409f53371f7b9c0cc403992b9ebadc8..b378090c56a5ca308aa58b2fdf2f852a327dd018 100644 --- a/ecmascript/interpreter/interpreter_assembly.cpp +++ b/ecmascript/interpreter/interpreter_assembly.cpp @@ -745,7 +745,7 @@ void InterpreterAssembly::HandleToNumberPrefV8( LOG_INST() << "intrinsics::tonumber" << " v" << v0; JSTaggedValue value = GET_VREG_VALUE(v0); - if (value.IsNumber() || value.IsBigInt()) { + if (value.IsNumber()) { // fast path SET_ACC(value); } else { @@ -3336,6 +3336,21 @@ void InterpreterAssembly::HandleLdBigIntPrefId32( DISPATCH(BytecodeInstruction::Format::PREF_ID32); } +void InterpreterAssembly::HandleToNumericPrefV8( + JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo, + JSTaggedValue acc, int32_t hotnessCounter) +{ + uint16_t v0 = READ_INST_8_1(); + + LOG_INST() << "intrinsics::tonumeric" + << " v" << v0; + JSTaggedValue value = GET_VREG_VALUE(v0); + JSTaggedValue res = SlowRuntimeStub::ToNumeric(thread, value); + INTERPRETER_RETURN_IF_ABRUPT(res); + SET_ACC(res); + DISPATCH(BytecodeInstruction::Format::PREF_V8); +} + void InterpreterAssembly::HandleSuperCallPrefImm16V8( JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo, JSTaggedValue acc, int32_t hotnessCounter) diff --git a/ecmascript/interpreter/interpreter_assembly.h b/ecmascript/interpreter/interpreter_assembly.h index 12c8a51636393d75f0fc3114ceca416917b2e5b3..5a8a01521004dd59df9404c83862862a1c6a033b 100644 --- a/ecmascript/interpreter/interpreter_assembly.h +++ b/ecmascript/interpreter/interpreter_assembly.h @@ -168,7 +168,6 @@ static std::array asmDispat InterpreterAssembly::HandleOverflow, InterpreterAssembly::HandleOverflow, InterpreterAssembly::HandleOverflow, - InterpreterAssembly::HandleOverflow, }; } // namespace panda::ecmascript #endif // ECMASCRIPT_INTERPRETER_INTERPRETER_ASSEMBLY_64BIT_H diff --git a/ecmascript/interpreter/slow_runtime_stub.cpp b/ecmascript/interpreter/slow_runtime_stub.cpp index 5caca98ad659e19f9955bd1444f3298e8b681369..85770194454e804a9c3489d4f99cbe45d9c3961b 100644 --- a/ecmascript/interpreter/slow_runtime_stub.cpp +++ b/ecmascript/interpreter/slow_runtime_stub.cpp @@ -126,7 +126,17 @@ JSTaggedValue SlowRuntimeStub::ToNumber(JSThread *thread, JSTaggedValue value) JSHandle number(thread, value); // may return exception - return JSTaggedValue::ToNumeric(thread, number).GetTaggedValue(); + return JSTaggedValue::ToNumber(thread, number); +} + +JSTaggedValue SlowRuntimeStub::ToNumeric(JSThread *thread, JSTaggedValue value) +{ + INTERPRETER_TRACE(thread, Tonumeric); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + JSHandle numeric(thread, value); + // may return exception + return JSTaggedValue::ToNumeric(thread, numeric).GetTaggedValue(); } JSTaggedValue SlowRuntimeStub::NotDyn(JSThread *thread, JSTaggedValue value) diff --git a/ecmascript/interpreter/slow_runtime_stub.h b/ecmascript/interpreter/slow_runtime_stub.h index 1b7380c8ae0fd3eb063eeed6b574eb0a1e456a8d..db167c1c9d25877312cfd87da6b8be72c079b2e9 100644 --- a/ecmascript/interpreter/slow_runtime_stub.h +++ b/ecmascript/interpreter/slow_runtime_stub.h @@ -31,6 +31,7 @@ public: static JSTaggedValue NegDyn(JSThread *thread, JSTaggedValue value); static JSTaggedValue AsyncFunctionEnter(JSThread *thread); static JSTaggedValue ToNumber(JSThread *thread, JSTaggedValue value); + static JSTaggedValue ToNumeric(JSThread *thread, JSTaggedValue value); static JSTaggedValue NotDyn(JSThread *thread, JSTaggedValue value); static JSTaggedValue IncDyn(JSThread *thread, JSTaggedValue value); static JSTaggedValue DecDyn(JSThread *thread, JSTaggedValue value); diff --git a/ecmascript/interpreter/templates/debugger_instruction_dispatch.inl b/ecmascript/interpreter/templates/debugger_instruction_dispatch.inl index 146ad8f0287863b3cbfe28bf3888cb00998f2363..34352f026fb1f4b6aed2555d310ba06601a644c8 100644 --- a/ecmascript/interpreter/templates/debugger_instruction_dispatch.inl +++ b/ecmascript/interpreter/templates/debugger_instruction_dispatch.inl @@ -149,6 +149,7 @@ &&DEBUG_HANDLE_LDFUNCTION_PREF, &&DEBUG_HANDLE_NEWLEXENVWITHNAMEDYN_PREF_IMM16_IMM16, &&DEBUG_HANDLE_LDBIGINT_PREF_ID32, + &&DEBUG_HANDLE_TONUMERIC_PREF_V8, &&DEBUG_HANDLE_MOV_DYN_V8_V8, &&DEBUG_HANDLE_MOV_DYN_V16_V16, &&DEBUG_HANDLE_LDA_STR_ID32, @@ -268,4 +269,3 @@ &&DEBUG_HANDLE_OVERFLOW, &&DEBUG_HANDLE_OVERFLOW, &&DEBUG_HANDLE_OVERFLOW, - &&DEBUG_HANDLE_OVERFLOW, diff --git a/ecmascript/interpreter/templates/debugger_instruction_handler.inl b/ecmascript/interpreter/templates/debugger_instruction_handler.inl index 08c25388542fe3c1ab7bbdbc6ef6aee72fd3e037..85e80ba114b035961e7a11d057b4ccffc0a9fada 100644 --- a/ecmascript/interpreter/templates/debugger_instruction_handler.inl +++ b/ecmascript/interpreter/templates/debugger_instruction_handler.inl @@ -693,6 +693,11 @@ NOTIFY_DEBUGGER_EVENT(); REAL_GOTO_DISPATCH_OPCODE(EcmaOpcode::LDBIGINT_PREF_ID32); } + HANDLE_OPCODE(DEBUG_HANDLE_TONUMERIC_PREF_V8) + { + NOTIFY_DEBUGGER_EVENT(); + REAL_GOTO_DISPATCH_OPCODE(EcmaOpcode::TONUMERIC_PREF_V8); + } HANDLE_OPCODE(DEBUG_HANDLE_MOV_DYN_V8_V8) { NOTIFY_DEBUGGER_EVENT(); diff --git a/ecmascript/interpreter/templates/instruction_dispatch.inl b/ecmascript/interpreter/templates/instruction_dispatch.inl index a7de27ff08f163bd5a2f58a9f08779aefce9ba86..17b73cc8e1906f46350b69335a42c4f369c656d2 100644 --- a/ecmascript/interpreter/templates/instruction_dispatch.inl +++ b/ecmascript/interpreter/templates/instruction_dispatch.inl @@ -149,6 +149,7 @@ &&HANDLE_LDFUNCTION_PREF, &&HANDLE_NEWLEXENVWITHNAMEDYN_PREF_IMM16_IMM16, &&HANDLE_LDBIGINT_PREF_ID32, + &&HANDLE_TONUMERIC_PREF_V8, &&HANDLE_MOV_DYN_V8_V8, &&HANDLE_MOV_DYN_V16_V16, &&HANDLE_LDA_STR_ID32, @@ -268,4 +269,3 @@ &&HANDLE_OVERFLOW, &&HANDLE_OVERFLOW, &&HANDLE_OVERFLOW, - &&HANDLE_OVERFLOW, diff --git a/ecmascript/runtime_call_id.h b/ecmascript/runtime_call_id.h index bff01d68627068f651dae0fa4d79a5f79043154d..d8b454500417deb5f556aa73aedec77e167f0933 100644 --- a/ecmascript/runtime_call_id.h +++ b/ecmascript/runtime_call_id.h @@ -31,7 +31,6 @@ namespace panda::ecmascript { V(Ldboolean) \ V(Ldnumber) \ V(Ldstring) \ - V(Ldbigint) \ V(Ldnull) \ V(Ldsymbol) \ V(Ldfunction) \ @@ -228,6 +227,7 @@ namespace panda::ecmascript { V(SetPropertyByName) \ V(GreaterEqDynWithIC) \ V(LdBigInt) \ + V(Tonumeric) \ V(DefineGeneratorFuncWithMethodId) \ V(GetSuperConstructor) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) diff --git a/ecmascript/stubs/runtime_stubs-inl.h b/ecmascript/stubs/runtime_stubs-inl.h index 2cf45b158e6b9b5c6219e6f6afeb3f50c3ebc43d..b2a82194413ecee139dbdb51787fb52186a689ee 100644 --- a/ecmascript/stubs/runtime_stubs-inl.h +++ b/ecmascript/stubs/runtime_stubs-inl.h @@ -993,6 +993,11 @@ JSTaggedValue RuntimeStubs::RuntimeStGlobalVar(JSThread *thread, const JSHandle< } JSTaggedValue RuntimeStubs::RuntimeToNumber(JSThread *thread, const JSHandle &value) +{ + return JSTaggedValue::ToNumber(thread, value); +} + +JSTaggedValue RuntimeStubs::RuntimeToNumeric(JSThread *thread, const JSHandle &value) { return JSTaggedValue::ToNumeric(thread, value).GetTaggedValue(); } diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index 418c095c9dc4dc7f58957f02eb9089a622ab27b0..a2468a904421a0d83952e7f7c96f4b3bb19f03d2 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -1527,6 +1527,13 @@ DEF_RUNTIME_STUBS(LdBigInt) return RuntimeLdBigInt(thread, numberBigInt).GetRawData(); } +DEF_RUNTIME_STUBS(ToNumeric) +{ + RUNTIME_STUBS_HEADER(ToNumeric); + JSHandle value = GetHArg(argv, argc, 0); // 0: means the zeroth parameter + return RuntimeToNumeric(thread, value).GetRawData(); +} + DEF_RUNTIME_STUBS(NewLexicalEnvWithNameDyn) { RUNTIME_STUBS_HEADER(NewLexicalEnvWithNameDyn); diff --git a/ecmascript/stubs/runtime_stubs.h b/ecmascript/stubs/runtime_stubs.h index 10fb250d68ec1cfd1679e755909997290537efaf..914396b1b89584973a05e8567124323e72e26b31 100644 --- a/ecmascript/stubs/runtime_stubs.h +++ b/ecmascript/stubs/runtime_stubs.h @@ -212,6 +212,7 @@ using JSFunctionEntryType = uint64_t (*)(uintptr_t glue, uintptr_t prevFp, uint3 V(DefineGetterSetterByValue) \ V(SuperCall) \ V(LdBigInt) \ + V(ToNumeric) \ V(NewLexicalEnvWithNameDyn) \ V(GetAotUnmapedArgs) \ V(CopyAotRestArgs) \ @@ -390,6 +391,7 @@ private: static inline JSTaggedValue RuntimeStGlobalVar(JSThread *thread, const JSHandle &prop, const JSHandle &value); static inline JSTaggedValue RuntimeToNumber(JSThread *thread, const JSHandle &value); + static inline JSTaggedValue RuntimeToNumeric(JSThread *thread, const JSHandle &value); static inline JSTaggedValue RuntimeEqDyn(JSThread *thread, const JSHandle &left, const JSHandle &right); static inline JSTaggedValue RuntimeNotEqDyn(JSThread *thread, const JSHandle &left, diff --git a/test/aottest/BUILD.gn b/test/aottest/BUILD.gn index 69bdc94f007086d7560d99c47b62639edd1b73cd..616b53ddfd74420540c8744d17be8f92722b984f 100644 --- a/test/aottest/BUILD.gn +++ b/test/aottest/BUILD.gn @@ -67,6 +67,7 @@ group("ark_aot_test") { "sub:subAotAction", "throw:throwAotAction", "tonumber:tonumberAotAction", + "tonumeric:tonumericAotAction", "trystglobalbynameprefid32:trystglobalbynameprefid32AotAction", "typeof:typeofAotAction", "xor:xorAotAction", diff --git a/test/aottest/tonumeric/BUILD.gn b/test/aottest/tonumeric/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..a98ecb80bd2e8c668345778cf3d809fc3bbb0dcf --- /dev/null +++ b/test/aottest/tonumeric/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//ark/js_runtime/test/test_helper.gni") + +host_aot_test_action("tonumeric") { + deps = [] +} diff --git a/test/aottest/tonumeric/expect_output.txt b/test/aottest/tonumeric/expect_output.txt new file mode 100644 index 0000000000000000000000000000000000000000..468eb70cb85ccaebd7c339a28cc304f45682a62a --- /dev/null +++ b/test/aottest/tonumeric/expect_output.txt @@ -0,0 +1,16 @@ +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +6 +8.7 +NaN diff --git a/test/aottest/tonumeric/tonumeric.ts b/test/aottest/tonumeric/tonumeric.ts new file mode 100644 index 0000000000000000000000000000000000000000..27647267a77aac2d42e50c07855a1dd634dac439 --- /dev/null +++ b/test/aottest/tonumeric/tonumeric.ts @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare function print(str:any):string; +var val1:number = 5; +val1++; +print(val1); +var val2:number = 7.7; +val2++; +print(val2); +var val3:number = NaN; +val3++; +print(val3); \ No newline at end of file