From fd204178a0cd48699633ec4da0664af7f9c7f678 Mon Sep 17 00:00:00 2001 From: duomingliang Date: Tue, 13 Aug 2024 14:43:15 +0800 Subject: [PATCH] optimize double2ecmastring Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IAJODL Description: optimize double2ecmastring, not use std::string Change-Id: Ifb0ba983f6327e093ca1b4940361f347fd2f9636 Signed-off-by: duomingliang --- ecmascript/base/number_helper.cpp | 65 ++++++--- ecmascript/base/tests/number_helper_test.cpp | 134 ++++++++++++++++++- ecmascript/global_env_constants.h | 2 + 3 files changed, 181 insertions(+), 20 deletions(-) diff --git a/ecmascript/base/number_helper.cpp b/ecmascript/base/number_helper.cpp index f2ba0d688e..9900c3dfd0 100644 --- a/ecmascript/base/number_helper.cpp +++ b/ecmascript/base/number_helper.cpp @@ -709,44 +709,71 @@ JSHandle NumberHelper::DoubleToEcmaString(const JSThread *thread, do return factory->NewFromASCII(IntToString(static_cast(d))); } - std::string result; + if (std::isinf(d)) { + return d < 0 ? JSHandle::Cast(thread->GlobalConstants()->GetHandledMinusInfinityCapitalString()) + : JSHandle::Cast(thread->GlobalConstants()->GetHandledInfinityCapitalString()); + } + + char buffer[JS_DTOA_BUF_SIZE] = {0}; + bool isNeg = false; + if (d < 0) { - result += "-"; + isNeg = true; d = -d; } - - if (std::isinf(d)) { - result += "Infinity"; - return factory->NewFromASCII(result.c_str()); - } - ASSERT(d > 0); - char buffer[JS_DTOA_BUF_SIZE] = {0}; + constexpr int startIdx = 8; + char *result = buffer + startIdx; int n; // decimal point int k; // length - DtoaHelper::Dtoa(d, buffer, &n, &k); //Fast Double To Ascii. - std::string base = buffer; + DtoaHelper::Dtoa(d, result, &n, &k); //Fast Double To Ascii. if (n > 0 && n <= MAX_DIGITS) { if (k <= n) { // 6. If k ≤ n ≤ 21 - base += std::string(n - k, '0'); + for (int i = k; i < n; ++i) { + result[i] = '0'; + } } else { // 7. If 0 < n ≤ 21 - base.insert(n, 1, '.'); + --result; + for (int i = 0; i < n; ++i) { + result[i] = result[i + 1]; + } + result[n] = '.'; } } else if (MIN_DIGITS < n && n <= 0) { // 8. If −6 < n ≤ 0 - base = std::string("0.") + std::string(-n, '0') + base; + constexpr int prefixLen = 2; + result -= (-n + prefixLen); + result[0] = '0'; + result[1] = '.'; + for (int i = prefixLen; i < -n + prefixLen; ++i) { + result[i] = '0'; + } } else { // 9. & 10. Otherwise - base.erase(1, k - 1); + int pos = k; if (k != 1) { - base += std::string(".") + std::string(buffer + 1); + --result; + result[0] = result[1]; + result[1] = '.'; + ++pos; + } + result[pos++] = 'e'; + if (n >= 1) { + result[pos++] = '+'; + } + auto expo = std::to_string(n - 1); + auto p = expo.c_str(); + for (size_t i = 0; i < expo.length(); ++i) { + result[pos++] = p[i]; } - base += "e" + (n >= 1 ? std::string("+") : "") + std::to_string(n - 1); } - result += base; - return factory->NewFromASCIISkippingStringTable(result.c_str()); + if (isNeg) { + --result; + result[0] = '-'; + } + return factory->NewFromASCIISkippingStringTable(result); } // 7.1.12.1 ToString Applied to the Number Type diff --git a/ecmascript/base/tests/number_helper_test.cpp b/ecmascript/base/tests/number_helper_test.cpp index f240b856bb..e772cd3374 100644 --- a/ecmascript/base/tests/number_helper_test.cpp +++ b/ecmascript/base/tests/number_helper_test.cpp @@ -178,6 +178,138 @@ HWTEST_F_L0(NumberHelperTest, DoubleToEcmaString) double d6 = 340000000000000000; JSHandle resultJSHandle6 = NumberHelper::DoubleToEcmaString(thread, d6); EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle6, resultStr6), 0); + + JSHandle resultStr7 = + factory->NewFromASCII("12.012345678901234"); + double d7 = 12.01234567890123456789; + JSHandle resultJSHandle7 = NumberHelper::DoubleToEcmaString(thread, d7); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle7, resultStr7), 0); + + JSHandle resultStr8 = + factory->NewFromASCII("0.0000012345678901234567"); + double digit8 = 0.000001234567890123456789; + JSHandle resultJSHandle8 = NumberHelper::DoubleToEcmaString(thread, digit8); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle8, resultStr8), 0); + + JSHandle resultStr9 = + factory->NewFromASCII("Infinity"); + double d9 = std::numeric_limits::infinity(); + JSHandle resultJSHandle9 = NumberHelper::DoubleToEcmaString(thread, d9); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle9, resultStr9), 0); + + JSHandle resultStr10 = + factory->NewFromASCII("-Infinity"); + double d10 = -std::numeric_limits::infinity(); + JSHandle resultJSHandle10 = NumberHelper::DoubleToEcmaString(thread, d10); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle10, resultStr10), 0); + + JSHandle resultStr11 = + factory->NewFromASCII("1.7976931348623157e+308"); + double d11 = 1.797693134862315807937e+308; + JSHandle resultJSHandle11 = NumberHelper::DoubleToEcmaString(thread, d11); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle11, resultStr11), 0); + + JSHandle resultStr12 = + factory->NewFromASCII("-1.7976931348623157e+308"); + double d12 = -1.797693134862315807937e+308; + JSHandle resultJSHandle12 = NumberHelper::DoubleToEcmaString(thread, d12); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle12, resultStr12), 0); + + JSHandle resultStr13 = + factory->NewFromASCII("2.22507e-308"); + double d13 = 2.22507e-308; + JSHandle resultJSHandle13 = NumberHelper::DoubleToEcmaString(thread, d13); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle13, resultStr13), 0); + + JSHandle resultStr14 = + factory->NewFromASCII("1.2345678901234568e-7"); + double digit14 = 0.0000001234567890123456789; + JSHandle resultJSHandle14 = NumberHelper::DoubleToEcmaString(thread, digit14); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle14, resultStr14), 0); + + JSHandle resultStr15 = + factory->NewFromASCII("3.4e+21"); + double digit15 = 3.4e21; + JSHandle resultJSHandle15 = NumberHelper::DoubleToEcmaString(thread, digit15); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle15, resultStr15), 0); + + JSHandle resultStr16 = + factory->NewFromASCII("120000000000000000000"); + double digit16 = 1.2e20; + JSHandle resultJSHandle16 = NumberHelper::DoubleToEcmaString(thread, digit16); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle16, resultStr16), 0); + + JSHandle resultStr17 = + factory->NewFromASCII("1.2"); + double digit17 = 1.2e0; + JSHandle resultJSHandle17 = NumberHelper::DoubleToEcmaString(thread, digit17); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle17, resultStr17), 0); + + JSHandle resultStr18 = + factory->NewFromASCII("0.0000012"); + double digit18 = 1.2e-6; + JSHandle resultJSHandle18 = NumberHelper::DoubleToEcmaString(thread, digit18); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle18, resultStr18), 0); + + JSHandle resultStr19 = + factory->NewFromASCII("1.2e-7"); + double digit19 = 1.2e-7; + JSHandle resultJSHandle19 = NumberHelper::DoubleToEcmaString(thread, digit19); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle19, resultStr19), 0); + + JSHandle resultStr20 = + factory->NewFromASCII("NaN"); + double digit20 = std::numeric_limits::quiet_NaN(); + JSHandle resultJSHandle20 = NumberHelper::DoubleToEcmaString(thread, digit20); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle20, resultStr20), 0); + + JSHandle resultStr21 = + factory->NewFromASCII("-12.012345678901234"); + double d21 = -12.01234567890123456789; + JSHandle resultJSHandle21 = NumberHelper::DoubleToEcmaString(thread, d21); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle21, resultStr21), 0); + + JSHandle resultStr22 = + factory->NewFromASCII("-0.0000012345678901234567"); + double digit22 = -0.000001234567890123456789; + JSHandle resultJSHandle22 = NumberHelper::DoubleToEcmaString(thread, digit22); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle22, resultStr22), 0); + + JSHandle resultStr23 = + factory->NewFromASCII("-1.2345678901234568e-7"); + double digit23 = -0.0000001234567890123456789; + JSHandle resultJSHandle23 = NumberHelper::DoubleToEcmaString(thread, digit23); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle23, resultStr23), 0); + + JSHandle resultStr24 = + factory->NewFromASCII("-3.4e+21"); + double digit24 = -3.4e21; + JSHandle resultJSHandle24 = NumberHelper::DoubleToEcmaString(thread, digit24); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle24, resultStr24), 0); + + JSHandle resultStr25 = + factory->NewFromASCII("-120000000000000000000"); + double digit25 = -1.2e20; + JSHandle resultJSHandle25 = NumberHelper::DoubleToEcmaString(thread, digit25); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle25, resultStr25), 0); + + JSHandle resultStr26 = + factory->NewFromASCII("-1.2"); + double digit26 = -1.2e0; + JSHandle resultJSHandle26 = NumberHelper::DoubleToEcmaString(thread, digit26); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle26, resultStr26), 0); + + JSHandle resultStr27 = + factory->NewFromASCII("-0.0000012"); + double digit27 = -1.2e-6; + JSHandle resultJSHandle27 = NumberHelper::DoubleToEcmaString(thread, digit27); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle27, resultStr27), 0); + + JSHandle resultStr28 = + factory->NewFromASCII("-1.2e-7"); + double digit28 = -1.2e-7; + JSHandle resultJSHandle28 = NumberHelper::DoubleToEcmaString(thread, digit28); + EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultJSHandle28, resultStr28), 0); } /** @@ -721,4 +853,4 @@ HWTEST_F_L0(NumberHelperTest, DoubleToASCII_002) EXPECT_EQ(EcmaStringAccessor::Compare(instance, handleEcmaStr7, resultStr), 0); } -} // namespace panda::ecmascript \ No newline at end of file +} // namespace panda::ecmascript diff --git a/ecmascript/global_env_constants.h b/ecmascript/global_env_constants.h index e302bb4fc5..a07c4f8db7 100644 --- a/ecmascript/global_env_constants.h +++ b/ecmascript/global_env_constants.h @@ -466,6 +466,8 @@ class ObjectFactory; V(IntegerString, INTEGER_STRING_INDEX, "integer") \ V(NanString, NAN_STRING_INDEX, "nan") \ V(InfinityString, INFINITY_STRING_INDEX, "infinity") \ + V(InfinityCapitalString, INFINITY_CAP_STRING_INDEX, "Infinity") \ + V(MinusInfinityCapitalString, MINUS_INFINITY_CAP_STRING_INDEX, "-Infinity") \ V(FractionString, FRACTION_STRING_INDEX, "fraction") \ V(DecimalString, DECIMAL_STRING_INDEX, "decimal") \ V(GroupString, GROUP_STRING_INDEX, "group") \