diff --git a/ecmascript/compiler/operations_stub_builder.cpp b/ecmascript/compiler/operations_stub_builder.cpp index 28f17fd46d0251ffa24d5cd72865170a60a9d26b..8c9802c1d4cd42b163836d2b2331733d528c2edf 100644 --- a/ecmascript/compiler/operations_stub_builder.cpp +++ b/ecmascript/compiler/operations_stub_builder.cpp @@ -1263,13 +1263,24 @@ GateRef OperationsStubBuilder::Inc(GateRef glue, GateRef value, ProfileOperation Bind(&valueNotInt); { Label valueIsDouble(env); + Label valueIsNanOrInf(env); + Label valueIsNotNanOrInf(env); BRANCH(TaggedIsDouble(value), &valueIsDouble, &slowPath); Bind(&valueIsDouble); { - callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType())); GateRef valueDouble = GetDoubleOfTDouble(value); - result = DoubleToTaggedDoublePtr(DoubleAdd(valueDouble, Double(1.0))); - Jump(&exit); + callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType())); + BRANCH_UNLIKELY(DoubleIsNanOrInf(valueDouble), &valueIsNanOrInf, &valueIsNotNanOrInf); + Bind(&valueIsNanOrInf); + { + result = value; + Jump(&exit); + } + Bind(&valueIsNotNanOrInf); + { + result = DoubleToTaggedDoublePtr(DoubleAdd(valueDouble, Double(1.0))); + Jump(&exit); + } } } Bind(&slowPath); @@ -1311,13 +1322,24 @@ GateRef OperationsStubBuilder::Dec(GateRef glue, GateRef value, ProfileOperation Bind(&valueNotInt); { Label valueIsDouble(env); + Label valueIsNanOrInf(env); + Label valueIsNotNanOrInf(env); BRANCH(TaggedIsDouble(value), &valueIsDouble, &slowPath); Bind(&valueIsDouble); { - callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType())); GateRef valueDouble = GetDoubleOfTDouble(value); - result = DoubleToTaggedDoublePtr(DoubleSub(valueDouble, Double(1.0))); - Jump(&exit); + callback.ProfileOpType(TaggedInt(PGOSampleType::DoubleType())); + BRANCH_UNLIKELY(DoubleIsNanOrInf(valueDouble), &valueIsNanOrInf, &valueIsNotNanOrInf); + Bind(&valueIsNanOrInf); + { + result = value; + Jump(&exit); + } + Bind(&valueIsNotNanOrInf); + { + result = DoubleToTaggedDoublePtr(DoubleSub(valueDouble, Double(1.0))); + Jump(&exit); + } } } Bind(&slowPath); diff --git a/ecmascript/interpreter/interpreter-inl.cpp b/ecmascript/interpreter/interpreter-inl.cpp index 88c696c84a1ec3936d23daf7cf7380d048ad4803..6e574b1121b8357fcef05807d214b87794c961b5 100644 --- a/ecmascript/interpreter/interpreter-inl.cpp +++ b/ecmascript/interpreter/interpreter-inl.cpp @@ -4868,7 +4868,12 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t SET_ACC(JSTaggedValue(a0 + 1)); } } else if (value.IsDouble()) { - SET_ACC(JSTaggedValue(value.GetDouble() + 1.0)); + double doubleVal = value.GetDouble(); + if (UNLIKELY(std::isnan(doubleVal) || !std::isfinite(doubleVal))) { + SET_ACC(value); + } else { + SET_ACC(JSTaggedValue(doubleVal + 1.0)); + } } else { // slow path SAVE_PC(); @@ -4895,7 +4900,12 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t SET_ACC(JSTaggedValue(a0 + 1)); } } else if (value.IsDouble()) { - SET_ACC(JSTaggedValue(value.GetDouble() + 1.0)); + double doubleVal = value.GetDouble(); + if (UNLIKELY(std::isnan(doubleVal) || !std::isfinite(doubleVal))) { + SET_ACC(value); + } else { + SET_ACC(JSTaggedValue(doubleVal + 1.0)); + } } else { // slow path SAVE_PC(); @@ -4919,7 +4929,12 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t SET_ACC(JSTaggedValue(a0 - 1)); } } else if (value.IsDouble()) { - SET_ACC(JSTaggedValue(value.GetDouble() - 1.0)); + double doubleVal = value.GetDouble(); + if (UNLIKELY(std::isnan(doubleVal) || !std::isfinite(doubleVal))) { + SET_ACC(value); + } else { + SET_ACC(JSTaggedValue(doubleVal - 1.0)); + } } else { // slow path SAVE_PC(); @@ -4945,7 +4960,12 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t SET_ACC(JSTaggedValue(a0 - 1)); } } else if (value.IsDouble()) { - SET_ACC(JSTaggedValue(value.GetDouble() - 1.0)); + double doubleVal = value.GetDouble(); + if (UNLIKELY(std::isnan(doubleVal) || !std::isfinite(doubleVal))) { + SET_ACC(value); + } else { + SET_ACC(JSTaggedValue(doubleVal - 1.0)); + } } else { // slow path SAVE_PC(); diff --git a/ecmascript/js_tagged_number.h b/ecmascript/js_tagged_number.h index fd67f78ce64b6765c01425fa8293f1379194ef70..6df81f25fca33ebc1cbb5a6e47077957f2909fe2 100644 --- a/ecmascript/js_tagged_number.h +++ b/ecmascript/js_tagged_number.h @@ -130,7 +130,12 @@ public: } return JSTaggedNumber(value + 1); } - return JSTaggedNumber(GetDouble() + 1.0); + ASSERT(IsDouble()); + double doubleVal = GetDouble(); + if (UNLIKELY(std::isnan(doubleVal) || !std::isfinite(doubleVal))) { + return JSTaggedNumber(doubleVal); + } + return JSTaggedNumber(doubleVal + 1.0); } JSTaggedNumber operator--() const @@ -142,7 +147,12 @@ public: } return JSTaggedNumber(value - 1); } - return JSTaggedNumber(GetDouble() - 1.0); + ASSERT(IsDouble()); + double doubleVal = GetDouble(); + if (UNLIKELY(std::isnan(doubleVal) || !std::isfinite(doubleVal))) { + return JSTaggedNumber(doubleVal); + } + return JSTaggedNumber(doubleVal - 1.0); } inline bool operator!=(const JSTaggedNumber &number) const diff --git a/test/moduletest/typearray/typearray.js b/test/moduletest/typearray/typearray.js index ffd142804ee7deaecce2260e41880cd290b4e5e5..d7de157276f0e1755485b3242ce2b2b95c91924c 100644 --- a/test/moduletest/typearray/typearray.js +++ b/test/moduletest/typearray/typearray.js @@ -1676,4 +1676,20 @@ for (let typedArrEle of iterForTypedArrEntry) { assert_equal(typedArrEleAssertRes,typedArrEleAssertEqual); assert_equal(typedArrEleAssertLengthRes,typedArrEleAssertLengthEqual); +{ + var v0 = new ArrayBuffer(16); + var v1 = new Int32Array(v0); + v1[1] = 0xfff7ffff; + let v2 = new Float64Array(v0); + v2[0]++; + v2[0]--; + assert_equal(Number.isNaN(v2[0]), true); + let v3 = Infinity; + v3++; + let v4 = -Infinity; + v4--; + assert_equal(v3, Infinity); + assert_equal(v4, -Infinity); +} + test_end(); \ No newline at end of file