From b486959846212c9a50616d9a8e02f7c5f76a8348 Mon Sep 17 00:00:00 2001 From: zhaozhibo Date: Tue, 31 May 2022 16:27:31 +0800 Subject: [PATCH 01/35] add unittest case for js_date_time_format Signed-off-by: zhaozhibo --- ecmascript/tests/BUILD.gn | 1 + ecmascript/tests/js_collator_test.cpp | 2 - ecmascript/tests/js_date_time_format_test.cpp | 686 ++++++++++++++++++ 3 files changed, 687 insertions(+), 2 deletions(-) create mode 100644 ecmascript/tests/js_date_time_format_test.cpp diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index 415a0fa85f..8c9ac4714b 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -58,6 +58,7 @@ host_unittest_action("EcmaVmTest") { "js_collator_test.cpp", "js_dataview_test.cpp", "js_date_test.cpp", + "js_date_time_format_test.cpp", "js_forin_iterator_test.cpp", "js_function_test.cpp", "js_handle_test.cpp", diff --git a/ecmascript/tests/js_collator_test.cpp b/ecmascript/tests/js_collator_test.cpp index 15cfe7cfbb..5c04690020 100644 --- a/ecmascript/tests/js_collator_test.cpp +++ b/ecmascript/tests/js_collator_test.cpp @@ -14,8 +14,6 @@ */ #include "ecmascript/js_collator.h" -#include "ecmascript/js_number_format.h" -#include "ecmascript/js_plural_rules.h" #include "ecmascript/global_env.h" #include "ecmascript/tests/test_helper.h" diff --git a/ecmascript/tests/js_date_time_format_test.cpp b/ecmascript/tests/js_date_time_format_test.cpp new file mode 100644 index 0000000000..5354341e93 --- /dev/null +++ b/ecmascript/tests/js_date_time_format_test.cpp @@ -0,0 +1,686 @@ +/* + * 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. + */ + +#include "ecmascript/global_env.h" +#include "ecmascript/js_date.h" +#include "ecmascript/js_date_time_format.h" +#include "ecmascript/js_locale.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda; +using namespace panda::ecmascript; + +namespace panda::test { +class JSDateTimeFormatTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + JSRuntimeOptions options; +#if PANDA_TARGET_LINUX + // for consistency requirement, use ohos_icu4j/data as icu-data-path + options.SetIcuDataPath(ICU_PATH); +#endif + options.SetEnableForceGC(true); + instance = JSNApi::CreateEcmaVM(options); + instance->SetEnableForceGC(true); + ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM"; + thread = instance->GetJSThread(); + scope = new EcmaHandleScope(thread); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + + EcmaVM *instance {nullptr}; + EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; +}; + +void SetDateOptionsTest(JSThread *thread, JSHandle &optionsObj, + std::map dateOptions) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto globalConst = thread->GlobalConstants(); + // Date options keys. + JSHandle weekdayKey = globalConst->GetHandledWeekdayString(); + JSHandle yearKey = globalConst->GetHandledYearString(); + JSHandle monthKey = globalConst->GetHandledMonthString(); + JSHandle dayKey = globalConst->GetHandledDayString(); + // Date options values. + JSHandle weekdayValue(factory->NewFromASCII(dateOptions["weekday"].c_str())); + JSHandle yearValue(factory->NewFromASCII(dateOptions["year"].c_str())); + JSHandle monthValue(factory->NewFromASCII(dateOptions["month"].c_str())); + JSHandle dayValue(factory->NewFromASCII(dateOptions["day"].c_str())); + // Set date options. + JSObject::SetProperty(thread, optionsObj, weekdayKey, weekdayValue); + JSObject::SetProperty(thread, optionsObj, yearKey, yearValue); + JSObject::SetProperty(thread, optionsObj, monthKey, monthValue); + JSObject::SetProperty(thread, optionsObj, dayKey, dayValue); +} + +void SetTimeOptionsTest(JSThread *thread, JSHandle &optionsObj, + std::map timeOptionsMap) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto globalConst = thread->GlobalConstants(); + // Time options keys. + JSHandle dayPeriodKey = globalConst->GetHandledDayPeriodString(); + JSHandle hourKey = globalConst->GetHandledHourString(); + JSHandle minuteKey = globalConst->GetHandledMinuteString(); + JSHandle secondKey = globalConst->GetHandledSecondString(); + JSHandle fractionalSecondDigitsKey = globalConst->GetHandledFractionalSecondDigitsString(); + // Time options values. + JSHandle dayPeriodValue(factory->NewFromASCII(timeOptionsMap["dayPeriod"].c_str())); + JSHandle hourValue(factory->NewFromASCII(timeOptionsMap["hour"].c_str())); + JSHandle minuteValue(factory->NewFromASCII(timeOptionsMap["minute"].c_str())); + JSHandle secondValue(factory->NewFromASCII(timeOptionsMap["second"].c_str())); + JSHandle fractionalSecondDigitsValue( + factory->NewFromASCII(timeOptionsMap["fractionalSecond"].c_str())); + // Set time options. + JSObject::SetProperty(thread, optionsObj, dayPeriodKey, dayPeriodValue); + JSObject::SetProperty(thread, optionsObj, hourKey, hourValue); + JSObject::SetProperty(thread, optionsObj, minuteKey, minuteValue); + JSObject::SetProperty(thread, optionsObj, secondKey, secondValue); + JSObject::SetProperty(thread, optionsObj, fractionalSecondDigitsKey, fractionalSecondDigitsValue); +} + +/** + * @tc.name: GetIcuLocale & SetIcuLocale + * @tc.desc: Set and obtain localization labels compatible with ICU Libraries. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JSDateTimeFormatTest, Set_Get_IcuLocale) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto env = vm->GetGlobalEnv(); + JSHandle ctor = env->GetDateTimeFormatFunction(); + JSHandle dtf = + JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(ctor), ctor)); + + icu::Locale locale1("ko", "Kore", "KR"); + JSDateTimeFormat::SetIcuLocale(thread, dtf, locale1, JSDateTimeFormat::FreeIcuLocale); + icu::Locale *resLocale1 = dtf->GetIcuLocale(); + EXPECT_STREQ(resLocale1->getBaseName(), "ko_Kore_KR"); + + icu::Locale locale2("zh", "Hans", "Cn"); + JSDateTimeFormat::SetIcuLocale(thread, dtf, locale2, JSDateTimeFormat::FreeIcuLocale); + icu::Locale *resLocale2 = dtf->GetIcuLocale(); + EXPECT_STREQ(resLocale2->getBaseName(), "zh_Hans_CN"); +} + +/** + * @tc.name: SetIcuSimpleDateFormat & GetIcuSimpleDateFormat + * @tc.desc: Set and obtain a simple time and date format compatible with ICU Libraries. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JSDateTimeFormatTest, Set_Get_IcuSimpleDateFormat) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto env = vm->GetGlobalEnv(); + JSHandle ctor = env->GetDateTimeFormatFunction(); + JSHandle dtf = + JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(ctor), ctor)); + UErrorCode status = UErrorCode::U_ZERO_ERROR; + icu::UnicodeString dateTime1("2022.05.25 11:09:34"); + icu::UnicodeString dateTime2("2022.May.25 11:09:34"); + icu::UnicodeString dateTime3("2022.May.25 AD 11:09:34 AM"); + + icu::UnicodeString pattern("yyyy.MM.dd HH:mm:ss"); + icu::SimpleDateFormat sdf(pattern, status); + JSDateTimeFormat::SetIcuSimpleDateFormat(thread, dtf, sdf, JSDateTimeFormat::FreeSimpleDateFormat); + icu::SimpleDateFormat *resSdf = dtf->GetIcuSimpleDateFormat(); + UDate timeStamp = resSdf->parse(dateTime1, status); + EXPECT_EQ(timeStamp, 1653448174000); + status = UErrorCode::U_ZERO_ERROR; + timeStamp = resSdf->parse(dateTime2, status); + EXPECT_EQ(timeStamp, 1653448174000); + status = UErrorCode::U_ZERO_ERROR; + timeStamp = resSdf->parse(dateTime3, status); + EXPECT_EQ(timeStamp, 0); + + status = UErrorCode::U_ZERO_ERROR; + icu::UnicodeString pattern2("yyyyy.MMMMM.dd GGG hh:mm::ss aaa"); + icu::SimpleDateFormat sdf2(pattern2, status); + JSDateTimeFormat::SetIcuSimpleDateFormat(thread, dtf, sdf2, JSDateTimeFormat::FreeSimpleDateFormat); + icu::SimpleDateFormat *resSdf2 = dtf->GetIcuSimpleDateFormat(); + timeStamp = resSdf2->parse(dateTime1, status); + EXPECT_EQ(timeStamp, 0); + status = UErrorCode::U_ZERO_ERROR; + timeStamp = resSdf2->parse(dateTime2, status); + EXPECT_EQ(timeStamp, 0); + status = UErrorCode::U_ZERO_ERROR; + timeStamp = resSdf2->parse(dateTime3, status); + EXPECT_EQ(timeStamp, 1653448174000); +} + +/** + * @tc.name: InitializeDateTimeFormat + * @tc.desc: Initialize the time and date format through localization label locales and options. + * Options can include year, month, day, hour, minute, second, time zone and weekday, etc. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JSDateTimeFormatTest, InitializeDateTimeFormat) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto env = vm->GetGlobalEnv(); + // Create locales. + JSHandle localeCtor = env->GetLocaleFunction(); + JSHandle locales = + JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(localeCtor), localeCtor)); + icu::Locale icuLocale("zh", "Hans", "Cn", "calendar=chinese"); + factory->NewJSIntlIcuData(locales, icuLocale, JSLocale::FreeIcuLocale); + // Create options. + JSHandle objFun = env->GetObjectFunction(); + JSHandle options = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); + options = JSDateTimeFormat::ToDateTimeOptions( + thread, JSHandle::Cast(options), RequiredOption::ANY, DefaultsOption::ALL); + // Initialize DateTimeFormat. + JSHandle dtfCtor = env->GetDateTimeFormatFunction(); + JSHandle dtf = + JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(dtfCtor), dtfCtor)); + dtf = JSDateTimeFormat::InitializeDateTimeFormat( + thread, dtf, JSHandle::Cast(locales), JSHandle::Cast(options)); + + JSHandle localeTagVal(thread, dtf->GetLocale()); + JSHandle localeEcmaStr = JSHandle::Cast(localeTagVal); + std::string localeStr = JSLocale::ConvertToStdString(localeEcmaStr); + EXPECT_STREQ(localeStr.c_str(), "zh-Hans-CN-u-ca-chinese"); +} + +/** + * @tc.name: ToDateTimeOptions + * @tc.desc: Empty or incomplete option objects are supplemented according to the required option and default option. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JSDateTimeFormatTest, ToDateTimeOptions_001) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto env = vm->GetGlobalEnv(); + auto globalConst = thread->GlobalConstants(); + + JSHandle objFun = env->GetObjectFunction(); + JSHandle yearKey = globalConst->GetHandledYearString(); + JSHandle monthKey = globalConst->GetHandledMonthString(); + JSHandle dayKey = globalConst->GetHandledDayString(); + JSHandle hourKey = globalConst->GetHandledHourString(); + JSHandle minuteKey = globalConst->GetHandledMinuteString(); + JSHandle secondKey = globalConst->GetHandledSecondString(); + + // When the option value is blank, it will be set according to the default option, + // including the year, month, day, hour, minute and second, and the values are all numeric. + JSHandle options = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); + options = JSDateTimeFormat::ToDateTimeOptions( + thread, JSHandle::Cast(options), RequiredOption::ANY, DefaultsOption::ALL); // test "ALL" + auto yearEcmaStr = JSHandle::Cast(JSObject::GetProperty(thread, options, yearKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(yearEcmaStr).c_str(), "numeric"); + auto monthEcmaStr = JSHandle::Cast(JSObject::GetProperty(thread, options, monthKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(monthEcmaStr).c_str(), "numeric"); + auto dayEcmaStr = JSHandle::Cast(JSObject::GetProperty(thread, options, dayKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(dayEcmaStr).c_str(), "numeric"); + auto hourEcmaStr = JSHandle::Cast(JSObject::GetProperty(thread, options, hourKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(hourEcmaStr).c_str(), "numeric"); + auto minuteEcmaStr = JSHandle::Cast(JSObject::GetProperty(thread, options, minuteKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(minuteEcmaStr).c_str(), "numeric"); + auto secondEcmaStr = JSHandle::Cast(JSObject::GetProperty(thread, options, secondKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(secondEcmaStr).c_str(), "numeric"); +} + +HWTEST_F_L0(JSDateTimeFormatTest, ToDateTimeOptions_002) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto env = vm->GetGlobalEnv(); + auto globalConst = thread->GlobalConstants(); + + JSHandle objFun = env->GetObjectFunction(); + JSHandle weekdayKey = globalConst->GetHandledWeekdayString(); + JSHandle yearKey = globalConst->GetHandledYearString(); + JSHandle monthKey = globalConst->GetHandledMonthString(); + JSHandle dayKey = globalConst->GetHandledDayString(); + JSHandle dayPeriodKey = globalConst->GetHandledDayPeriodString(); + JSHandle hourKey = globalConst->GetHandledHourString(); + JSHandle minuteKey = globalConst->GetHandledMinuteString(); + JSHandle secondKey = globalConst->GetHandledSecondString(); + JSHandle fracSecKey = globalConst->GetHandledFractionalSecondDigitsString(); + + // When the option value is not empty, it will be set according to the required options. + JSHandle options = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); + std::map dateOptionsMap { + { "weekday", "narrow" }, + { "year", "2-digit" }, + { "month", "2-digit" }, + { "day", "2-digit" } + }; + std::map timeOptionsMap { + { "dayPeriod", "narrow" }, + { "hour", "2-digit" }, + { "minute", "2-digit" }, + { "second", "2-digit" }, + { "fractionalSecond", "1" } + }; + SetDateOptionsTest(thread, options, dateOptionsMap); + SetTimeOptionsTest(thread, options, timeOptionsMap); + options = JSDateTimeFormat::ToDateTimeOptions( + thread, JSHandle::Cast(options), RequiredOption::ANY, DefaultsOption::ALL); // test "ANY" + auto weekdayStr = JSHandle::Cast(JSObject::GetProperty(thread, options, weekdayKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(weekdayStr).c_str(), "narrow"); + auto yearStr = JSHandle::Cast(JSObject::GetProperty(thread, options, yearKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(yearStr).c_str(), "2-digit"); + auto monthStr = JSHandle::Cast(JSObject::GetProperty(thread, options, monthKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(monthStr).c_str(), "2-digit"); + auto dayStr = JSHandle::Cast(JSObject::GetProperty(thread, options, dayKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(dayStr).c_str(), "2-digit"); + + auto dayPeriodStr = JSHandle::Cast(JSObject::GetProperty(thread, options, dayPeriodKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(dayPeriodStr).c_str(), "narrow"); + auto hourStr = JSHandle::Cast(JSObject::GetProperty(thread, options, hourKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(hourStr).c_str(), "2-digit"); + auto minuteStr = JSHandle::Cast(JSObject::GetProperty(thread, options, minuteKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(minuteStr).c_str(), "2-digit"); + auto secondStr = JSHandle::Cast(JSObject::GetProperty(thread, options, secondKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(secondStr).c_str(), "2-digit"); + auto fracSecStr = JSHandle::Cast(JSObject::GetProperty(thread, options, fracSecKey).GetValue()); + EXPECT_STREQ(JSLocale::ConvertToStdString(fracSecStr).c_str(), "1"); +} + +JSHandle CreateDateTimeFormatTest(JSThread *thread, icu::Locale icuLocale, JSHandle options) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto env = vm->GetGlobalEnv(); + + JSHandle localeCtor = env->GetLocaleFunction(); + JSHandle dtfCtor = env->GetDateTimeFormatFunction(); + JSHandle locales = + JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(localeCtor), localeCtor)); + JSHandle dtf = + JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(dtfCtor), dtfCtor)); + + JSHandle optionsVal = JSHandle::Cast(options); + factory->NewJSIntlIcuData(locales, icuLocale, JSLocale::FreeIcuLocale); + dtf = JSDateTimeFormat::InitializeDateTimeFormat(thread, dtf, JSHandle::Cast(locales), optionsVal); + return dtf; +} +/** + * @tc.name: FormatDateTime + * @tc.desc: Convert floating-point timestamp to fixed format time date through time date format. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_001) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto env = vm->GetGlobalEnv(); + auto globalConst = thread->GlobalConstants(); + + icu::Locale icuLocale("zh", "Hans", "Cn"); + JSHandle objFun = env->GetObjectFunction(); + JSHandle optionsEmtpy = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); + JSHandle hourCycleKey = globalConst->GetHandledHourCycleString(); + JSHandle hourCycleValue(factory->NewFromASCII("h12")); + JSObject::SetProperty(thread, optionsEmtpy, hourCycleKey, hourCycleValue); + JSHandle dtf = CreateDateTimeFormatTest(thread, icuLocale, optionsEmtpy); + + double timeStamp1 = 1653448174000; // test "2022-05-25 11:09:34.000" + double timeStamp2 = 1653921012999; // test "2022-05-30 22:30:12.999" + + // When the option is blank, the default format is "yyyy/MM/dd", the year, month and day are all numeric, + // because the default option in initialization is "DefaultsOption::DATE". + JSHandle dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp1); + EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr1).c_str(), "2022/5/25"); + JSHandle dateTimeEcamStr2 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp2); + EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr2).c_str(), "2022/5/30"); +} + +HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_002) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto env = vm->GetGlobalEnv(); + auto globalConst = thread->GlobalConstants(); + + icu::Locale icuLocale("zh", "Hans", "Cn"); + JSHandle objFun = env->GetObjectFunction(); + JSHandle optionsEmtpy = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); + JSHandle hourCycleKey = globalConst->GetHandledHourCycleString(); + JSHandle hourCycleValue(factory->NewFromASCII("h12")); + JSObject::SetProperty(thread, optionsEmtpy, hourCycleKey, hourCycleValue); + JSHandle options = JSDateTimeFormat::ToDateTimeOptions( + thread, JSHandle::Cast(optionsEmtpy), RequiredOption::ANY, DefaultsOption::ALL); + JSHandle dtf = CreateDateTimeFormatTest(thread, icuLocale, options); + + double timeStamp1 = 1653448174000; // test "2022-05-25 11:09:34.000" + double timeStamp2 = 1653921012999; // test "2022-05-30 22:30:12.999" + + // Format to include all options by "DefaultsOption::ALL". + JSHandle dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp1); + EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr1).c_str(), "2022/5/25 上午11:09:34"); + JSHandle dateTimeEcamStr2 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp2); + EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr2).c_str(), "2022/5/30 下午10:30:12"); +} + +HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_003) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto env = vm->GetGlobalEnv(); + auto globalConst = thread->GlobalConstants(); + + icu::Locale icuLocale("zh", "Hans", "Cn"); + JSHandle objFun = env->GetObjectFunction(); + JSHandle optionsEmtpy = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); + JSHandle hourCycleKey = globalConst->GetHandledHourCycleString(); + JSHandle hourCycleValue(factory->NewFromASCII("h12")); + JSObject::SetProperty(thread, optionsEmtpy, hourCycleKey, hourCycleValue); + + // Set custom date time format. + JSHandle options = optionsEmtpy; + std::map dateOptionsMap { + { "weekday", "long" }, + { "year", "2-digit" }, + { "month", "2-digit" }, + { "day", "2-digit" } + }; + std::map timeOptionsMap { + { "dayPeriod", "long" }, + { "hour", "2-digit" }, + { "minute", "2-digit" }, + { "second", "2-digit" }, + { "fractionalSecond", "3" } + }; + SetDateOptionsTest(thread, options, dateOptionsMap); + SetTimeOptionsTest(thread, options, timeOptionsMap); + options = JSDateTimeFormat::ToDateTimeOptions( + thread, JSHandle::Cast(options), RequiredOption::ANY, DefaultsOption::ALL); + JSHandle dtf = CreateDateTimeFormatTest(thread, icuLocale, options); + + double timeStamp1 = 1653448174000; // test "2022-05-25 11:09:34.000" + double timeStamp2 = 1653921012999; // test "2022-05-30 22:30:12.999" + + JSHandle dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp1); + EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr1).c_str(), "22年05月25日星期三 上午11:09:34.000"); + JSHandle dateTimeEcamStr2 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp2); + EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr2).c_str(), "22年05月30日星期一 晚上10:30:12.999"); +} + +HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTime_004) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto env = vm->GetGlobalEnv(); + auto globalConst = thread->GlobalConstants(); + + icu::Locale icuLocale("en", "Hans", "US"); + JSHandle objFun = env->GetObjectFunction(); + JSHandle optionsEmtpy = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); + JSHandle hourCycleKey = globalConst->GetHandledHourCycleString(); + JSHandle hourCycleValue(factory->NewFromASCII("h12")); + JSObject::SetProperty(thread, optionsEmtpy, hourCycleKey, hourCycleValue); + + // Set custom date time format. + JSHandle options = optionsEmtpy; + std::map dateOptionsMap { + { "weekday", "long" }, + { "year", "2-digit" }, + { "month", "2-digit" }, + { "day", "2-digit" } + }; + std::map timeOptionsMap { + { "dayPeriod", "long" }, + { "hour", "2-digit" }, + { "minute", "2-digit" }, + { "second", "2-digit" }, + { "fractionalSecond", "3" } + }; + SetDateOptionsTest(thread, options, dateOptionsMap); + SetTimeOptionsTest(thread, options, timeOptionsMap); + options = JSDateTimeFormat::ToDateTimeOptions( + thread, JSHandle::Cast(options), RequiredOption::ANY, DefaultsOption::ALL); + JSHandle dtf = CreateDateTimeFormatTest(thread, icuLocale, options); + + double timeStamp1 = 1653448174000; // test "2022-05-25 11:09:34.000" + double timeStamp2 = 1653921012999; // test "2022-05-30 22:30:12.999" + + JSHandle dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp1); + EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr1).c_str(), + "Wednesday, 05/25/22, 11:09:34.000 in the morning"); + JSHandle dateTimeEcamStr2 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp2); + EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr2).c_str(), + "Monday, 05/30/22, 10:30:12.999 at night"); +} + +std::string GetDateTimePartStringTest(JSThread *thread, JSHandle key, JSHandle part) +{ + JSHandle partObj = JSHandle::Cast(part); + JSHandle partValue = JSObject::GetProperty(thread, partObj, key).GetValue(); + JSHandle partEcmaStr = JSHandle::Cast(partValue); + std::string partStr = JSLocale::ConvertToStdString(partEcmaStr); + return partStr; +} + +/** + * @tc.name: FormatDateTimeToParts + * @tc.desc: Convert floating-point timestamp to fixed format time date through time date format. + * The "FormatDateTimeToParts" method converts the output result into an array containing various time and + * date attributes. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTimeToParts_001) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto env = vm->GetGlobalEnv(); + auto globalConst = thread->GlobalConstants(); + + JSHandle typeKey = globalConst->GetHandledTypeString(); + JSHandle valueKey = globalConst->GetHandledValueString(); + + icu::Locale icuLocale("zh", "Hans", "Cn"); + JSHandle objFun = env->GetObjectFunction(); + JSHandle optionsEmtpy = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); + JSHandle hourCycleKey = globalConst->GetHandledHourCycleString(); + JSHandle hourCycleValue(factory->NewFromASCII("h12")); + JSObject::SetProperty(thread, optionsEmtpy, hourCycleKey, hourCycleValue); + JSHandle dtf = CreateDateTimeFormatTest(thread, icuLocale, optionsEmtpy); + + double timeStamp = 1653448174123; // test "2022-05-25 11:09:34.123" + // Use default date time format and format date and time to parts. + JSHandle dateTimeEcamStr1 = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp); + EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr1).c_str(), "2022/5/25"); + JSHandle dateTimeArray1 = JSDateTimeFormat::FormatDateTimeToParts(thread, dtf, timeStamp); + auto year = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray1), 0).GetValue(); + auto literal1 = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray1), 1).GetValue(); + auto month = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray1), 2).GetValue(); + auto literal2 = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray1), 3).GetValue(); + auto day = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray1), 4).GetValue(); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, year).c_str(), "year"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, year).c_str(), "2022"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal1).c_str(), "literal"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal1).c_str(), "/"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, month).c_str(), "month"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, month).c_str(), "5"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal2).c_str(), "literal"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal2).c_str(), "/"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, day).c_str(), "day"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, day).c_str(), "25"); +} + +HWTEST_F_L0(JSDateTimeFormatTest, FormatDateTimeToParts_002) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto env = vm->GetGlobalEnv(); + auto globalConst = thread->GlobalConstants(); + + JSHandle typeKey = globalConst->GetHandledTypeString(); + JSHandle valueKey = globalConst->GetHandledValueString(); + icu::Locale icuLocale("zh", "Hans", "Cn"); + JSHandle objFun = env->GetObjectFunction(); + JSHandle options = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); + JSHandle hourCycleKey = globalConst->GetHandledHourCycleString(); + JSHandle hourCycleValue(factory->NewFromASCII("h12")); + JSObject::SetProperty(thread, options, hourCycleKey, hourCycleValue); + + double timeStamp = 1653448174123; // test "2022-05-25 11:09:34.123" + // Set custom date time format and format date and time to parts. + std::map dateOptionsMap { + { "weekday", "long" }, + { "year", "2-digit" }, + { "month", "2-digit" }, + { "day", "2-digit" } + }; + std::map timeOptionsMap { + { "dayPeriod", "long" }, + { "hour", "2-digit" }, + { "minute", "2-digit" }, + { "second", "2-digit" }, + { "fractionalSecond", "3" } + }; + SetDateOptionsTest(thread, options, dateOptionsMap); + SetTimeOptionsTest(thread, options, timeOptionsMap); + options = JSDateTimeFormat::ToDateTimeOptions( + thread, JSHandle::Cast(options), RequiredOption::ANY, DefaultsOption::ALL); + JSHandle dtf = CreateDateTimeFormatTest(thread, icuLocale, options); + JSHandle dateTimeEcamStr = JSDateTimeFormat::FormatDateTime(thread, dtf, timeStamp); + EXPECT_STREQ(JSLocale::ConvertToStdString(dateTimeEcamStr).c_str(), "22年05月25日星期三 上午11:09:34.123"); + + JSHandle dateTimeArray = JSDateTimeFormat::FormatDateTimeToParts(thread, dtf, timeStamp); + auto year = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 0).GetValue(); + auto literal1 = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 1).GetValue(); + auto month = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 2).GetValue(); + auto literal2 = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 3).GetValue(); + auto day = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 4).GetValue(); + auto literal3 = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 5).GetValue(); + auto weekday = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 6).GetValue(); + auto literal4 = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 7).GetValue(); + auto dayPeriod = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 8).GetValue(); + auto hour = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 9).GetValue(); + auto literal5 = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 10).GetValue(); + auto minute = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 11).GetValue(); + auto literal6 = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 12).GetValue(); + auto second = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 13).GetValue(); + auto literal7 = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 14).GetValue(); + auto fracSec = JSTaggedValue::GetProperty(thread, JSHandle::Cast(dateTimeArray), 15).GetValue(); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, year).c_str(), "year"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, year).c_str(), "22"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal1).c_str(), "literal"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal1).c_str(), "年"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, month).c_str(), "month"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, month).c_str(), "05"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal2).c_str(), "literal"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal2).c_str(), "月"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, day).c_str(), "day"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, day).c_str(), "25"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal3).c_str(), "literal"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal3).c_str(), "日"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, weekday).c_str(), "weekday"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, weekday).c_str(), "星期三"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal4).c_str(), "literal"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal4).c_str(), " "); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, dayPeriod).c_str(), "dayPeriod"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, dayPeriod).c_str(), "上午"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, hour).c_str(), "hour"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, hour).c_str(), "11"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal5).c_str(), "literal"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal5).c_str(), ":"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, minute).c_str(), "minute"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, minute).c_str(), "09"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal6).c_str(), "literal"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal6).c_str(), ":"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, second).c_str(), "second"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, second).c_str(), "34"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, literal7).c_str(), "literal"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, literal7).c_str(), "."); + EXPECT_STREQ(GetDateTimePartStringTest(thread, typeKey, fracSec).c_str(), "fractionalSecond"); + EXPECT_STREQ(GetDateTimePartStringTest(thread, valueKey, fracSec).c_str(), "123"); +} +/** + * @tc.name: GainAvailableLocales + * @tc.desc: Get the available localized label array. If the global time date localized label is not set, return an + * array containing all available labels. Otherwise, return an array containing self-defined labels. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F_L0(JSDateTimeFormatTest, GainAvailableLocales) +{ + auto vm = thread->GetEcmaVM(); + auto factory = vm->GetFactory(); + auto env = vm->GetGlobalEnv(); + + // The date and time format locales is not initialized, + // then get all available locales and save them in a 'TaggedArray'. + JSHandle dateTimeFormatLocales = env->GetDateTimeFormatLocales(); + EXPECT_EQ(dateTimeFormatLocales.GetTaggedValue(), JSTaggedValue::Undefined()); + + const char *key = "calendar"; + const char *path = nullptr; + JSHandle availableLocales = JSLocale::GetAvailableLocales(thread, key, path); + env->SetDateTimeFormatLocales(thread, availableLocales); + JSHandle gainLocales1 = JSDateTimeFormat::GainAvailableLocales(thread); + EXPECT_EQ(JSHandle::Cast(gainLocales1).GetTaggedValue().GetRawData(), + JSHandle::Cast(availableLocales).GetTaggedValue().GetRawData()); + + // The date and time format locales has already been initialized, + // then get custom locale and save it in a 'TaggedArray'. + JSHandle objFun = env->GetObjectFunction(); + JSHandle localeCtor = env->GetLocaleFunction(); + JSHandle dtfCtor = env->GetDateTimeFormatFunction(); + + JSHandle locales = + JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(localeCtor), localeCtor)); + icu::Locale icuLocale("zh", "Hans", "Cn", "calendar=chinese"); + factory->NewJSIntlIcuData(locales, icuLocale, JSLocale::FreeIcuLocale); + JSHandle options = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); + options = JSDateTimeFormat::ToDateTimeOptions( + thread, JSHandle::Cast(options), RequiredOption::ANY, DefaultsOption::ALL); + JSHandle dtf = + JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(dtfCtor), dtfCtor)); + dtf = JSDateTimeFormat::InitializeDateTimeFormat( + thread, dtf, JSHandle::Cast(locales), JSHandle::Cast(options)); + + JSHandle localeTagVal(thread, dtf->GetLocale()); + JSHandle localesTagArr = factory->NewTaggedArray(1); + localesTagArr->Set(thread, 0, localeTagVal); + env->SetDateTimeFormatLocales(thread, localesTagArr); + JSHandle gainLocales2 = JSDateTimeFormat::GainAvailableLocales(thread); + EXPECT_EQ(gainLocales2->GetLength(), 1U); + EXPECT_STREQ(CString(JSHandle(thread, gainLocales2->Get(0))->GetCString().get()).c_str(), + "zh-Hans-CN-u-ca-chinese"); +} +} // namespace panda::test From 077f38f6891c7571962d4d36d70b46ac3d4829d2 Mon Sep 17 00:00:00 2001 From: lichenshuai Date: Thu, 2 Jun 2022 10:32:46 +0800 Subject: [PATCH 02/35] Delete RSP macro and .S file Rsp is used in future work, therefore .S file should be deleted. Issue: #I5AGW3 Signed-off-by: lichenshuai Change-Id: Ib1fb140d40d259bc4519fbf547857e5f80e9ee0c --- BUILD.gn | 15 - ecmascript/base/config.h | 1 - ecmascript/compiler/interpreter_stub-inl.h | 4 - ecmascript/compiler/interpreter_stub.cpp | 623 ------------------ ecmascript/compiler/stub.cpp | 16 - .../trampoline/x64/assembler_stubs_x64.cpp | 2 - ecmascript/frames.h | 1 - ecmascript/interpreter/frame_handler.cpp | 27 +- ecmascript/interpreter/frame_handler.h | 2 - ecmascript/interpreter/interpreter-inl.h | 8 - ecmascript/interpreter/interpreter.cpp | 8 - .../interpreter/interpreter_assembly.cpp | 217 +----- ecmascript/interpreter/interpreter_assembly.h | 1 - ecmascript/js_method.h | 1 - ecmascript/js_thread.cpp | 6 - ecmascript/object_factory.cpp | 12 +- ecmascript/trampoline/aarch64/call.S | 56 -- ecmascript/trampoline/arm32/call.S | 21 - ecmascript/trampoline/asm_defines.h | 22 - ecmascript/trampoline/mac_x64/call.S | 19 - ecmascript/trampoline/win_x64/call.S | 21 - ecmascript/trampoline/x64/call.S | 55 -- 22 files changed, 7 insertions(+), 1131 deletions(-) delete mode 100644 ecmascript/trampoline/aarch64/call.S delete mode 100644 ecmascript/trampoline/arm32/call.S delete mode 100644 ecmascript/trampoline/asm_defines.h delete mode 100644 ecmascript/trampoline/mac_x64/call.S delete mode 100644 ecmascript/trampoline/win_x64/call.S delete mode 100644 ecmascript/trampoline/x64/call.S diff --git a/BUILD.gn b/BUILD.gn index e9d50c9294..fb229abdc0 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -521,21 +521,6 @@ if (!is_mingw && !is_mac) { ] } -if (current_cpu == "arm") { - ecma_source += [ "ecmascript/trampoline/arm32/call.S" ] -} else if (current_cpu == "arm64") { - ecma_source += [ "ecmascript/trampoline/aarch64/call.S" ] -} else if (current_cpu == "amd64" || current_cpu == "x64" || - current_cpu == "x86_64") { - if (is_linux) { - ecma_source += [ "ecmascript/trampoline/x64/call.S" ] - } else if (is_mingw) { - ecma_source += [ "ecmascript/trampoline/win_x64/call.S" ] - } else if (is_mac) { - ecma_source += [ "ecmascript/trampoline/mac_x64/call.S" ] - } -} - source_set("libark_jsruntime_set") { sources = ecma_source sources += ecma_profiler_source diff --git a/ecmascript/base/config.h b/ecmascript/base/config.h index 6c7576b0e7..2f3b95eee2 100644 --- a/ecmascript/base/config.h +++ b/ecmascript/base/config.h @@ -22,7 +22,6 @@ namespace panda::ecmascript { #define ECMASCRIPT_ENABLE_DEBUG_MODE 0 #define ECMASCRIPT_ENABLE_ARK_CONTAINER 1 -#define ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK 0 #define ECMASCRIPT_ENABLE_ASM_INTERPRETER_LOG 0 #define ECMASCRIPT_ENABLE_RUNTIME_STAT 0 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) diff --git a/ecmascript/compiler/interpreter_stub-inl.h b/ecmascript/compiler/interpreter_stub-inl.h index 2975ed7fed..fc377ec861 100644 --- a/ecmascript/compiler/interpreter_stub-inl.h +++ b/ecmascript/compiler/interpreter_stub-inl.h @@ -405,11 +405,7 @@ GateRef InterpreterStub::PushRange(GateRef glue, GateRef sp, GateRef array, Gate GateRef InterpreterStub::GetCurrentFrame(GateRef glue) { -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK return GetLastLeaveFrame(glue); -#else - return GetCurrentSpFrame(glue); -#endif } GateRef InterpreterStub::ReadInst32_0(GateRef pc) diff --git a/ecmascript/compiler/interpreter_stub.cpp b/ecmascript/compiler/interpreter_stub.cpp index b7bcc018af..28f9185b55 100644 --- a/ecmascript/compiler/interpreter_stub.cpp +++ b/ecmascript/compiler/interpreter_stub.cpp @@ -352,179 +352,6 @@ DECLARE_ASM_HANDLER(HandleNewObjDynRangePrefImm16V8) GateRef firstArgOffset = Int16(2); GateRef ctor = GetVregValue(sp, ZExtInt16ToPtr(firstArgRegIdx)); GateRef newTarget = GetVregValue(sp, PtrAdd(ZExtInt16ToPtr(firstArgRegIdx), IntPtr(1))); -#if !ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK - Label ctorIsHeapObject(env); - Label ctorIsJSFunction(env); - Label fastPath(env); - Label slowPath(env); - Branch(TaggedIsHeapObject(ctor), &ctorIsHeapObject, &slowPath); - Bind(&ctorIsHeapObject); - Branch(IsJSFunction(ctor), &ctorIsJSFunction, &slowPath); - Bind(&ctorIsJSFunction); - Branch(IsConstructor(ctor), &fastPath, &slowPath); - Bind(&fastPath); - { - GateRef methodOffset = IntPtr(JSFunction::METHOD_OFFSET); - GateRef ctorMethod = Load(VariableType::NATIVE_POINTER(), ctor, methodOffset); - Label ctorIsBuiltinsConstructor(env); - Label ctorNotBuiltinsConstructor(env); - Branch(IsBuiltinsConstructor(ctor), &ctorIsBuiltinsConstructor, &ctorNotBuiltinsConstructor); - Bind(&ctorIsBuiltinsConstructor); - { - // Changed to push newSp like call for further asm. - DEFVARIABLE(newSp, VariableType::NATIVE_POINTER(), - PointerSub(sp, IntPtr(AsmInterpretedFrame::GetSize(env->IsArch32Bit())))); - DEFVARIABLE(i, VariableType::INT32(), ZExtInt16ToInt32(numArgs)); - i = Int32Sub(*i, Int32(1)); - GateRef startIndex = Int32Add(ZExtInt16ToInt32(firstArgRegIdx), ZExtInt16ToInt32(firstArgOffset)); - GateRef endIndex = Int32Add(ZExtInt16ToInt32(firstArgRegIdx), *i); - newSp = PushRange(glue, *newSp, sp, startIndex, endIndex); - // push this - newSp = PushArg(glue, *newSp, Int64(JSTaggedValue::VALUE_UNDEFINED)); - // push newTarget - newSp = PushArg(glue, *newSp, newTarget); - // push func - newSp = PushArg(glue, *newSp, ctor); - // ASSERT(ctorMethod->GetNumVregsWithCallField() == 0) - Label stackOverflow(env); - Label stackNotOverflow(env); - Branch(CheckStackOverflow(glue, *newSp), &stackOverflow, &stackNotOverflow); - Bind(&stackOverflow); - { - CallRuntime(glue, RTSTUB_ID(ThrowStackOverflowException), {}); - DISPATCH_LAST(); - } - Bind(&stackNotOverflow); - SetFrameState(glue, *newSp, ctor, Hole(VariableType::JS_ANY()), Hole(VariableType::JS_ANY()), - IntPtr(0), sp, Int64(static_cast(FrameType::ASM_INTERPRETER_FRAME))); - SetCurrentSpFrame(glue, *newSp); - GateRef numArgsWithThis = Int16Add(numArgs, - Int16(1 - static_cast(NUM_MANDATORY_JSFUNC_ARGS))); // 1: this - GateRef retValue = CallRuntime(glue, RTSTUB_ID(CallNative), - {Int16BuildTaggedTypeWithNoGC(numArgsWithThis)}); - SetCurrentSpFrame(glue, sp); - Label hasPendingException(env); - Label noPendingException(env); - Branch(TaggedIsException(retValue), &hasPendingException, &noPendingException); - Bind(&hasPendingException); - { - DISPATCH_LAST(); - } - Bind(&noPendingException); - varAcc = retValue; - DISPATCH_WITH_ACC(PREF_IMM16_V8); - } - Bind(&ctorNotBuiltinsConstructor); - // IsFastNewFrameEnter is not considered in asm. - GateRef callFieldOffset = IntPtr(JSMethod::GetCallFieldOffset(env->IsArch32Bit())); - GateRef callField = Load(VariableType::INT64(), ctorMethod, callFieldOffset); - GateRef isNativeMask = Int64(static_cast(1) << JSMethod::IsNativeBit::START_BIT); - Label ctorMethodNotNative(env); - Branch(Int64NotEqual(Int64And(callField, isNativeMask), Int64(0)), &slowPath, &ctorMethodNotNative); - Bind(&ctorMethodNotNative); - { - SetPcToFrame(glue, GetFrame(sp), pc); - SetCallSizeToFrame(glue, GetFrame(sp), - IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8))); - DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined()); - Label ctorIsBase(env); - Label ctorNotBase(env); // ASSERT(ctorFunc->IsDerivedConstructor()) - Branch(IsBase(ctor), &ctorIsBase, &ctorNotBase); - Bind(&ctorIsBase); - { - thisObj = CallRuntime(glue, RTSTUB_ID(NewThisObject), {ctor, newTarget}); - // INTERPRETER_RETURN_IF_ABRUPT(thisObj) - Label thisObjIsException(env); - Branch(TaggedIsException(*thisObj), &thisObjIsException, &ctorNotBase); - Bind(&thisObjIsException); - { - DISPATCH_LAST(); - } - } - Bind(&ctorNotBase); - // Changed to push newSp like call for further asm. - DEFVARIABLE(newSp, VariableType::NATIVE_POINTER(), - PointerSub(sp, IntPtr(AsmInterpretedFrame::GetSize(env->IsArch32Bit())))); - DEFVARIABLE(i, VariableType::INT32(), Int32(0)); - GateRef numArgsOffset = Int64(JSMethod::NumArgsBits::START_BIT); - GateRef numArgsMask = Int64((static_cast(1) << JSMethod::NumArgsBits::SIZE) - 1); - GateRef declaredNumArgs = ChangeInt64ToInt32(Int64And(Int64LSR(callField, numArgsOffset), numArgsMask)); - GateRef actualNumArgs = ZExtInt16ToInt32(Int16Sub(numArgs, firstArgOffset)); // exclude func and newTarget - // Ignore haveExtra to hide this object in the 2nd last index - newSp = PushArg(glue, *newSp, IntBuildTaggedTypeWithNoGC(actualNumArgs)); - newSp = PushArg(glue, *newSp, *thisObj); - GateRef undefinedNumArgs = Int32Sub(declaredNumArgs, actualNumArgs); - newSp = PushUndefined(glue, *newSp, undefinedNumArgs); - i = actualNumArgs; - i = Int32Add(*i, Int32(1)); // +2 for func and newTarget, -1 to get last index - GateRef startIndex = Int32Add(ZExtInt16ToInt32(firstArgRegIdx), ZExtInt16ToInt32(firstArgOffset)); - GateRef endIndex = Int32Add(ZExtInt16ToInt32(firstArgRegIdx), *i); - newSp = PushRange(glue, *newSp, sp, startIndex, endIndex); - - GateRef haveThisMask = Int64(static_cast(1) << JSMethod::HaveThisBit::START_BIT); - Label ctorMethodHaveThis(env); - Label ctorMethodNoThis(env); - Branch(Int64NotEqual(Int64And(callField, haveThisMask), Int64(0)), - &ctorMethodHaveThis, &ctorMethodNoThis); - Bind(&ctorMethodHaveThis); - { - newSp = PushArg(glue, *newSp, *thisObj); - Jump(&ctorMethodNoThis); - } - Bind(&ctorMethodNoThis); - GateRef haveNewTargetMask = Int64(static_cast(1) << JSMethod::HaveNewTargetBit::START_BIT); - Label ctorMethodHaveNewTarget(env); - Label ctorMethodNoNewTarget(env); - Branch(Int64NotEqual(Int64And(callField, haveNewTargetMask), Int64(0)), - &ctorMethodHaveNewTarget, &ctorMethodNoNewTarget); - Bind(&ctorMethodHaveNewTarget); - { - newSp = PushArg(glue, *newSp, newTarget); - Jump(&ctorMethodNoNewTarget); - } - Bind(&ctorMethodNoNewTarget); - GateRef haveFuncMask = Int64(static_cast(1) << JSMethod::HaveFuncBit::START_BIT); - Label ctorMethodHaveFunc(env); - Label ctorMethodNoFunc(env); - Branch(Int64NotEqual(Int64And(callField, haveFuncMask), Int64(0)), - &ctorMethodHaveFunc, &ctorMethodNoFunc); - Bind(&ctorMethodHaveFunc); - { - newSp = PushArg(glue, *newSp, ctor); - Jump(&ctorMethodNoFunc); - } - Bind(&ctorMethodNoFunc); - - // push vregs - GateRef numVregsOffset = Int64(JSMethod::NumVregsBits::START_BIT); - GateRef numVregsMask = Int64((static_cast(1) << JSMethod::NumVregsBits::SIZE) - 1); - GateRef numVregs = ChangeInt64ToInt32(Int64And(Int64LSR(callField, numVregsOffset), numVregsMask)); - newSp = PushUndefined(glue, *newSp, numVregs); - Label stackOverflow(env); - Label stackNotOverflow(env); - Branch(CheckStackOverflow(glue, *newSp), &stackOverflow, &stackNotOverflow); - Bind(&stackOverflow); - { - CallRuntime(glue, RTSTUB_ID(ThrowStackOverflowException), {}); - DISPATCH_LAST(); - } - Bind(&stackNotOverflow); - GateRef newEnv = GetEnvFromFunction(ctor); - GateRef bytecodeArrayOffset = IntPtr(JSMethod::GetBytecodeArrayOffset(env->IsArch32Bit())); - GateRef bytecodeArray = Load(VariableType::NATIVE_POINTER(), ctorMethod, bytecodeArrayOffset); - SetFrameState(glue, *newSp, ctor, Hole(VariableType::JS_ANY()), newEnv, bytecodeArray, sp, - Int64(static_cast(FrameType::INTERPRETER_CONSTRUCTOR_FRAME))); - SetCurrentSpFrame(glue, *newSp); - GateRef newConstpool = GetConstpoolFromFunction(ctor); - GateRef newProfileTypeInfo = GetProfileTypeInfoFromFunction(ctor); - GateRef newHotnessCounter = Load(VariableType::INT32(), ctorMethod, - IntPtr(JSMethod::GetHotnessCounterOffset(env->IsArch32Bit()))); - Dispatch(glue, *newSp, bytecodeArray, newConstpool, newProfileTypeInfo, - Hole(VariableType::JS_ANY()), newHotnessCounter, IntPtr(0)); - } - } - Bind(&slowPath); -#endif GateRef firstArgIdx = Int16Add(firstArgRegIdx, firstArgOffset); GateRef length = Int16Sub(numArgs, firstArgOffset); GateRef res = CallRuntime(glue, RTSTUB_ID(NewObjDynRange), @@ -4371,47 +4198,6 @@ DECLARE_ASM_HANDLER(HandleReturnDyn) } Bind(&pcNotEqualNullptr); { -#if !ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK - SetCurrentSpFrame(glue, *varSp); - GateRef frameTypeOffset = IntPtr(AsmInterpretedFrame::GetBaseOffset(env->IsArch32Bit()) + - InterpretedFrameBase::GetTypeOffset(env->IsArch32Bit())); - GateRef currentFrameType = Load(VariableType::INT64(), frame, frameTypeOffset); - Label isFastNewFrameExit(env); - Label interpreterStubReturn(env); - Branch(Int64Equal(currentFrameType, Int64(static_cast(FrameType::INTERPRETER_CONSTRUCTOR_FRAME))), - &isFastNewFrameExit, &interpreterStubReturn); - Bind(&isFastNewFrameExit); - { - GateRef func = GetFunctionFromFrame(frame); - Label accNotEcmaObject(env); - Branch(IsEcmaObject(*varAcc), &interpreterStubReturn, &accNotEcmaObject); - Bind(&accNotEcmaObject); - Label funcIsBase(env); - Label funcNotBase(env); - Branch(IsBase(func), &funcIsBase, &funcNotBase); - Bind(&funcIsBase); - { - GateRef thisObject = GetThisObjectFromFastNewFrame(*varSp); - varAcc = thisObject; - Jump(&interpreterStubReturn); - } - Bind(&funcNotBase); - Label accIsUndefined(env); - Label accNotUndefined(env); - Branch(TaggedIsUndefined(*varAcc), &accIsUndefined, &accNotUndefined); - Bind(&accNotUndefined); - { - SetCurrentSpFrame(glue, currentSp); // Exception should be thrown in currentSp instead of prevSp. - CallRuntime(glue, RTSTUB_ID(ThrowDerivedMustReturnException), {}); - DISPATCH_LAST(); - } - Bind(&accIsUndefined); - GateRef thisObject = GetThisObjectFromFastNewFrame(*varSp); - varAcc = thisObject; - Jump(&interpreterStubReturn); - } - Bind(&interpreterStubReturn); -#endif GateRef function = GetFunctionFromFrame(prevState); varConstpool = GetConstpoolFromFunction(function); varProfileTypeInfo = GetProfileTypeInfoFromFunction(function); @@ -4419,15 +4205,10 @@ DECLARE_ASM_HANDLER(HandleReturnDyn) IntPtr(JSFunctionBase::METHOD_OFFSET)); varHotnessCounter = GetHotnessCounterFromMethod(method); GateRef jumpSize = GetCallSizeFromFrame(prevState); -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndDispatch), { glue, currentSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, jumpSize }); Return(); -#else - Dispatch(glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, - *varHotnessCounter, jumpSize); -#endif } } @@ -4478,44 +4259,6 @@ DECLARE_ASM_HANDLER(HandleReturnUndefinedPref) } Bind(&pcNotEqualNullptr); { -#if !ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK - SetCurrentSpFrame(glue, *varSp); - GateRef frameTypeOffset = IntPtr(AsmInterpretedFrame::GetBaseOffset(env->IsArch32Bit()) + - InterpretedFrameBase::GetTypeOffset(env->IsArch32Bit())); - GateRef currentFrameType = Load(VariableType::INT64(), frame, frameTypeOffset); - Label isFastNewFrameExit(env); - Label interpreterStubReturn(env); - Branch(Int64Equal(currentFrameType, Int64(static_cast(FrameType::INTERPRETER_CONSTRUCTOR_FRAME))), - &isFastNewFrameExit, &interpreterStubReturn); - Bind(&isFastNewFrameExit); - { - GateRef func = GetFunctionFromFrame(frame); - Label funcIsBase(env); - Label funcNotBase(env); - Branch(IsBase(func), &funcIsBase, &funcNotBase); - Bind(&funcIsBase); - { - GateRef thisObject = GetThisObjectFromFastNewFrame(*varSp); - varAcc = thisObject; - Jump(&interpreterStubReturn); - } - Bind(&funcNotBase); - Label accIsUndefined(env); - Label accNotUndefined(env); - Branch(TaggedIsUndefined(*varAcc), &accIsUndefined, &accNotUndefined); - Bind(&accNotUndefined); - { - SetCurrentSpFrame(glue, currentSp); // Exception should be thrown in currentSp instead of prevSp. - CallRuntime(glue, RTSTUB_ID(ThrowDerivedMustReturnException), {}); - DISPATCH_LAST(); - } - Bind(&accIsUndefined); - GateRef thisObject = GetThisObjectFromFastNewFrame(*varSp); - varAcc = thisObject; - Jump(&interpreterStubReturn); - } - Bind(&interpreterStubReturn); -#endif GateRef function = GetFunctionFromFrame(prevState); varConstpool = GetConstpoolFromFunction(function); varProfileTypeInfo = GetProfileTypeInfoFromFunction(function); @@ -4523,15 +4266,10 @@ DECLARE_ASM_HANDLER(HandleReturnUndefinedPref) IntPtr(JSFunctionBase::METHOD_OFFSET)); varHotnessCounter = GetHotnessCounterFromMethod(method); GateRef jumpSize = GetCallSizeFromFrame(prevState); -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndDispatch), { glue, currentSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, jumpSize }); Return(); -#else - Dispatch(glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, - *varHotnessCounter, jumpSize); -#endif } } @@ -4580,9 +4318,7 @@ DECLARE_ASM_HANDLER(HandleSuspendGeneratorPrefV8V8) } Bind(&tryContinue); -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK GateRef currentSp = *varSp; -#endif varSp = Load(VariableType::NATIVE_POINTER(), frame, IntPtr(AsmInterpretedFrame::GetBaseOffset(env->IsArch32Bit()))); GateRef prevState = GetFrame(*varSp); @@ -4595,9 +4331,6 @@ DECLARE_ASM_HANDLER(HandleSuspendGeneratorPrefV8V8) } Bind(&pcNotEqualNullptr); { -#if !ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK - SetCurrentSpFrame(glue, *varSp); -#endif GateRef function = GetFunctionFromFrame(prevState); varConstpool = GetConstpoolFromFunction(function); varProfileTypeInfo = GetProfileTypeInfoFromFunction(function); @@ -4605,15 +4338,10 @@ DECLARE_ASM_HANDLER(HandleSuspendGeneratorPrefV8V8) IntPtr(JSFunctionBase::METHOD_OFFSET)); varHotnessCounter = GetHotnessCounterFromMethod(method); GateRef jumpSize = GetCallSizeFromFrame(prevState); -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndDispatch), { glue, currentSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter, jumpSize }); Return(); -#else - Dispatch(glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, - *varHotnessCounter, jumpSize); -#endif } } @@ -4635,11 +4363,7 @@ DECLARE_ASM_HANDLER(ExceptionHandler) Branch(IntPtrEqual(*varPc, IntPtr(0)), &pcIsInvalid, &pcNotInvalid); Bind(&pcIsInvalid); { -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK CallNGCRuntime(glue, RTSTUB_ID(ResumeUncaughtFrameAndReturn), { glue }); -#else - CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndReturn), { Undefined() }); -#endif Return(); } Bind(&pcNotInvalid); @@ -4654,15 +4378,10 @@ DECLARE_ASM_HANDLER(ExceptionHandler) GateRef method = Load(VariableType::NATIVE_POINTER(), function, IntPtr(JSFunctionBase::METHOD_OFFSET)); varHotnessCounter = GetHotnessCounterFromMethod(method); -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK CallNGCRuntime(glue, RTSTUB_ID(ResumeCaughtFrameAndDispatch), { glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, *varHotnessCounter}); Return(); -#else - Dispatch(glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc, - *varHotnessCounter, IntPtr(0)); -#endif } } @@ -5148,318 +4867,11 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8) DISPATCH_WITH_ACC(PREF_V8); } -#define CALL_INITIALIZE() \ - SetPcToFrame(glue, GetFrame(sp), pc); \ - GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); \ - Label funcIsHeapObject(env); \ - Label funcIsCallable(env); \ - Label funcNotCallable(env); \ - Branch(TaggedIsHeapObject(func), &funcIsHeapObject, &funcNotCallable); \ - Bind(&funcIsHeapObject); \ - Branch(IsCallable(func), &funcIsCallable, &funcNotCallable); \ - Bind(&funcNotCallable); \ - { \ - CallRuntime(glue, RTSTUB_ID(ThrowNotCallableException), {}); \ - DISPATCH_LAST(); \ - } \ - Bind(&funcIsCallable); \ - GateRef method = GetMethodFromJSFunction(func); \ - GateRef callField = GetCallFieldFromMethod(method); \ - DEFVARIABLE(newSp, VariableType::NATIVE_POINTER(), \ - PointerSub(sp, IntPtr(AsmInterpretedFrame::GetSize(env->IsArch32Bit())))) - -#define CALL_PUSH_ARGS(format) \ - DEFVARIABLE(i, VariableType::INT32(), Int32(0)); \ - GateRef isNativeMask = Int64(static_cast(1) << JSMethod::IsNativeBit::START_BIT); \ - Label methodIsNative(env); \ - Label methodNotNative(env); \ - Branch(Int64NotEqual(Int64And(callField, isNativeMask), Int64(0)), &methodIsNative, &methodNotNative); \ - Bind(&methodIsNative); \ - { \ - CALL_PUSH_ARGS_##format(); \ - SET_VREGS_AND_FRAME_NATIVE(format); \ - } \ - Bind(&methodNotNative); \ - GateRef numArgsOffset = Int64(JSMethod::NumArgsBits::START_BIT); \ - GateRef numArgsMask = Int64((static_cast(1) << JSMethod::NumArgsBits::SIZE) - 1); \ - GateRef declaredNumArgs = ChangeInt64ToInt32(Int64And(Int64LSR(callField, numArgsOffset), numArgsMask)); \ - Label fastPath(env); \ - Label slowPath(env); \ - Label setVregsAndFrameNotNative(env); \ - Branch(Int32Equal(actualNumArgs, declaredNumArgs), &fastPath, &slowPath); \ - Bind(&fastPath); \ - { \ - CALL_PUSH_ARGS_##format(); \ - Jump(&setVregsAndFrameNotNative); \ - } \ - Bind(&slowPath); \ - GateRef haveExtraMask = Int64(static_cast(1) << JSMethod::HaveExtraBit::START_BIT); \ - Label methodNoExtra(env); \ - Label methodHaveExtra(env); \ - Branch(Int64NotEqual(Int64And(callField, haveExtraMask), Int64(0)), &methodHaveExtra, &methodNoExtra); \ - Bind(&methodNoExtra); \ - { \ - GateRef undefinedNumArgs = Int32Sub(declaredNumArgs, actualNumArgs); \ - newSp = PushUndefined(glue, *newSp, undefinedNumArgs); \ - CALL_PUSH_ARGS_NO_EXTRA_##format(); \ - Jump(&setVregsAndFrameNotNative); \ - } \ - Bind(&methodHaveExtra); \ - { \ - newSp = PushArg(glue, *newSp, IntBuildTaggedTypeWithNoGC(actualNumArgs)); \ - GateRef undefinedNumArgs = Int32Sub(declaredNumArgs, actualNumArgs); \ - newSp = PushUndefined(glue, *newSp, undefinedNumArgs); \ - CALL_PUSH_ARGS_##format(); \ - Jump(&setVregsAndFrameNotNative); \ - } \ - Bind(&setVregsAndFrameNotNative); \ - SET_VREGS_AND_FRAME_NOT_NATIVE(format) - -#define SET_VREGS_AND_FRAME_NATIVE(format) \ - Label pushThis(env); \ - Label pushThisUndefined(env); \ - Label pushNewTarget(env); \ - Branch(callThis, &pushThis, &pushThisUndefined); \ - Bind(&pushThis); \ - { \ - GateRef thisValue = GetVregValue(sp, PtrAdd(ZExtInt8ToPtr(funcReg), IntPtr(1))); \ - newSp = PushArg(glue, *newSp, thisValue); \ - Jump(&pushNewTarget); \ - } \ - Bind(&pushThisUndefined); \ - { \ - newSp = PushArg(glue, *newSp, Int64(JSTaggedValue::VALUE_UNDEFINED)); \ - Jump(&pushNewTarget); \ - } \ - Bind(&pushNewTarget); \ - newSp = PushArg(glue, *newSp, Int64(JSTaggedValue::VALUE_UNDEFINED)); \ - newSp = PushArg(glue, *newSp, func); \ - /* ASSERT(JSMethod::NumVregsBits::Decode(callField) == 0) */ \ - Label stackOverflow(env); \ - Label stackNotOverflow(env); \ - Branch(CheckStackOverflow(glue, *newSp), &stackOverflow, &stackNotOverflow); \ - Bind(&stackOverflow); \ - { \ - CallRuntime(glue, RTSTUB_ID(ThrowStackOverflowException), {}); \ - DISPATCH_LAST(); \ - } \ - Bind(&stackNotOverflow); \ - SetFrameState(glue, *newSp, func, Hole(VariableType::JS_ANY()), \ - Hole(VariableType::JS_ANY()), IntPtr(0), sp, \ - Int64(static_cast(FrameType::ASM_INTERPRETER_FRAME))); \ - SetCurrentSpFrame(glue, *newSp); \ - GateRef retValue = CallRuntime(glue, RTSTUB_ID(CallNative), \ - {IntBuildTaggedTypeWithNoGC(actualNumArgs)}); \ - SetCurrentSpFrame(glue, sp); \ - Label hasPendingException(env); \ - Label noPendingException(env); \ - Branch(TaggedIsException(retValue), &hasPendingException, &noPendingException); \ - Bind(&hasPendingException); \ - { \ - DISPATCH_LAST(); \ - } \ - Bind(&noPendingException); \ - DEFVARIABLE(varAcc, VariableType::JS_ANY(), retValue); \ - DISPATCH_WITH_ACC(format) - -#define SET_VREGS_AND_FRAME_NOT_NATIVE(format) \ - Label funcIsClassConstructor(env); \ - Label funcNotClassConstructor(env); \ - Branch(IsClassConstructor(func), &funcIsClassConstructor, &funcNotClassConstructor); \ - Bind(&funcIsClassConstructor); \ - { \ - CallRuntime(glue, RTSTUB_ID(ThrowCallConstructorException), {}); \ - DISPATCH_LAST(); \ - } \ - Bind(&funcNotClassConstructor); \ - Label notNormalCallType(env); \ - Label isNormalCallType(env); \ - Branch(Int64Equal(Int64And(callField, Int64(CALL_TYPE_MASK)), Int64(0)), \ - &isNormalCallType, ¬NormalCallType); \ - Bind(¬NormalCallType); \ - { \ - GateRef haveThisMask = Int64(static_cast(1) << JSMethod::HaveThisBit::START_BIT); \ - Label methodHaveThis(env); \ - Label methodNoThis(env); \ - Branch(Int64NotEqual(Int64And(callField, haveThisMask), Int64(0)), \ - &methodHaveThis, &methodNoThis); \ - Bind(&methodHaveThis); \ - { \ - Label pushThis(env); \ - Label pushThisUndefined(env); \ - Branch(callThis, &pushThis, &pushThisUndefined); \ - Bind(&pushThis); \ - { \ - GateRef thisValue = GetVregValue(sp, PtrAdd(ZExtInt8ToPtr(funcReg), IntPtr(1))); \ - newSp = PushArg(glue, *newSp, thisValue); \ - Jump(&methodNoThis); \ - } \ - Bind(&pushThisUndefined); \ - { \ - newSp = PushArg(glue, *newSp, Int64(JSTaggedValue::VALUE_UNDEFINED)); \ - Jump(&methodNoThis); \ - } \ - } \ - Bind(&methodNoThis); \ - GateRef haveNewTargetMask = Int64(static_cast(1) << JSMethod::HaveNewTargetBit::START_BIT); \ - Label methodHaveNewTarget(env); \ - Label methodNoNewTarget(env); \ - Branch(Int64NotEqual(Int64And(callField, haveNewTargetMask), Int64(0)), \ - &methodHaveNewTarget, &methodNoNewTarget); \ - Bind(&methodHaveNewTarget); \ - { \ - newSp = PushArg(glue, *newSp, Int64(JSTaggedValue::VALUE_UNDEFINED)); \ - Jump(&methodNoNewTarget); \ - } \ - Bind(&methodNoNewTarget); \ - GateRef haveFuncMask = Int64(static_cast(1) << JSMethod::HaveFuncBit::START_BIT); \ - Label methodHaveFunc(env); \ - Label methodNoFunc(env); \ - Branch(Int64NotEqual(Int64And(callField, haveFuncMask), Int64(0)), \ - &methodHaveFunc, &methodNoFunc); \ - Bind(&methodHaveFunc); \ - { \ - newSp = PushArg(glue, *newSp, func); \ - Jump(&methodNoFunc); \ - } \ - Bind(&methodNoFunc); \ - Jump(&isNormalCallType); \ - } \ - Bind(&isNormalCallType); \ - { \ - GateRef numVregsOffset = Int64(JSMethod::NumVregsBits::START_BIT); \ - GateRef numVregsMask = Int64((static_cast(1) << JSMethod::NumVregsBits::SIZE) - 1); \ - GateRef numVregs = ChangeInt64ToInt32(Int64And(Int64LSR(callField, numVregsOffset), numVregsMask)); \ - newSp = PushUndefined(glue, *newSp, numVregs); \ - Label stackOverflow(env); \ - Label stackNotOverflow(env); \ - Branch(CheckStackOverflow(glue, *newSp), &stackOverflow, &stackNotOverflow); \ - Bind(&stackOverflow); \ - { \ - CallRuntime(glue, RTSTUB_ID(ThrowStackOverflowException), {}); \ - DISPATCH_LAST(); \ - } \ - Bind(&stackNotOverflow); \ - SetCallSizeToFrame(glue, GetFrame(sp), \ - IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::format))); \ - GateRef newEnv = GetEnvFromFunction(func); \ - GateRef bytecodeArrayOffset = IntPtr(JSMethod::GetBytecodeArrayOffset(env->IsArch32Bit())); \ - GateRef bytecodeArray = Load(VariableType::NATIVE_POINTER(), method, bytecodeArrayOffset); \ - SetFrameState(glue, *newSp, func, Hole(VariableType::JS_ANY()), newEnv, bytecodeArray, sp, \ - Int64(static_cast(FrameType::ASM_INTERPRETER_FRAME))); \ - SetCurrentSpFrame(glue, *newSp); \ - GateRef newConstpool = GetConstpoolFromFunction(func); \ - GateRef newProfileTypeInfo = GetProfileTypeInfoFromFunction(func); \ - GateRef newHotnessCounter = GetHotnessCounterFromMethod(method); \ - Dispatch(glue, *newSp, bytecodeArray, newConstpool, newProfileTypeInfo, \ - Hole(VariableType::JS_ANY()), newHotnessCounter, IntPtr(0)); \ - } - -#define CALL_PUSH_ARGS_PREF_V8() \ - static_cast(0) // do nothing when 0 arg - -#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8() \ - static_cast(0) // do nothing when 0 arg - -#define CALL_PUSH_ARGS_PREF_V8_V8() \ - GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); \ - newSp = PushArg(glue, *newSp, a0Value) - -#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8() \ - Label push0(env); \ - Label skip0(env); \ - Branch(Int32GreaterThanOrEqual(declaredNumArgs, \ - Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARG1)), &push0, &skip0); \ - Bind(&push0); \ - { \ - GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); \ - newSp = PushArg(glue, *newSp, a0Value); \ - Jump(&skip0); \ - } \ - Bind(&skip0) - -#define CALL_PUSH_ARGS_PREF_V8_V8_V8() \ - GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1)); \ - newSp = PushArg(glue, *newSp, a1Value); \ - CALL_PUSH_ARGS_PREF_V8_V8() - -#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8() \ - Label push1(env); \ - Label skip1(env); \ - Branch(Int32GreaterThanOrEqual(declaredNumArgs, \ - Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARGS2)), &push1, &skip1); \ - Bind(&push1); \ - { \ - GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1)); \ - newSp = PushArg(glue, *newSp, a1Value); \ - Jump(&skip1); \ - } \ - Bind(&skip1); \ - CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8() - -#define CALL_PUSH_ARGS_PREF_V8_V8_V8_V8() \ - GateRef a2Value = GetVregValue(sp, ZExtInt8ToPtr(a2)); \ - newSp = PushArg(glue, *newSp, a2Value); \ - CALL_PUSH_ARGS_PREF_V8_V8_V8() - -#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8_V8() \ - Label push2(env); \ - Label skip2(env); \ - Branch(Int32GreaterThanOrEqual(declaredNumArgs, \ - Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARGS3)), &push2, &skip2); \ - Bind(&push2); \ - { \ - GateRef a2Value = GetVregValue(sp, ZExtInt8ToPtr(a2)); \ - newSp = PushArg(glue, *newSp, a2Value); \ - Jump(&skip2); \ - } \ - Bind(&skip2); \ - CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8() - -#define CALL_PUSH_ARGS_PREF_IMM16_V8() \ - i = actualNumArgs; \ - CALL_PUSH_ARGS_I() - -#define CALL_PUSH_ARGS_NO_EXTRA_PREF_IMM16_V8() \ - /* i = std::min(actualNumArgs, declaredNumArgs) */ \ - i = actualNumArgs; \ - Label declaredNumArgsSmaller(env); \ - Label callPushArgsI(env); \ - Branch(Int32LessThan(*i, declaredNumArgs), &callPushArgsI, &declaredNumArgsSmaller); \ - Bind(&declaredNumArgsSmaller); \ - i = declaredNumArgs; \ - Jump(&callPushArgsI); \ - Bind(&callPushArgsI); \ - CALL_PUSH_ARGS_I() - -#define CALL_PUSH_ARGS_I() \ - Label pushWithThis(env); \ - Label pushWithoutThis(env); \ - Label pushArgsEnd(env); \ - Branch(callThis, &pushWithThis, &pushWithoutThis); \ - Bind(&pushWithThis); \ - { \ - i = Int32Add(*i, Int32(1)); /* 1: skip this */ \ - GateRef startIndex = Int32Add(ZExtInt8ToInt32(funcReg), Int32(2)); /* 2: skip this */ \ - GateRef endIndex = Int32Add(ZExtInt8ToInt32(funcReg), *i); \ - newSp = PushRange(glue, *newSp, sp, startIndex, endIndex); \ - Jump(&pushArgsEnd); \ - } \ - Bind(&pushWithoutThis); \ - { \ - GateRef startIndex = Int32Add(ZExtInt8ToInt32(funcReg), Int32(1)); \ - GateRef endIndex = Int32Add(ZExtInt8ToInt32(funcReg), *i); \ - newSp = PushRange(glue, *newSp, sp, startIndex, endIndex); \ - Jump(&pushArgsEnd); \ - } \ - Bind(&pushArgsEnd) - DECLARE_ASM_HANDLER(HandleCallArg0DynPrefV8) { auto env = GetEnvironment(); GateRef actualNumArgs = Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARG0); GateRef funcReg = ReadInst8_1(pc); -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8)); GateRef res = JSCallDispatch(glue, func, actualNumArgs, JSCallMode::CALL_ARG0, {}); @@ -5472,11 +4884,6 @@ DECLARE_ASM_HANDLER(HandleCallArg0DynPrefV8) } Bind(¬Exception); Dispatch(glue, sp, pc, constpool, profileTypeInfo, res, hotnessCounter, jumpSize); -#else - CALL_INITIALIZE(); - GateRef callThis = False(); - CALL_PUSH_ARGS(PREF_V8); -#endif } DECLARE_ASM_HANDLER(HandleCallArg1DynPrefV8V8) @@ -5485,7 +4892,6 @@ DECLARE_ASM_HANDLER(HandleCallArg1DynPrefV8V8) GateRef actualNumArgs = Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARG1); GateRef funcReg = ReadInst8_1(pc); GateRef a0 = ReadInst8_2(pc); -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8)); @@ -5499,11 +4905,6 @@ DECLARE_ASM_HANDLER(HandleCallArg1DynPrefV8V8) } Bind(¬Exception); Dispatch(glue, sp, pc, constpool, profileTypeInfo, res, hotnessCounter, jumpSize); -#else - CALL_INITIALIZE(); - GateRef callThis = False(); - CALL_PUSH_ARGS(PREF_V8_V8); -#endif } DECLARE_ASM_HANDLER(HandleCallArgs2DynPrefV8V8V8) @@ -5513,7 +4914,6 @@ DECLARE_ASM_HANDLER(HandleCallArgs2DynPrefV8V8V8) GateRef funcReg = ReadInst8_1(pc); GateRef a0 = ReadInst8_2(pc); GateRef a1 = ReadInst8_3(pc); -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1)); @@ -5529,11 +4929,6 @@ DECLARE_ASM_HANDLER(HandleCallArgs2DynPrefV8V8V8) } Bind(¬Exception); Dispatch(glue, sp, pc, constpool, profileTypeInfo, res, hotnessCounter, jumpSize); -#else - CALL_INITIALIZE(); - GateRef callThis = False(); - CALL_PUSH_ARGS(PREF_V8_V8_V8); -#endif } DECLARE_ASM_HANDLER(HandleCallArgs3DynPrefV8V8V8V8) @@ -5544,7 +4939,6 @@ DECLARE_ASM_HANDLER(HandleCallArgs3DynPrefV8V8V8V8) GateRef a0 = ReadInst8_2(pc); GateRef a1 = ReadInst8_3(pc); GateRef a2 = ReadInst8_4(pc); -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1)); @@ -5561,11 +4955,6 @@ DECLARE_ASM_HANDLER(HandleCallArgs3DynPrefV8V8V8V8) } Bind(¬Exception); Dispatch(glue, sp, pc, constpool, profileTypeInfo, res, hotnessCounter, jumpSize); -#else - CALL_INITIALIZE(); - GateRef callThis = False(); - CALL_PUSH_ARGS(PREF_V8_V8_V8_V8); -#endif } DECLARE_ASM_HANDLER(HandleCallIRangeDynPrefImm16V8) @@ -5573,7 +4962,6 @@ DECLARE_ASM_HANDLER(HandleCallIRangeDynPrefImm16V8) auto env = GetEnvironment(); GateRef actualNumArgs = ZExtInt16ToInt32(ReadInst16_1(pc)); GateRef funcReg = ReadInst8_3(pc); -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); GateRef argv = PtrAdd(sp, PtrMul( PtrAdd(ZExtInt8ToPtr(funcReg), IntPtr(1)), IntPtr(8))); // 1: skip function @@ -5590,11 +4978,6 @@ DECLARE_ASM_HANDLER(HandleCallIRangeDynPrefImm16V8) } Bind(¬Exception); Dispatch(glue, sp, pc, constpool, profileTypeInfo, res, hotnessCounter, jumpSize); -#else - CALL_INITIALIZE(); - GateRef callThis = False(); - CALL_PUSH_ARGS(PREF_IMM16_V8); -#endif } DECLARE_ASM_HANDLER(HandleCallIThisRangeDynPrefImm16V8) @@ -5602,7 +4985,6 @@ DECLARE_ASM_HANDLER(HandleCallIThisRangeDynPrefImm16V8) auto env = GetEnvironment(); GateRef actualNumArgs = Int32Sub(ZExtInt16ToInt32(ReadInst16_1(pc)), Int32(1)); // 1: exclude this GateRef funcReg = ReadInst8_3(pc); -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK funcReg = ZExtInt8ToPtr(funcReg); GateRef func = GetVregValue(sp, funcReg); GateRef thisValue = GetVregValue(sp, PtrAdd(funcReg, IntPtr(1))); @@ -5621,11 +5003,6 @@ DECLARE_ASM_HANDLER(HandleCallIThisRangeDynPrefImm16V8) } Bind(¬Exception); Dispatch(glue, sp, pc, constpool, profileTypeInfo, res, hotnessCounter, jumpSize); -#else - CALL_INITIALIZE(); - GateRef callThis = True(); - CALL_PUSH_ARGS(PREF_IMM16_V8); -#endif } DECLARE_ASM_HANDLER(HandleLdBigIntPrefId32) diff --git a/ecmascript/compiler/stub.cpp b/ecmascript/compiler/stub.cpp index 22599470e2..d3dc723f29 100644 --- a/ecmascript/compiler/stub.cpp +++ b/ecmascript/compiler/stub.cpp @@ -3786,22 +3786,14 @@ GateRef Stub::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNumArgs, case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV: break; case JSCallMode::CALL_GETTER: -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative), { glue, nativeCode, actualNumArgs, func, newTarget, data[0] }); -#else - result = Hole(); -#endif break; case JSCallMode::CALL_SETTER: -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative), { glue, nativeCode, actualNumArgs, func, newTarget, data[0], data[1] }); -#else - result = Hole(); -#endif break; default: UNREACHABLE(); @@ -3858,21 +3850,13 @@ GateRef Stub::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNumArgs, case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV: break; case JSCallMode::CALL_GETTER: -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK result = CallNGCRuntime(glue, RTSTUB_ID(CallGetter), { glue, func, method, callField, data[0] }); -#else - result = Hole(); -#endif Jump(&exit); break; case JSCallMode::CALL_SETTER: -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK result = CallNGCRuntime(glue, RTSTUB_ID(CallSetter), { glue, func, method, callField, data[0], data[1], }); -#else - result = Hole(); -#endif Jump(&exit); break; default: diff --git a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp index c4c99cd59f..a766e57e39 100644 --- a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp +++ b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp @@ -2039,12 +2039,10 @@ void AssemblerStubsX64::CallSetterSlow(ExtendedAssembler *assembler) void AssemblerStubsX64::ResumeRspAndReturn([[maybe_unused]] ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(ResumeRspAndReturn)); -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK Register fpRegister = r10; auto offset = AsmInterpretedFrame::GetFpOffset(false) - AsmInterpretedFrame::GetSize(false); __ Movq(Operand(rbp, offset), fpRegister); __ Movq(fpRegister, rsp); -#endif // return { __ Movq(r13, rax); diff --git a/ecmascript/frames.h b/ecmascript/frames.h index b587a3c784..e51dba1ad3 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -17,7 +17,6 @@ #define ECMASCRIPT_FRAMES_H #include "ecmascript/js_tagged_value.h" -#include "ecmascript/trampoline/asm_defines.h" // Frame Layout // Interpreter Frame(alias **iframe** ) Layout as follow: diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index 83dc59a8b3..8eff24124f 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -41,13 +41,9 @@ void FrameHandler::PrevFrame() case FrameType::ASM_INTERPRETER_FRAME: { auto frame = AsmInterpretedFrame::GetFrameFromSp(sp_); sp_ = frame->GetPrevFrameFp(); -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK - if (thread_->IsAsmInterpreter() && - sp_ != nullptr && - GetFrameType() != FrameType::ASM_INTERPRETER_ENTRY_FRAME) { + if (thread_->IsAsmInterpreter()) { fp_ = frame->GetCurrentFramePointer(); } -#endif break; } case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: { @@ -180,12 +176,10 @@ JSTaggedType* FrameHandler::GetPrevInterpretedFrame() uint32_t FrameHandler::GetNumberArgs() { -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK if (thread_->IsAsmInterpreter()) { auto *frame = AsmInterpretedFrame::GetFrameFromSp(sp_); return static_cast(frame->GetCurrentFramePointer() - sp_); } -#endif ASSERT(IsInterpretedFrame()); JSTaggedType *prevSp = nullptr; if (IsAsmInterpretedFrame()) { @@ -402,7 +396,6 @@ ARK_INLINE void FrameHandler::AsmInterpretedFrameIterate(const JSTaggedType *sp, const RootVisitor &v0, const RootRangeVisitor &v1) const { -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(sp); uintptr_t start = ToUintPtr(sp); uintptr_t end = ToUintPtr(frame->GetCurrentFramePointer()); @@ -412,22 +405,6 @@ ARK_INLINE void FrameHandler::AsmInterpretedFrameIterate(const JSTaggedType *sp, v0(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->acc))); v0(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->env))); } -#else - AsmInterpretedFrame *frame = AsmInterpretedFrame::GetFrameFromSp(sp); - if (frame->function == JSTaggedValue::Hole()) { - return; - } - - JSTaggedType *prevSp = frame->GetPrevFrameFp(); - uintptr_t start = ToUintPtr(sp); - uintptr_t end = GetInterpretedFrameEnd(prevSp); - v1(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end)); - v0(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->function))); - if (frame->pc != nullptr) { - v0(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->acc))); - v0(Root::ROOT_FRAME, ObjectSlot(ToUintPtr(&frame->env))); - } -#endif // ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK } ARK_INLINE void FrameHandler::BuiltinFrameIterate(const JSTaggedType *sp, @@ -631,13 +608,11 @@ void FrameHandler::IterateSp(const RootVisitor &v0, const RootRangeVisitor &v1) void FrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const { -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK if (thread_->IsAsmInterpreter()) { IterateSp(v0, v1); IterateRsp(v0, v1); return; } -#endif JSTaggedType *current = const_cast(thread_->GetCurrentSPFrame()); FrameType frameType = FrameHandler::GetFrameType(current); if (frameType != FrameType::INTERPRETER_ENTRY_FRAME) { diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index 1c2e4b925d..ff6dc64497 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -89,11 +89,9 @@ public: bool IsInterpretedEntryFrame() const { -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK if (thread_->IsAsmInterpreter()) { return (GetFrameType() == FrameType::ASM_INTERPRETER_ENTRY_FRAME); } -#endif return (GetFrameType() == FrameType::INTERPRETER_ENTRY_FRAME); } diff --git a/ecmascript/interpreter/interpreter-inl.h b/ecmascript/interpreter/interpreter-inl.h index e61597fd03..8054bb942c 100644 --- a/ecmascript/interpreter/interpreter-inl.h +++ b/ecmascript/interpreter/interpreter-inl.h @@ -446,15 +446,7 @@ JSTaggedValue EcmaInterpreter::Execute(EcmaRuntimeCallInfo *info) JSThread *thread = info->GetThread(); INTERPRETER_TRACE(thread, Execute); if (thread->IsAsmInterpreter()) { -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK return InterpreterAssembly::Execute(info); -#else - auto prevLeaveFrame = const_cast(thread->GetLastLeaveFrame()); - thread->SetLastLeaveFrame(nullptr); // avoid setting again in NewRuntimeCallInfo() - JSTaggedValue asmResult = InterpreterAssembly::Execute(info); - thread->SetLastLeaveFrame(prevLeaveFrame); - return asmResult; -#endif } JSHandle func = info->GetFunction(); ECMAObject *callTarget = reinterpret_cast(func.GetTaggedValue().GetTaggedObject()); diff --git a/ecmascript/interpreter/interpreter.cpp b/ecmascript/interpreter/interpreter.cpp index 2924744ecf..8081c39af6 100644 --- a/ecmascript/interpreter/interpreter.cpp +++ b/ecmascript/interpreter/interpreter.cpp @@ -44,15 +44,7 @@ EcmaRuntimeCallInfo EcmaInterpreter::NewRuntimeCallInfo( JSTaggedType *newSp; JSTaggedType *prevSp = sp; if (thread->IsAsmInterpreter()) { -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK newSp = FrameHandler::GetInterpretedEntryFrameStart(sp); -#else - newSp = sp - AsmInterpretedFrame::NumOfMembers(); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) - auto leaveFrame = const_cast(thread->GetLastLeaveFrame()); - if (leaveFrame != nullptr) { - prevSp = leaveFrame; - } -#endif } else { newSp = sp - InterpretedFrame::NumOfMembers(); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) } diff --git a/ecmascript/interpreter/interpreter_assembly.cpp b/ecmascript/interpreter/interpreter_assembly.cpp index 36a50a763c..1aac89aa40 100644 --- a/ecmascript/interpreter/interpreter_assembly.cpp +++ b/ecmascript/interpreter/interpreter_assembly.cpp @@ -351,7 +351,7 @@ using panda::ecmascript::kungfu::CommonStubCSigns; EcmaRuntimeCallInfo ecmaRuntimeCallInfo(thread, static_cast(actualNumArgs), newSp); \ AsmInterpretedFrame *state = GET_ASM_FRAME(newSp); \ state->base.prev = sp; \ - state->base.type = FrameType::ASM_INTERPRETER_FRAME; \ + state->base.type = FrameType::ASM_INTERPRETER_FRAME; \ state->pc = nullptr; \ state->function = funcValue; \ thread->SetCurrentSPFrame(newSp); \ @@ -404,7 +404,7 @@ using panda::ecmascript::kungfu::CommonStubCSigns; GET_ASM_FRAME(sp)->callSizeOrCallSiteSp = GetJumpSizeAfterCall(pc); \ AsmInterpretedFrame *state = GET_ASM_FRAME(newSp); \ state->base.prev = sp; \ - state->base.type = FrameType::ASM_INTERPRETER_FRAME; \ + state->base.type = FrameType::ASM_INTERPRETER_FRAME; \ pc = method->GetBytecodeArray(); /* will be stored in DISPATCH_OFFSET */ \ sp = newSp; /* for DISPATCH_OFFSET */ \ state->function = funcValue; \ @@ -419,29 +419,11 @@ using panda::ecmascript::kungfu::CommonStubCSigns; DISPATCH_OFFSET(0); \ } while (false) -extern "C" JSTaggedType JSCallEntry(uintptr_t glue, JSTaggedType *sp, const uint8_t *pc, JSTaggedValue constpool, - JSTaggedValue profileTypeInfo, JSTaggedValue acc, uint32_t hotnessCounter); - using InterpreterEntry = JSTaggedType (*)(uintptr_t glue, uint32_t argc, uintptr_t argv); using GeneratorReEnterInterpEntry = JSTaggedType (*)(uintptr_t glue, JSTaggedType context); -// NOLINTNEXTLINE(readability-function-size) -JSTaggedType InterpreterAssembly::RunInternal(JSThread *thread, ConstantPool *constpool, const uint8_t *pc, JSTaggedType *sp) -{ - // check is or not debugger - thread->CheckSwitchDebuggerBCStub(); - JSTaggedValue acc = JSTaggedValue::Hole(); - AsmInterpretedFrame *state = GET_ASM_FRAME(sp); - auto method = ECMAObject::Cast(state->function.GetTaggedObject())->GetCallTarget(); - auto hotnessCounter = method->GetHotnessCounter(); - auto profileTypeInfo = JSFunction::Cast(state->function.GetTaggedObject())->GetProfileTypeInfo(); - - return JSCallEntry(thread->GetGlueAddr(), sp, pc, JSTaggedValue(constpool), profileTypeInfo, acc, hotnessCounter); -} - void InterpreterAssembly::InitStackFrame(JSThread *thread) { -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK JSTaggedType *prevSp = const_cast(thread->GetCurrentSPFrame()); InterpretedEntryFrame *entryState = InterpretedEntryFrame::GetFrameFromSp(prevSp); entryState->base.type = FrameType::INTERPRETER_ENTRY_FRAME; @@ -453,15 +435,6 @@ void InterpreterAssembly::InitStackFrame(JSThread *thread) *(--newSp) = JSTaggedValue::Undefined().GetRawData(); *(--newSp) = JSTaggedValue::Undefined().GetRawData(); *(--newSp) = JSTaggedValue::Undefined().GetRawData(); -#else - uint64_t *prevSp = const_cast(thread->GetCurrentSPFrame()); - AsmInterpretedFrame *state = GET_ASM_FRAME(prevSp); - state->pc = nullptr; - state->function = JSTaggedValue::Hole(); - state->acc = JSTaggedValue::Hole(); - state->base.type = FrameType::ASM_INTERPRETER_FRAME; - state->base.prev = nullptr; -#endif } JSTaggedValue InterpreterAssembly::ExecuteNative(EcmaRuntimeCallInfo *info) @@ -515,7 +488,6 @@ JSTaggedValue InterpreterAssembly::ExecuteNative(EcmaRuntimeCallInfo *info) return tagged; } -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK JSTaggedValue InterpreterAssembly::Execute(EcmaRuntimeCallInfo *info) { ASSERT(info); @@ -539,187 +511,13 @@ JSTaggedValue InterpreterAssembly::Execute(EcmaRuntimeCallInfo *info) #endif return JSTaggedValue(acc); } -#else -JSTaggedValue InterpreterAssembly::Execute(EcmaRuntimeCallInfo *info) -{ - JSThread *thread = info->GetThread(); - ECMAObject *callTarget = reinterpret_cast(info->GetFunctionValue().GetTaggedObject()); - ASSERT(callTarget != nullptr); - JSMethod *method = callTarget->GetCallTarget(); - if (method->IsNativeWithCallField()) { - return InterpreterAssembly::ExecuteNative(info); - } - // current sp is entry frame. - JSTaggedType *sp = const_cast(thread->GetCurrentSPFrame()); - FrameHandler frameHandler(thread); - JSTaggedType *prevSp = frameHandler.GetPrevInterpretedFrame(); - - int32_t actualNumArgs = static_cast(info->GetArgsNumber()); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - JSTaggedType *newSp = sp - GET_ENTRY_FRAME_WITH_ARGS_SIZE(static_cast(actualNumArgs)); - if (thread->DoStackOverflowCheck(newSp - actualNumArgs - RESERVED_CALL_ARGCOUNT)) { - return JSTaggedValue::Undefined(); - } - - int32_t declaredNumArgs = static_cast(method->GetNumArgsWithCallField()); - // push args - if (actualNumArgs == declaredNumArgs) { - // fast path, just push all args directly - for (int i = actualNumArgs - 1; i >= 0; i--) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - *(--newSp) = info->GetCallArgValue(i).GetRawData(); - } - } else { - // slow path - if (!method->HaveExtraWithCallField()) { - // push length = declaredNumArgs, may push undefined - if (declaredNumArgs > actualNumArgs) { - CALL_PUSH_UNDEFINED(declaredNumArgs - actualNumArgs); - } - for (int32_t i = std::min(actualNumArgs, declaredNumArgs) - 1; i >= 0; i--) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - *(--newSp) = info->GetCallArgValue(i).GetRawData(); - } - } else { - // push actualNumArgs in the end, then all args, may push undefined - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - *(--newSp) = JSTaggedValue(actualNumArgs).GetRawData(); - if (declaredNumArgs > actualNumArgs) { - CALL_PUSH_UNDEFINED(declaredNumArgs - actualNumArgs); - } - for (int32_t i = actualNumArgs - 1; i >= 0; i--) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - *(--newSp) = info->GetCallArgValue(i).GetRawData(); - } - } - } - uint64_t callField = method->GetCallField(); - if ((callField & CALL_TYPE_MASK) != 0) { - // not normal call type, setting func/newTarget/this cannot be skipped - if (method->HaveThisWithCallField()) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - *(--newSp) = info->GetThisValue().GetRawData(); // push this - } - if (method->HaveNewTargetWithCallField()) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - *(--newSp) = info->GetNewTargetValue().GetRawData(); // push new target - } - if (method->HaveFuncWithCallField()) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - *(--newSp) = info->GetFunctionValue().GetRawData(); // push func - } - } - int32_t numVregs = static_cast(method->GetNumVregsWithCallField()); - // push vregs - CALL_PUSH_UNDEFINED(numVregs); - if (UNLIKELY(thread->DoStackOverflowCheck(newSp))) { - return JSTaggedValue::Undefined(); - } - - const uint8_t *pc = method->GetBytecodeArray(); - AsmInterpretedFrame *state = GET_ASM_FRAME(newSp); - state->pc = pc; - state->function = info->GetFunctionValue(); - state->acc = JSTaggedValue::Hole(); - JSHandle thisFunc = JSHandle::Cast(info->GetFunction()); - JSTaggedValue constpool = thisFunc->GetConstantPool(); - state->base.prev = sp; - state->base.type = FrameType::ASM_INTERPRETER_FRAME; - state->env = thisFunc->GetLexicalEnv(); - thread->SetCurrentSPFrame(newSp); -#if ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER - CpuProfiler::IsNeedAndGetStack(thread); -#endif - thread->CheckSafepoint(); - LOG(DEBUG, INTERPRETER) << "break Entry: Runtime Call " << std::hex << reinterpret_cast(newSp) << " " - << std::hex << reinterpret_cast(pc); - - auto res = InterpreterAssembly::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), pc, newSp); - - // NOLINTNEXTLINE(readability-identifier-naming) - const JSTaggedValue resAcc = JSTaggedValue(res); - // pop frame - thread->SetCurrentSPFrame(prevSp); -#if ECMASCRIPT_ENABLE_ACTIVE_CPUPROFILER - CpuProfiler::IsNeedAndGetStack(thread); -#endif - return resAcc; -} -#endif - -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK JSTaggedValue InterpreterAssembly::GeneratorReEnterInterpreter(JSThread *thread, JSHandle context) { auto entry = thread->GetRTInterface(kungfu::RuntimeStubCSigns::ID_GeneratorReEnterAsmInterp); auto acc = reinterpret_cast(entry)(thread->GetGlueAddr(), context.GetTaggedType()); return JSTaggedValue(acc); } -#else -JSTaggedValue InterpreterAssembly::GeneratorReEnterInterpreter(JSThread *thread, JSHandle context) -{ - JSHandle func = JSHandle::Cast(JSHandle(thread, context->GetMethod())); - JSMethod *method = func->GetCallTarget(); - - JSTaggedType *currentSp = const_cast(thread->GetCurrentSPFrame()); - JSTaggedType *currentLeaveFrame = const_cast(thread->GetLastLeaveFrame()); - - // push break frame - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - JSTaggedType *breakSp = currentSp - AsmInterpretedFrame::NumOfMembers(); - if (thread->DoStackOverflowCheck(breakSp) || thread->HasPendingException()) { - return JSTaggedValue::Exception(); - } - AsmInterpretedFrame *breakState = GET_ASM_FRAME(breakSp); - breakState->pc = nullptr; - breakState->function = JSTaggedValue::Hole(); - if (currentLeaveFrame == nullptr) { - // no leave frame, set frame chain as usual - breakState->base.prev = currentSp; - } else { - // set current leave frame into the frame chain - breakState->base.prev = currentLeaveFrame; - thread->SetLastLeaveFrame(nullptr); - } - breakState->base.type = FrameType::ASM_INTERPRETER_FRAME; - - // create new frame and resume sp and pc - uint32_t nregs = context->GetNRegs(); - size_t newFrameSize = AsmInterpretedFrame::NumOfMembers() + nregs; - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic - JSTaggedType *newSp = breakSp - newFrameSize; - if (thread->DoStackOverflowCheck(newSp) || thread->HasPendingException()) { - return JSTaggedValue::Exception(); - } - JSHandle regsArray(thread, context->GetRegsArray()); - for (size_t i = 0; i < nregs; i++) { - newSp[i] = regsArray->Get(i).GetRawData(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - } - JSTaggedValue constpool = func->GetConstantPool(); - uint32_t pcOffset = context->GetBCOffset(); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - const uint8_t *resumePc = method->GetBytecodeArray() + pcOffset + - BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8); - - AsmInterpretedFrame *state = GET_ASM_FRAME(newSp); - state->pc = resumePc; - state->function = func.GetTaggedValue(); - state->acc = context->GetAcc(); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - state->base.prev = breakSp; - state->base.type = FrameType::ASM_INTERPRETER_FRAME; - JSTaggedValue env = context->GetLexicalEnv(); - state->env = env; - // execute interpreter - thread->SetCurrentSPFrame(newSp); - auto res = InterpreterAssembly::RunInternal(thread, ConstantPool::Cast(constpool.GetTaggedObject()), resumePc, newSp); - JSTaggedValue acc = JSTaggedValue(res); - // pop frame - thread->SetCurrentSPFrame(currentSp); - thread->SetLastLeaveFrame(currentLeaveFrame); - return acc; -} -#endif void InterpreterAssembly::HandleMovV4V4( JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo, @@ -4216,18 +4014,7 @@ JSTaggedValue InterpreterAssembly::GetNewTarget(JSTaggedType *sp) JSTaggedType *InterpreterAssembly::GetAsmInterpreterFramePointer(AsmInterpretedFrame *state) { JSTaggedType *fp = nullptr; -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK fp = state->GetCurrentFramePointer(); -#else - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - JSTaggedType *lastFrame = state->base.prev; - // The prev frame of InterpretedFrame may entry frame or interpreter frame. - if (FrameHandler::GetFrameType(state->base.prev) == FrameType::INTERPRETER_ENTRY_FRAME) { - fp = FrameHandler::GetInterpretedEntryFrameStart(state->base.prev); - } else { - fp = lastFrame - AsmInterpretedFrame::NumOfMembers(); - } -#endif return fp; } diff --git a/ecmascript/interpreter/interpreter_assembly.h b/ecmascript/interpreter/interpreter_assembly.h index 6d65ddbd0b..c37de0b23e 100644 --- a/ecmascript/interpreter/interpreter_assembly.h +++ b/ecmascript/interpreter/interpreter_assembly.h @@ -36,7 +36,6 @@ class InterpreterAssembly { public: static const uint32_t METHOD_HOTNESS_THRESHOLD = 512; enum ActualNumArgsOfCall : uint8_t { CALLARG0 = 0, CALLARG1, CALLARGS2, CALLARGS3 }; - static JSTaggedType RunInternal(JSThread *thread, ConstantPool *constpool, const uint8_t *pc, JSTaggedType *sp); static void InitStackFrame(JSThread *thread); static JSTaggedValue Execute(EcmaRuntimeCallInfo *info); static JSTaggedValue ExecuteNative(EcmaRuntimeCallInfo *info); diff --git a/ecmascript/js_method.h b/ecmascript/js_method.h index 0738e6a0d8..165f2f125a 100644 --- a/ecmascript/js_method.h +++ b/ecmascript/js_method.h @@ -19,7 +19,6 @@ #include "ecmascript/base/aligned_struct.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/mem/c_string.h" -#include "ecmascript/trampoline/asm_defines.h" #include "libpandafile/file.h" static constexpr uint32_t CALL_TYPE_MASK = 0xF; // 0xF: the last 4 bits are used as callType diff --git a/ecmascript/js_thread.cpp b/ecmascript/js_thread.cpp index d58a064bbe..f4161dead8 100644 --- a/ecmascript/js_thread.cpp +++ b/ecmascript/js_thread.cpp @@ -92,32 +92,26 @@ JSTaggedValue JSThread::GetCurrentLexenv() const const JSTaggedType *JSThread::GetCurrentFrame() const { -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK if (IsAsmInterpreter()) { return GetLastLeaveFrame(); } -#endif return GetCurrentSPFrame(); } void JSThread::SetCurrentFrame(JSTaggedType *sp) { -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK if (IsAsmInterpreter()) { return SetLastLeaveFrame(sp); } -#endif return SetCurrentSPFrame(sp); } const JSTaggedType *JSThread::GetCurrentInterpretedFrame() const { -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK if (IsAsmInterpreter()) { auto frameHandler = FrameHandler(this); return frameHandler.GetSp(); } -#endif return GetCurrentSPFrame(); } diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index cf58710370..48fb40fec5 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -804,16 +804,12 @@ JSHandle ObjectFactory::NewJSError(const ErrorType &errorType, const J // current frame may be entry frame, exception happened in JSFunction::Call and JSFunction::Construct, // in this case sp = the prev frame (interpreter frame). -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK if (!thread_->IsAsmInterpreter()) { -#endif - FrameHandler frameHandler(thread_); - if (frameHandler.IsInterpretedEntryFrame()) { - thread_->SetCurrentSPFrame(frameHandler.GetPrevInterpretedFrame()); + FrameHandler frameHandler(thread_); + if (frameHandler.IsInterpretedEntryFrame()) { + thread_->SetCurrentSPFrame(frameHandler.GetPrevInterpretedFrame()); + } } -#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK - } -#endif JSHandle env = vm_->GetGlobalEnv(); const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); diff --git a/ecmascript/trampoline/aarch64/call.S b/ecmascript/trampoline/aarch64/call.S deleted file mode 100644 index cec6487475..0000000000 --- a/ecmascript/trampoline/aarch64/call.S +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2021 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. - */ - #include "../asm_defines.h" - -.type JSCallEntryInternal, %function -JSCallEntryInternal: - str x30, [sp, #-16]! // 16 byte align - br x8 - -.global JSCallEntry -.type JSCallEntry, %function -JSCallEntry: - stp x29, x30, [sp, #-160]! - stp d15, d14, [sp, #16] - stp d13, d12, [sp, #32] - stp d11, d10, [sp, #48] - stp d9, d8, [sp, #64] - stp x28, x27, [sp, #80] - stp x26, x25, [sp, #96] - stp x24, x23, [sp, #112] - stp x22, x21, [sp, #128] - stp x20, x19, [sp, #144] - ldrb w8, [x2] - mov x29, x1 - mov x19, x0 - mov x20, x2 - add x8, x0, x8, lsl #3 - ldr x8, [x8, #ASM_GLUE_BC_HANDLERS_OFFSET] - mov x21, x3 - mov x22, x4 - mov x23, x5 - mov x24, x6 - bl JSCallEntryInternal - ldp x20, x19, [sp, #144] - ldp x22, x21, [sp, #128] - ldp x24, x23, [sp, #112] - ldp x26, x25, [sp, #96] - ldp x28, x27, [sp, #80] - ldp d9, d8, [sp, #64] - ldp d11, d10, [sp, #48] - ldp d13, d12, [sp, #32] - ldp d15, d14, [sp, #16] - ldp x29, x30, [sp], #160 - ret diff --git a/ecmascript/trampoline/arm32/call.S b/ecmascript/trampoline/arm32/call.S deleted file mode 100644 index cc7caa2bdf..0000000000 --- a/ecmascript/trampoline/arm32/call.S +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2021 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. - */ - -#include "../asm_defines.h" - -.global JSCallEntry -.type JSCallEntry, %function -JSCallEntry: - bx lr diff --git a/ecmascript/trampoline/asm_defines.h b/ecmascript/trampoline/asm_defines.h deleted file mode 100644 index dab39491a8..0000000000 --- a/ecmascript/trampoline/asm_defines.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2021 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. - */ - -#ifndef ECMASCRIPT_ASM_DEFINES_H -#define ECMASCRIPT_ASM_DEFINES_H - -#define ASM_GLUE_BC_HANDLERS_OFFSET (56) -#define JS_ENTRY_FRAME_TYPE (1) - -#endif // ECMASCRIPT_ASM_DEFINES_H diff --git a/ecmascript/trampoline/mac_x64/call.S b/ecmascript/trampoline/mac_x64/call.S deleted file mode 100644 index b80901bba2..0000000000 --- a/ecmascript/trampoline/mac_x64/call.S +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2021 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. - */ - - #include "../asm_defines.h" - -.global _JSCallEntry -_JSCallEntry: \ No newline at end of file diff --git a/ecmascript/trampoline/win_x64/call.S b/ecmascript/trampoline/win_x64/call.S deleted file mode 100644 index 044d211593..0000000000 --- a/ecmascript/trampoline/win_x64/call.S +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2021 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. - */ - - #include "../asm_defines.h" - -// Not supported on windows x64 yet - -.global JSCallEntry -JSCallEntry: \ No newline at end of file diff --git a/ecmascript/trampoline/x64/call.S b/ecmascript/trampoline/x64/call.S deleted file mode 100644 index 9032b0ebc4..0000000000 --- a/ecmascript/trampoline/x64/call.S +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2021 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. - */ - - #include "../asm_defines.h" - -// uint64_t JSFunctionEntry(uintptr_t glue, uintptr_t sp, uintptr_t pc, JSTaggedType constpool, -// JSTaggedType profileInfo, JSTaggedType acc, uint32_t hotnessCounter); -// Input: -// %rdi - glue -// %rsi - sp -// %rdx - pc -// %rcx - constpool -// %r8 - profileInfo -// %r9 - acc -// sp [0] hotnessCounter -.global JSCallEntry -.type JSCallEntry, %function -JSCallEntry: - pushq %rbp - movq %rsp, %rbp - pushq $JS_ENTRY_FRAME_TYPE - pushq %r15 - pushq %r14 - pushq %r13 - pushq %r12 - pushq %rbx - movq %rcx, %rbx // constpool - movq %rdi, %r13 // glue - movzbl (%rdx), %eax // opcode - movl 16(%rbp), %edi // hotnessCounter - movq %rsi, %rbp // sp - movq %rdx, %r12 // pc - movq %r8, %r14 // profileInfo - movq %r9, %rsi // acc - callq *ASM_GLUE_BC_HANDLERS_OFFSET(%r13,%rax,8) - popq %rbx - popq %r12 - popq %r13 - popq %r14 - popq %r15 - addq $8, %rsp // skip type - popq %rbp - retq From 65d3976bf444b6e549ee7566024aeffef761af80 Mon Sep 17 00:00:00 2001 From: yqhan Date: Thu, 2 Jun 2022 10:50:26 +0800 Subject: [PATCH 03/35] Added debugger module tests. Issues:https://gitee.com/openharmony/ark_js_runtime/issues/I5ACV8 Describe: Breakpoints are set inside async functions and arrow functions. Breakpoints can be hit and call stacks can be retrieved. Signed-off-by: yqhan --- ecmascript/tooling/test/BUILD.gn | 26 ++++++ ecmascript/tooling/test/js/ArrowFunc.js | 23 +++++ ecmascript/tooling/test/js/AsyncFunc.js | 33 +++++++ .../testcases/js_breakpoint_arrow_test.h | 89 ++++++++++++++++++ .../testcases/js_breakpoint_async_test.h | 91 +++++++++++++++++++ .../test/utils/testcases/test_list.cpp | 4 + 6 files changed, 266 insertions(+) create mode 100644 ecmascript/tooling/test/js/ArrowFunc.js create mode 100644 ecmascript/tooling/test/js/AsyncFunc.js create mode 100644 ecmascript/tooling/test/utils/testcases/js_breakpoint_arrow_test.h create mode 100644 ecmascript/tooling/test/utils/testcases/js_breakpoint_async_test.h diff --git a/ecmascript/tooling/test/BUILD.gn b/ecmascript/tooling/test/BUILD.gn index ec5099f35b..ce45a1e016 100644 --- a/ecmascript/tooling/test/BUILD.gn +++ b/ecmascript/tooling/test/BUILD.gn @@ -44,6 +44,30 @@ ts2abc_gen_abc("ark_sample_abc") { out_puts = [ test_abc_path ] } +ts2abc_gen_abc("ark_asyncfunc_abc") { + test_js_path = "//ark/js_runtime/ecmascript/tooling/test/js/AsyncFunc.js" + test_abc_path = "$target_out_dir/AsyncFunc.abc" + extra_visibility = [ ":*" ] # Only targets in this file can depend on this. + src_js = rebase_path(test_js_path) + dst_file = rebase_path(test_abc_path) + extra_args = [ "--debug" ] + + in_puts = [ test_js_path ] + out_puts = [ test_abc_path ] +} + +ts2abc_gen_abc("ark_arrowfunc_abc") { + test_js_path = "//ark/js_runtime/ecmascript/tooling/test/js/ArrowFunc.js" + test_abc_path = "$target_out_dir/ArrowFunc.abc" + extra_visibility = [ ":*" ] # Only targets in this file can depend on this. + src_js = rebase_path(test_js_path) + dst_file = rebase_path(test_abc_path) + extra_args = [ "--debug" ] + + in_puts = [ test_js_path ] + out_puts = [ test_abc_path ] +} + ts2abc_gen_abc("ark_exception_abc") { test_js_path = "//ark/js_runtime/ecmascript/tooling/test/js/exception.js" test_abc_path = "$target_out_dir/exception.abc" @@ -62,6 +86,8 @@ source_set("debugger_entry_set") { public_configs = [ ":debug_api_test" ] deps = [ + ":ark_arrowfunc_abc", + ":ark_asyncfunc_abc", ":ark_exception_abc", ":ark_sample_abc", ":jsdebugtest", diff --git a/ecmascript/tooling/test/js/ArrowFunc.js b/ecmascript/tooling/test/js/ArrowFunc.js new file mode 100644 index 0000000000..75e9b5fabf --- /dev/null +++ b/ecmascript/tooling/test/js/ArrowFunc.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021 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. + */ + +var sum = (num1, num2) => { + num1 = num1 + 1; + print(num1); + num2 = num2 + 1; + print(num2); + return num1 + num2; + }; +print(sum(1,2)); \ No newline at end of file diff --git a/ecmascript/tooling/test/js/AsyncFunc.js b/ecmascript/tooling/test/js/AsyncFunc.js new file mode 100644 index 0000000000..f9c0ac6481 --- /dev/null +++ b/ecmascript/tooling/test/js/AsyncFunc.js @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 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. + */ + +async function helloAsync(){ + print ("helloAsync log 1"); + print ("helloAsync log 2"); + print ("helloAsync log 3"); + print ("helloAsync log 4"); + return "helloAsync"; +} + +print("main test 1"); +print(helloAsync()); +print("main test 2"); +print("main test 3"); + +helloAsync().then(v=>{ + print(v); + print("helloAsync then end!"); +}) +print("main test end!"); \ No newline at end of file diff --git a/ecmascript/tooling/test/utils/testcases/js_breakpoint_arrow_test.h b/ecmascript/tooling/test/utils/testcases/js_breakpoint_arrow_test.h new file mode 100644 index 0000000000..9ce610f248 --- /dev/null +++ b/ecmascript/tooling/test/utils/testcases/js_breakpoint_arrow_test.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 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. + */ + +#ifndef ECMASCRIPT_TOOLING_TEST_UTILS_TESTCASES_JS_BREAKPOINT_ARROW_TEST_H +#define ECMASCRIPT_TOOLING_TEST_UTILS_TESTCASES_JS_BREAKPOINT_ARROW_TEST_H + +#include "ecmascript/tooling/test/utils/test_util.h" + +namespace panda::ecmascript::tooling::test { +class JsBreakpointArrowTest : public TestEvents { +public: + JsBreakpointArrowTest() + { + vmStart = [this] { + location_ = TestUtil::GetLocation("ArrowFunc.js", 18, 0, pandaFile_.c_str()); // 18: breakpointer line + ASSERT_TRUE(location_.GetMethodId().IsValid()); + return true; + }; + + breakpoint = [this](const JSPtLocation &location) { + ASSERT_TRUE(location.GetMethodId().IsValid()); + ASSERT_LOCATION_EQ(location, location_); + ++breakpointCounter_; + TestUtil::SuspendUntilContinue(DebugEvent::BREAKPOINT, location); + return true; + }; + + loadModule = [this](std::string_view moduleName) { + if (flag_) { + if (moduleName != pandaFile_) { + return true; + } + ASSERT_TRUE(debugger_->NotifyScriptParsed(0, pandaFile_)); + flag_ = false; + auto condFuncRef = FunctionRef::Undefined(vm_); + auto ret = debugInterface_->SetBreakpoint(location_, condFuncRef); + ASSERT_TRUE(ret); + } + return true; + }; + + scenario = [this]() { + ASSERT_BREAKPOINT_SUCCESS(location_); + TestUtil::Continue(); + auto ret = debugInterface_->RemoveBreakpoint(location_); + ASSERT_TRUE(ret); + ASSERT_EXITED(); + return true; + }; + + vmDeath = [this]() { + ASSERT_EQ(breakpointCounter_, 1U); + return true; + }; + } + + std::pair GetEntryPoint() override + { + return {pandaFile_, entryPoint_}; + } + ~JsBreakpointArrowTest() = default; + +private: + CString pandaFile_ = DEBUGGER_ABC_DIR "ArrowFunc.abc"; + CString entryPoint_ = "_GLOBAL::func_main_0"; + JSPtLocation location_ {nullptr, JSPtLocation::EntityId(0), 0}; + size_t breakpointCounter_ = 0; + bool flag_ = true; +}; + +std::unique_ptr GetJsBreakpointArrowTest() +{ + return std::make_unique(); +} +} // namespace panda::ecmascript::tooling::test + +#endif // ECMASCRIPT_TOOLING_TEST_UTILS_TESTCASES_JS_BREAKPOINT_ARROW_TEST_H diff --git a/ecmascript/tooling/test/utils/testcases/js_breakpoint_async_test.h b/ecmascript/tooling/test/utils/testcases/js_breakpoint_async_test.h new file mode 100644 index 0000000000..07d32c8708 --- /dev/null +++ b/ecmascript/tooling/test/utils/testcases/js_breakpoint_async_test.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2021 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. + */ + +#ifndef ECMASCRIPT_TOOLING_TEST_UTILS_TESTCASES_JS_BREAKPOINT_ASYNC_TEST_H +#define ECMASCRIPT_TOOLING_TEST_UTILS_TESTCASES_JS_BREAKPOINT_ASYNC_TEST_H + +#include "ecmascript/tooling/test/utils/test_util.h" + +namespace panda::ecmascript::tooling::test { +class JsBreakpointAsyncTest : public TestEvents { +public: + JsBreakpointAsyncTest() + { + vmStart = [this] { + location_ = TestUtil::GetLocation("AsyncFunc.js", 18, 0, pandaFile_.c_str()); // 18: breakpointer line + ASSERT_TRUE(location_.GetMethodId().IsValid()); + return true; + }; + + breakpoint = [this](const JSPtLocation &location) { + ASSERT_TRUE(location.GetMethodId().IsValid()); + ASSERT_LOCATION_EQ(location, location_); + ++breakpointCounter_; + TestUtil::SuspendUntilContinue(DebugEvent::BREAKPOINT, location); + return true; + }; + + loadModule = [this](std::string_view moduleName) { + if (flag_) { + if (moduleName != pandaFile_) { + return true; + } + ASSERT_TRUE(debugger_->NotifyScriptParsed(0, pandaFile_)); + flag_ = false; + auto condFuncRef = FunctionRef::Undefined(vm_); + auto ret = debugInterface_->SetBreakpoint(location_, condFuncRef); + ASSERT_TRUE(ret); + } + return true; + }; + + scenario = [this]() { + ASSERT_BREAKPOINT_SUCCESS(location_); + TestUtil::Continue(); + ASSERT_BREAKPOINT_SUCCESS(location_); + TestUtil::Continue(); + auto ret = debugInterface_->RemoveBreakpoint(location_); + ASSERT_TRUE(ret); + ASSERT_EXITED(); + return true; + }; + + vmDeath = [this]() { + ASSERT_EQ(breakpointCounter_, 2U); + return true; + }; + } + + std::pair GetEntryPoint() override + { + return {pandaFile_, entryPoint_}; + } + ~JsBreakpointAsyncTest() = default; + +private: + CString pandaFile_ = DEBUGGER_ABC_DIR "AsyncFunc.abc"; + CString entryPoint_ = "_GLOBAL::func_main_0"; + JSPtLocation location_ {nullptr, JSPtLocation::EntityId(0), 0}; + size_t breakpointCounter_ = 0; + bool flag_ = true; +}; + +std::unique_ptr GetJsBreakpointAsyncTest() +{ + return std::make_unique(); +} +} // namespace panda::ecmascript::tooling::test + +#endif // ECMASCRIPT_TOOLING_TEST_UTILS_TESTCASES_JS_BREAKPOINT_ASYNC_TEST_H diff --git a/ecmascript/tooling/test/utils/testcases/test_list.cpp b/ecmascript/tooling/test/utils/testcases/test_list.cpp index 27b37ab8ec..430ac42f1b 100644 --- a/ecmascript/tooling/test/utils/testcases/test_list.cpp +++ b/ecmascript/tooling/test/utils/testcases/test_list.cpp @@ -19,6 +19,8 @@ // testcase list #include "js_breakpoint_test.h" +#include "js_breakpoint_arrow_test.h" +#include "js_breakpoint_async_test.h" #include "js_exception_test.h" #include "js_single_step_test.h" @@ -31,6 +33,8 @@ static void RegisterTests() TestUtil::RegisterTest("JsExceptionTest", GetJsExceptionTest()); TestUtil::RegisterTest("JsSingleStepTest", GetJsSingleStepTest()); TestUtil::RegisterTest("JsBreakpointTest", GetJsBreakpointTest()); + TestUtil::RegisterTest("JsBreakpointAsyncTest", GetJsBreakpointAsyncTest()); + TestUtil::RegisterTest("JsBreakpointArrowTest", GetJsBreakpointArrowTest()); } CVector GetTestList() From 4c6b65c7a7dc581c7ce67de709a61ad2f94de184 Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Thu, 2 Jun 2022 11:28:13 +0800 Subject: [PATCH 04/35] Descriptor: fix proxy bug details:SetMethod always is nullptr, set right method: CallJsProxy issue: https://gitee.com/openharmony/ark_js_runtime/issues/I5AIBR Signed-off-by: wengchangcheng Change-Id: Ia0fa992d302b9183a20faafeffbfce31f01cd072 --- ecmascript/file_loader.cpp | 4 ++-- ecmascript/js_function.h | 5 ----- ecmascript/js_proxy.h | 5 ----- ecmascript/object_factory.cpp | 28 ++++++++++-------------- ecmascript/tests/native_pointer_test.cpp | 2 +- test/moduletest/BUILD.gn | 2 ++ test/moduletest/proxy/BUILD.gn | 18 +++++++++++++++ test/moduletest/proxy/expect_output.txt | 16 ++++++++++++++ test/moduletest/proxy/proxy.js | 28 ++++++++++++++++++++++++ 9 files changed, 79 insertions(+), 29 deletions(-) create mode 100644 test/moduletest/proxy/BUILD.gn create mode 100644 test/moduletest/proxy/expect_output.txt create mode 100644 test/moduletest/proxy/proxy.js diff --git a/ecmascript/file_loader.cpp b/ecmascript/file_loader.cpp index 814b76b9db..ef23df778f 100644 --- a/ecmascript/file_loader.cpp +++ b/ecmascript/file_loader.cpp @@ -262,7 +262,7 @@ void FileLoader::UpdateJSMethods(JSHandle mainFunc, const JSPandaFil auto mainEntry = GetAOTFuncEntry(fileHash, mainFuncMethodId); // 1 : default para number JSMethod *mainMethod = factory_->NewMethodForAOTFunction(reinterpret_cast(mainEntry), 1); - mainFunc->SetCallTarget(thread, mainMethod); + mainFunc->SetMethod(mainMethod); mainFunc->SetCodeEntry(reinterpret_cast(mainEntry)); const CUnorderedMap &constpoolMap = jsPandaFile->GetConstpoolMap(); @@ -277,7 +277,7 @@ void FileLoader::UpdateJSMethods(JSHandle mainFunc, const JSPandaFil auto codeEntry = GetAOTFuncEntry(fileHash, it.first); JSMethod *curMethod = factory_->NewMethodForAOTFunction(reinterpret_cast(codeEntry), 1); auto curFunction = JSFunction::Cast(curPool->GetObjectFromCache(id).GetTaggedObject()); - curFunction->SetCallTarget(thread, curMethod); + curFunction->SetMethod(curMethod); curFunction->SetCodeEntry(reinterpret_cast(codeEntry)); } } diff --git a/ecmascript/js_function.h b/ecmascript/js_function.h index 663c6e0cf4..d9c25f827b 100644 --- a/ecmascript/js_function.h +++ b/ecmascript/js_function.h @@ -39,11 +39,6 @@ public: const JSHandle &name, const JSHandle &prefix); static JSHandle GetFunctionName(JSThread *thread, const JSHandle &func); - void SetCallTarget([[maybe_unused]] const JSThread *thread, JSMethod *p) - { - SetMethod(p); - } - static constexpr size_t METHOD_OFFSET = JSObject::SIZE; ACCESSORS_NATIVE_FIELD(Method, JSMethod, METHOD_OFFSET, CODE_ENTRY_OFFSET) ACCESSORS_PRIMITIVE_FIELD(CodeEntry, uintptr_t, CODE_ENTRY_OFFSET, LAST_OFFSET) diff --git a/ecmascript/js_proxy.h b/ecmascript/js_proxy.h index d2d33d465a..14f474e8fd 100644 --- a/ecmascript/js_proxy.h +++ b/ecmascript/js_proxy.h @@ -77,11 +77,6 @@ public: GetClass()->SetConstructor(constructor); } - void SetCallTarget([[maybe_unused]] const JSThread *thread, JSMethod *p) - { - SetMethod(p); - } - JSHandle GetSourceTarget(JSThread *thread) const; // ES6 9.5.13 [[Call]] (thisArgument, argumentsList) diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index cf58710370..b7a4370d0c 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -1344,7 +1344,7 @@ JSHandle ObjectFactory::NewJSFunctionByDynClass(JSMethod *method, co clazz->SetCallable(true); clazz->SetExtensible(true); JSFunction::InitializeJSFunction(thread_, function, kind); - function->SetCallTarget(thread_, method); + function->SetMethod(method); return function; } @@ -1355,7 +1355,7 @@ JSHandle ObjectFactory::NewJSFunctionByDynClass(const void *func, co clazz->SetCallable(true); clazz->SetExtensible(true); JSFunction::InitializeJSFunction(thread_, function, kind); - function->SetCallTarget(thread_, NewMethodForNativeFunction(func)); + function->SetMethod(NewMethodForNativeFunction(func)); return function; } @@ -1403,7 +1403,7 @@ JSHandle ObjectFactory::NewJSBoundFunction(const JSHandleSetConstructor(true); } JSMethod *method = GetMethodByIndex(MethodIndex::BUILTINS_GLOBAL_CALL_JS_BOUND_FUNCTION); - bundleFunction->SetCallTarget(thread_, method); + bundleFunction->SetMethod(method); return bundleFunction; } @@ -1416,7 +1416,7 @@ JSHandle ObjectFactory::NewJSIntlBoundFunction(MethodIndex intlBoundFunc->SetNumberFormat(JSTaggedValue::Undefined()); intlBoundFunc->SetDateTimeFormat(JSTaggedValue::Undefined()); intlBoundFunc->SetCollator(JSTaggedValue::Undefined()); - intlBoundFunc->SetCallTarget(thread_, GetMethodByIndex(idx)); + intlBoundFunc->SetMethod(GetMethodByIndex(idx)); JSHandle function = JSHandle::Cast(intlBoundFunc); JSFunction::InitializeJSFunction(thread_, function, FunctionKind::NORMAL_FUNCTION); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(functionLength)); @@ -1437,7 +1437,7 @@ JSHandle ObjectFactory::NewJSProxyRevocFunction(const JSHa JSHandle revocFunction = JSHandle::Cast(NewJSObject(dynclass)); revocFunction->SetRevocableProxy(JSTaggedValue::Undefined()); revocFunction->SetRevocableProxy(thread_, proxy); - revocFunction->SetCallTarget(thread_, GetMethodByIndex(MethodIndex::BUILTINS_PROXY_INVALIDATE_PROXY_FUNCTION)); + revocFunction->SetMethod(GetMethodByIndex(MethodIndex::BUILTINS_PROXY_INVALIDATE_PROXY_FUNCTION)); JSHandle function = JSHandle::Cast(revocFunction); JSFunction::InitializeJSFunction(thread_, function, FunctionKind::NORMAL_FUNCTION); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(0)); @@ -1457,7 +1457,7 @@ JSHandle ObjectFactory::NewJSAsyncAwaitStatusFunctio JSHandle::Cast(NewJSObject(dynclass)); awaitFunction->SetAsyncContext(JSTaggedValue::Undefined()); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(awaitFunction)); - awaitFunction->SetCallTarget(thread_, GetMethodByIndex(idx)); + awaitFunction->SetMethod(GetMethodByIndex(idx)); return awaitFunction; } @@ -1468,7 +1468,7 @@ JSHandle ObjectFactory::NewJSGeneratorFunction(JSMethod *method) JSHandle dynclass = JSHandle::Cast(env->GetGeneratorFunctionClass()); JSHandle generatorFunc = JSHandle::Cast(NewJSObject(dynclass)); JSFunction::InitializeJSFunction(thread_, generatorFunc, FunctionKind::GENERATOR_FUNCTION); - generatorFunc->SetCallTarget(thread_, method); + generatorFunc->SetMethod(method); return generatorFunc; } @@ -1492,7 +1492,7 @@ JSHandle ObjectFactory::NewAsyncFunction(JSMethod *method) JSHandle dynclass = JSHandle::Cast(env->GetAsyncFunctionClass()); JSHandle asyncFunction = JSHandle::Cast(NewJSObject(dynclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(asyncFunction)); - asyncFunction->SetCallTarget(thread_, method); + asyncFunction->SetMethod(method); return asyncFunction; } @@ -1817,11 +1817,7 @@ JSHandle ObjectFactory::NewJSProxy(const JSHandle &targe } JSHandle proxy(thread_, header); - JSMethod *method = nullptr; - if (target->IsCallable()) { - JSMethod *nativeMethod = GetMethodByIndex(MethodIndex::BUILTINS_GLOBAL_CALL_JS_PROXY); - proxy->SetCallTarget(thread_, nativeMethod); - } + JSMethod *method = GetMethodByIndex(MethodIndex::BUILTINS_GLOBAL_CALL_JS_PROXY); proxy->SetMethod(method); proxy->SetTarget(thread_, target.GetTaggedValue()); @@ -2318,7 +2314,7 @@ JSHandle ObjectFactory::CreateJSPromiseReactionsFunc JSHandle::Cast(NewJSObject(dynclass)); reactionsFunction->SetPromise(thread_, JSTaggedValue::Hole()); reactionsFunction->SetAlreadyResolved(thread_, JSTaggedValue::Hole()); - reactionsFunction->SetCallTarget(thread_, GetMethodByIndex(idx)); + reactionsFunction->SetMethod(GetMethodByIndex(idx)); JSHandle function = JSHandle::Cast(reactionsFunction); JSFunction::InitializeJSFunction(thread_, function); JSFunction::SetFunctionLength(thread_, function, JSTaggedValue(1)); @@ -2332,7 +2328,7 @@ JSHandle ObjectFactory::CreateJSPromiseExecutorFuncti JSHandle executorFunction = JSHandle::Cast(NewJSObject(dynclass)); executorFunction->SetCapability(thread_, JSTaggedValue::Hole()); - executorFunction->SetCallTarget(thread_, GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_EXECUTOR)); + executorFunction->SetMethod(GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_EXECUTOR)); executorFunction->SetCapability(thread_, JSTaggedValue::Undefined()); JSHandle function = JSHandle::Cast(executorFunction); JSFunction::InitializeJSFunction(thread_, function, FunctionKind::NORMAL_FUNCTION); @@ -2347,7 +2343,7 @@ JSHandle ObjectFactory::NewJSPromiseAllResol JSHandle function = JSHandle::Cast(NewJSObject(dynclass)); JSFunction::InitializeJSFunction(thread_, JSHandle::Cast(function)); - function->SetCallTarget(thread_, GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_RESOLVE_ELEMENT_FUNCTION)); + function->SetMethod(GetMethodByIndex(MethodIndex::BUILTINS_PROMISE_HANDLER_RESOLVE_ELEMENT_FUNCTION)); function->SetIndex(JSTaggedValue::Undefined()); function->SetValues(JSTaggedValue::Undefined()); function->SetCapabilities(JSTaggedValue::Undefined()); diff --git a/ecmascript/tests/native_pointer_test.cpp b/ecmascript/tests/native_pointer_test.cpp index f7660649ff..3700f3ae07 100644 --- a/ecmascript/tests/native_pointer_test.cpp +++ b/ecmascript/tests/native_pointer_test.cpp @@ -67,7 +67,7 @@ HWTEST_F_L0(NativePointerTest, Print) EXPECT_TRUE(*jsFunction != nullptr); JSMethod *target = factory->NewMethodForNativeFunction(nullptr); - jsFunction->SetCallTarget(thread, target); + jsFunction->SetMethod(target); // run cpp methed 'Print' ASSERT_EQ(target, jsFunction->GetCallTarget()); diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index 57a2b14f59..f0cfc60371 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -37,6 +37,7 @@ group("ark_js_moduletest") { "newobjdynrange:newobjdynrangeAction", "objectcloneproperties:objectclonepropertiesAction", "promise:promiseAction", + "proxy:proxyAction", "regexpcallthrow:regexpcallthrowAction", "spreadoperator:spreadoperatorAction", "stackoverflow:stackoverflowAction", @@ -77,6 +78,7 @@ group("ark_asm_test") { "newobjdynrange:newobjdynrangeAsmAction", "objectcloneproperties:objectclonepropertiesAsmAction", "promise:promiseAsmAction", + "proxy:proxyAsmAction", "regexpcallthrow:regexpcallthrowAsmAction", "spreadoperator:spreadoperatorAsmAction", "stackoverflow:stackoverflowAsmAction", diff --git a/test/moduletest/proxy/BUILD.gn b/test/moduletest/proxy/BUILD.gn new file mode 100644 index 0000000000..cd3688f254 --- /dev/null +++ b/test/moduletest/proxy/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright (c) 2021 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_moduletest_action("proxy") { + deps = [] +} diff --git a/test/moduletest/proxy/expect_output.txt b/test/moduletest/proxy/expect_output.txt new file mode 100644 index 0000000000..d9b6bf26f9 --- /dev/null +++ b/test/moduletest/proxy/expect_output.txt @@ -0,0 +1,16 @@ +# Copyright (c) 2021 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. + +true +true +true diff --git a/test/moduletest/proxy/proxy.js b/test/moduletest/proxy/proxy.js new file mode 100644 index 0000000000..d0ef4d4ec0 --- /dev/null +++ b/test/moduletest/proxy/proxy.js @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 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. + */ + +function add(a, b) { + return a + b +} + +let addProxy = new Proxy(add, { + apply: function(target, thisObj, args) { + return target.apply(thisObj, args) + } +}) + +for (var a = 1; a < 4; a++) { + print(addProxy(a, 12345 * a) == add(12345 * a, a)) +} From 3bc6dcb73105707f8a2bd43b4964ac253ec2b403 Mon Sep 17 00:00:00 2001 From: chenqi Date: Thu, 2 Jun 2022 09:11:52 +0800 Subject: [PATCH 05/35] Add Containers List And LinkedList Description 1.To ensure the high performance of container classes, List and LinkedList is provided in ark. 2.modify Copyright 2021->2022. 3.fix containers. Related issue #I58XA9:Add Containers List And LinkedList. Signed-off-by: chenqi --- BUILD.gn | 7 + .../containers/containers_arraylist.cpp | 11 +- .../containers/containers_linked_list.cpp | 428 +++++++++++ .../containers/containers_linked_list.h | 51 ++ ecmascript/containers/containers_list.cpp | 409 +++++++++++ ecmascript/containers/containers_list.h | 49 ++ .../containers/containers_plainarray.cpp | 14 +- ecmascript/containers/containers_private.cpp | 167 ++++- ecmascript/containers/containers_private.h | 4 + ecmascript/containers/tests/BUILD.gn | 2 + .../tests/containers_linked_list_test.cpp | 453 ++++++++++++ .../containers/tests/containers_list_test.cpp | 461 ++++++++++++ ecmascript/dfx/hprof/heap_snapshot.cpp | 4 + ecmascript/dump.cpp | 194 ++++- ecmascript/global_env_constants.cpp | 11 + ecmascript/global_env_constants.h | 6 + ecmascript/ic/ic_runtime.cpp | 2 +- .../interpreter/fast_runtime_stub-inl.h | 26 +- ecmascript/js_api_arraylist.cpp | 36 +- ecmascript/js_api_arraylist.h | 10 +- ecmascript/js_api_arraylist_iterator.cpp | 2 +- ecmascript/js_api_arraylist_iterator.h | 2 +- ecmascript/js_api_deque.cpp | 22 +- ecmascript/js_api_deque.h | 6 +- ecmascript/js_api_deque_iterator.cpp | 14 +- ecmascript/js_api_linked_list.cpp | 234 ++++++ ecmascript/js_api_linked_list.h | 72 ++ ecmascript/js_api_linked_list_iterator.cpp | 66 ++ ecmascript/js_api_linked_list_iterator.h | 43 ++ ecmascript/js_api_list.cpp | 218 ++++++ ecmascript/js_api_list.h | 75 ++ ecmascript/js_api_list_iterator.cpp | 63 ++ ecmascript/js_api_list_iterator.h | 43 ++ ecmascript/js_api_plain_array.cpp | 14 +- ecmascript/js_api_plain_array.h | 2 +- ecmascript/js_api_queue.cpp | 38 +- ecmascript/js_api_queue.h | 7 +- ecmascript/js_api_queue_iterator.cpp | 2 +- ecmascript/js_api_queue_iterator.h | 2 +- ecmascript/js_api_stack.cpp | 23 +- ecmascript/js_api_stack.h | 6 +- ecmascript/js_api_tree_map.cpp | 2 +- ecmascript/js_api_tree_map.h | 2 +- ecmascript/js_api_tree_map_iterator.cpp | 2 +- ecmascript/js_api_tree_map_iterator.h | 2 +- ecmascript/js_api_tree_set.cpp | 2 +- ecmascript/js_api_tree_set.h | 2 +- ecmascript/js_api_tree_set_iterator.cpp | 2 +- ecmascript/js_api_tree_set_iterator.h | 2 +- ecmascript/js_api_vector.cpp | 9 +- ecmascript/js_api_vector.h | 3 +- ecmascript/js_hclass.h | 23 +- ecmascript/js_object-inl.h | 10 + ecmascript/js_object.h | 2 + ecmascript/js_tagged_value-inl.h | 20 + ecmascript/js_tagged_value.cpp | 107 ++- ecmascript/js_tagged_value.h | 4 + ecmascript/mem/object_xray.h | 16 + ecmascript/object_factory.cpp | 74 +- ecmascript/object_factory.h | 12 +- ecmascript/runtime_call_id.h | 47 +- .../snapshot/mem/snapshot_processor.cpp | 53 +- ecmascript/tagged_list.cpp | 684 ++++++++++++++++++ ecmascript/tagged_list.h | 190 +++++ ecmascript/tagged_tree.cpp | 2 +- ecmascript/tagged_tree.h | 2 +- ecmascript/tests/BUILD.gn | 2 + ecmascript/tests/dump_test.cpp | 58 ++ ecmascript/tests/js_api_arraylist_test.cpp | 3 +- ecmascript/tests/js_api_deque_test.cpp | 23 + ecmascript/tests/js_api_linked_list_test.cpp | 338 +++++++++ ecmascript/tests/js_api_list_test.cpp | 303 ++++++++ ecmascript/tests/js_api_plain_array_test.cpp | 25 + ecmascript/tests/js_api_queue_test.cpp | 5 +- ecmascript/tests/js_api_stack_test.cpp | 22 + ecmascript/tests/js_api_tree_map_test.cpp | 2 +- ecmascript/tests/js_api_tree_set_test.cpp | 2 +- ecmascript/tests/js_api_vector_test.cpp | 22 + ecmascript/tests/tagged_tree_test.cpp | 2 +- test/moduletest/container/BUILD.gn | 14 +- test/moduletest/container/container.js | 2 +- .../container/container_arraylist.js | 2 +- .../container/container_linked_list.js | 130 ++++ test/moduletest/container/container_list.js | 160 ++++ .../moduletest/container/container_treemap.js | 2 +- .../moduletest/container/container_treeset.js | 2 +- test/moduletest/container/expect_output.txt | 48 +- 87 files changed, 5580 insertions(+), 160 deletions(-) create mode 100644 ecmascript/containers/containers_linked_list.cpp create mode 100644 ecmascript/containers/containers_linked_list.h create mode 100644 ecmascript/containers/containers_list.cpp create mode 100644 ecmascript/containers/containers_list.h create mode 100644 ecmascript/containers/tests/containers_linked_list_test.cpp create mode 100644 ecmascript/containers/tests/containers_list_test.cpp create mode 100644 ecmascript/js_api_linked_list.cpp create mode 100644 ecmascript/js_api_linked_list.h create mode 100644 ecmascript/js_api_linked_list_iterator.cpp create mode 100644 ecmascript/js_api_linked_list_iterator.h create mode 100644 ecmascript/js_api_list.cpp create mode 100644 ecmascript/js_api_list.h create mode 100644 ecmascript/js_api_list_iterator.cpp create mode 100644 ecmascript/js_api_list_iterator.h create mode 100644 ecmascript/tagged_list.cpp create mode 100644 ecmascript/tagged_list.h create mode 100644 ecmascript/tests/js_api_linked_list_test.cpp create mode 100644 ecmascript/tests/js_api_list_test.cpp create mode 100644 test/moduletest/container/container_linked_list.js create mode 100644 test/moduletest/container/container_list.js diff --git a/BUILD.gn b/BUILD.gn index e9d50c9294..ed3ef2a831 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -346,6 +346,8 @@ ecma_source = [ "ecmascript/builtins/builtins_weak_set.cpp", "ecmascript/containers/containers_arraylist.cpp", "ecmascript/containers/containers_deque.cpp", + "ecmascript/containers/containers_linked_list.cpp", + "ecmascript/containers/containers_list.cpp", "ecmascript/containers/containers_plainarray.cpp", "ecmascript/containers/containers_private.cpp", "ecmascript/containers/containers_queue.cpp", @@ -391,6 +393,10 @@ ecma_source = [ "ecmascript/js_api_arraylist_iterator.cpp", "ecmascript/js_api_deque.cpp", "ecmascript/js_api_deque_iterator.cpp", + "ecmascript/js_api_linked_list.cpp", + "ecmascript/js_api_linked_list_iterator.cpp", + "ecmascript/js_api_list.cpp", + "ecmascript/js_api_list_iterator.cpp", "ecmascript/js_api_plain_array.cpp", "ecmascript/js_api_plain_array_iterator.cpp", "ecmascript/js_api_queue.cpp", @@ -477,6 +483,7 @@ ecma_source = [ "ecmascript/regexp/regexp_parser_cache.cpp", "ecmascript/shared_mm/shared_mm.cpp", "ecmascript/tagged_dictionary.cpp", + "ecmascript/tagged_list.cpp", "ecmascript/tagged_tree.cpp", "ecmascript/template_string.cpp", "ecmascript/weak_vector.cpp", diff --git a/ecmascript/containers/containers_arraylist.cpp b/ecmascript/containers/containers_arraylist.cpp index 6e3ce2dc52..e9fee8f055 100644 --- a/ecmascript/containers/containers_arraylist.cpp +++ b/ecmascript/containers/containers_arraylist.cpp @@ -76,10 +76,11 @@ JSTaggedValue ContainersArrayList::Insert(EcmaRuntimeCallInfo *argv) JSHandle value = GetCallArg(argv, 0); JSHandle index = GetCallArg(argv, 1); - if (!index->IsNumber()) { + if (!index->IsInteger()) { THROW_TYPE_ERROR_AND_RETURN(thread, "index is not Integer", JSTaggedValue::Exception()); } JSAPIArrayList::Insert(thread, JSHandle::Cast(self), value, JSTaggedValue::ToUint32(thread, index)); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); return JSTaggedValue::Undefined(); } @@ -166,7 +167,7 @@ JSTaggedValue ContainersArrayList::IncreaseCapacityTo(EcmaRuntimeCallInfo *argv) } JSHandle newCapacity = GetCallArg(argv, 0); - if (!newCapacity->IsNumber()) { + if (!newCapacity->IsInteger()) { THROW_TYPE_ERROR_AND_RETURN(thread, "newCapacity is not Integer", JSTaggedValue::Exception()); } @@ -274,7 +275,7 @@ JSTaggedValue ContainersArrayList::RemoveByIndex(EcmaRuntimeCallInfo *argv) } JSHandle value = GetCallArg(argv, 0); - if (!value->IsNumber()) { + if (!value->IsInteger()) { THROW_TYPE_ERROR_AND_RETURN(thread, "index is not Integer", JSTaggedValue::Exception()); } @@ -318,7 +319,7 @@ JSTaggedValue ContainersArrayList::RemoveByRange(EcmaRuntimeCallInfo *argv) JSHandle startIndex = GetCallArg(argv, 0); JSHandle endIndex = GetCallArg(argv, 1); - if (!startIndex->IsNumber() || !endIndex->IsNumber()) { + if (!startIndex->IsInteger() || !endIndex->IsInteger()) { THROW_TYPE_ERROR_AND_RETURN(thread, "startIndex or endIndex is not Integer", JSTaggedValue::Exception()); } JSAPIArrayList::RemoveByRange(thread, JSHandle::Cast(self), startIndex, endIndex); @@ -382,7 +383,7 @@ JSTaggedValue ContainersArrayList::SubArrayList(EcmaRuntimeCallInfo *argv) JSHandle value1 = GetCallArg(argv, 0); JSHandle value2 = GetCallArg(argv, 1); - if (!value1->IsNumber() || !value2->IsNumber()) { + if (!value1->IsInteger() || !value2->IsInteger()) { THROW_TYPE_ERROR_AND_RETURN(thread, "startIndex or endIndex is not Integer", JSTaggedValue::Exception()); } JSHandle newArrayList = diff --git a/ecmascript/containers/containers_linked_list.cpp b/ecmascript/containers/containers_linked_list.cpp new file mode 100644 index 0000000000..45b0fa9aa7 --- /dev/null +++ b/ecmascript/containers/containers_linked_list.cpp @@ -0,0 +1,428 @@ +/* + * 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. + */ + +#include "containers_linked_list.h" +#include "ecmascript/ecma_vm.h" +#include "ecmascript/interpreter/interpreter.h" +#include "ecmascript/js_api_linked_list.h" +#include "ecmascript/js_api_linked_list_iterator.h" +#include "ecmascript/js_function.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/tagged_array-inl.h" +#include "ecmascript/tagged_list.h" + +namespace panda::ecmascript::containers { +JSTaggedValue ContainersLinkedList::LinkedListConstructor(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, Constructor); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle newTarget = GetNewTarget(argv); + if (newTarget->IsUndefined()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "new target can't be undefined", JSTaggedValue::Exception()); + } + JSHandle constructor = GetConstructor(argv); + JSHandle obj = factory->NewJSObjectByConstructor(JSHandle(constructor), newTarget); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + JSHandle linkedList = JSHandle::Cast(obj); + JSTaggedValue doubleList = TaggedDoubleList::Create(thread); + linkedList->SetDoubleList(thread, doubleList); + return linkedList.GetTaggedValue(); +} + +JSTaggedValue ContainersLinkedList::Add(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, Add); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + + JSHandle value = GetCallArg(argv, 0); + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSAPILinkedList::Add(thread, jsAPILinkedList, value); + return JSTaggedValue::True(); +} + +JSTaggedValue ContainersLinkedList::AddFirst(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, AddFirst); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + + JSHandle value = GetCallArg(argv, 0); + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSAPILinkedList::AddFirst(thread, jsAPILinkedList, value); + return JSTaggedValue::True(); +} + +JSTaggedValue ContainersLinkedList::GetFirst(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, GetFirst); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + return jsAPILinkedList->GetFirst(); +} + +JSTaggedValue ContainersLinkedList::GetLast(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, GetLast); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + return jsAPILinkedList->GetLast(); +} + +JSTaggedValue ContainersLinkedList::Length(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, Length); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + return JSTaggedValue(jsAPILinkedList->Length()); +} + +JSTaggedValue ContainersLinkedList::Insert(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, Insert); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + + JSHandle value = GetCallArg(argv, 1); + JSHandle index = GetCallArg(argv, 0); + + if (!index->IsInteger()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "the index is not integer", JSTaggedValue::Exception()); + } + + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSTaggedValue result = + JSAPILinkedList::Insert(thread, jsAPILinkedList, value, index->GetInt()); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return result; +} + +JSTaggedValue ContainersLinkedList::Clear(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, Clear); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + jsAPILinkedList->Clear(thread); + return JSTaggedValue::Undefined(); +} + +JSTaggedValue ContainersLinkedList::Clone(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, Clone); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSHandle newLinkedList = JSAPILinkedList::Clone(thread, jsAPILinkedList); + return newLinkedList.GetTaggedValue(); +} + +JSTaggedValue ContainersLinkedList::Has(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, Has); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSHandle element = GetCallArg(argv, 0); + return GetTaggedBoolean(jsAPILinkedList->Has(element.GetTaggedValue())); +} + +JSTaggedValue ContainersLinkedList::Get(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, Get); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSHandle index = GetCallArg(argv, 0); + if (!index->IsInteger()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "the index is not integer", JSTaggedValue::Exception()); + } + return jsAPILinkedList->Get(index->GetInt()); +} + +JSTaggedValue ContainersLinkedList::GetIndexOf(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, GetIndexOf); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSHandle element = GetCallArg(argv, 0); + return jsAPILinkedList->GetIndexOf(element.GetTaggedValue()); +} + +JSTaggedValue ContainersLinkedList::GetLastIndexOf(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, GetLastIndexOf); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSHandle element(GetCallArg(argv, 0)); + return jsAPILinkedList->GetLastIndexOf(element.GetTaggedValue()); +} + +JSTaggedValue ContainersLinkedList::RemoveByIndex(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, RemoveByIndex); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle index = GetCallArg(argv, 0); + if (!index->IsInteger()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "the index is not integer", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSTaggedValue nodeData = + JSAPILinkedList::RemoveByIndex(thread, jsAPILinkedList, index->GetInt()); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return nodeData; +} + +JSTaggedValue ContainersLinkedList::Remove(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, Remove); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle element = GetCallArg(argv, 0); + JSHandle jsAPILinkedList = JSHandle::Cast(self); + return jsAPILinkedList->Remove(thread, element.GetTaggedValue()); +} + +JSTaggedValue ContainersLinkedList::RemoveFirst(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, RemoveFirst); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSTaggedValue lastValue = JSAPILinkedList::RemoveFirst(thread, jsAPILinkedList); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return lastValue; +} + +JSTaggedValue ContainersLinkedList::RemoveFirstFound(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, RemoveFirstFound); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle element = GetCallArg(argv, 0); + + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSTaggedValue result = JSAPILinkedList::RemoveFirstFound(thread, jsAPILinkedList, element.GetTaggedValue()); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return result; +} + +JSTaggedValue ContainersLinkedList::RemoveLast(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, RemoveLast); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSTaggedValue lastValue = JSAPILinkedList::RemoveLast(thread, jsAPILinkedList); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return lastValue; +} + +JSTaggedValue ContainersLinkedList::RemoveLastFound(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, RemoveLastFound); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle element = GetCallArg(argv, 0); + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSTaggedValue result = JSAPILinkedList::RemoveLastFound(thread, jsAPILinkedList, element.GetTaggedValue()); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return result; +} + +JSTaggedValue ContainersLinkedList::Set(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, Set); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle index = GetCallArg(argv, 0); + JSHandle element = GetCallArg(argv, 1); + if (!index->IsInteger()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "the index is not integer", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + JSTaggedValue oldValue = + JSAPILinkedList::Set(thread, jsAPILinkedList, index->GetInt(), element); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return oldValue; +} + +JSTaggedValue ContainersLinkedList::ConvertToArray(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, ConvertToArray); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + JSHandle jsAPILinkedList = JSHandle::Cast(self); + return JSAPILinkedList::ConvertToArray(thread, jsAPILinkedList); +} + +JSTaggedValue ContainersLinkedList::ForEach(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, ForEach); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle thisHandle = GetThis(argv); + if (!thisHandle->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", JSTaggedValue::Exception()); + } + + JSHandle callbackFnHandle(GetCallArg(argv, 0)); + if (!callbackFnHandle->IsCallable()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "The first arg is not Callable", JSTaggedValue::Exception()); + } + + JSHandle thisArgHandle = GetCallArg(argv, 1); + JSHandle linkedList = JSHandle::Cast(thisHandle); + JSHandle doubleList(thread, linkedList->GetDoubleList()); + int length = linkedList->Length(); + + int index = 0; + const uint32_t argsLength = 3; // 3: «kValue, k, O» + JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); + while (index < length) { + JSTaggedValue value = doubleList->Get(index); + EcmaRuntimeCallInfo info = + EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); + info.SetCallArg(value, JSTaggedValue(index), thisHandle.GetTaggedValue()); + JSTaggedValue funcResult = JSFunction::Call(&info); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult); + index++; + } + return JSTaggedValue::Undefined(); +} + +JSTaggedValue ContainersLinkedList::GetIteratorObj(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, LinkedList, GetIteratorObj); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + JSHandle iter = JSAPILinkedListIterator::CreateLinkedListIterator(thread, self); + return iter.GetTaggedValue(); +} +} // namespace panda::ecmascript::containers diff --git a/ecmascript/containers/containers_linked_list.h b/ecmascript/containers/containers_linked_list.h new file mode 100644 index 0000000000..bab0d27a64 --- /dev/null +++ b/ecmascript/containers/containers_linked_list.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef ECMASCRIPT_CONTAINERS_CONTAINERS_LINKED_LIST_H +#define ECMASCRIPT_CONTAINERS_CONTAINERS_LINKED_LIST_H + +#include "ecmascript/base/builtins_base.h" +#include "ecmascript/ecma_runtime_call_info.h" + +namespace panda::ecmascript::containers { +class ContainersLinkedList : public base::BuiltinsBase { +public: + static JSTaggedValue LinkedListConstructor(EcmaRuntimeCallInfo *argv); + + static JSTaggedValue Add(EcmaRuntimeCallInfo *argv); + static JSTaggedValue GetFirst(EcmaRuntimeCallInfo *argv); + static JSTaggedValue GetLast(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Insert(EcmaRuntimeCallInfo *argv); + static JSTaggedValue AddFirst(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Clear(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Clone(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Has(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Get(EcmaRuntimeCallInfo *argv); + static JSTaggedValue GetIndexOf(EcmaRuntimeCallInfo *argv); + static JSTaggedValue GetLastIndexOf(EcmaRuntimeCallInfo *argv); + static JSTaggedValue RemoveByIndex(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Remove(EcmaRuntimeCallInfo *argv); + static JSTaggedValue RemoveFirst(EcmaRuntimeCallInfo *argv); + static JSTaggedValue RemoveFirstFound(EcmaRuntimeCallInfo *argv); + static JSTaggedValue RemoveLast(EcmaRuntimeCallInfo *argv); + static JSTaggedValue RemoveLastFound(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Set(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Length(EcmaRuntimeCallInfo *argv); + static JSTaggedValue ConvertToArray(EcmaRuntimeCallInfo *argv); + static JSTaggedValue ForEach(EcmaRuntimeCallInfo *argv); + static JSTaggedValue GetIteratorObj(EcmaRuntimeCallInfo *argv); +}; +} // namespace panda::ecmascript::containers +#endif // ECMASCRIPT_CONTAINERS_CONTAINERS_LINKED_LIST_H diff --git a/ecmascript/containers/containers_list.cpp b/ecmascript/containers/containers_list.cpp new file mode 100644 index 0000000000..5fdfbc0a7c --- /dev/null +++ b/ecmascript/containers/containers_list.cpp @@ -0,0 +1,409 @@ +/* + * 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. + */ + +#include "containers_list.h" +#include "ecmascript/ecma_vm.h" +#include "ecmascript/interpreter/interpreter.h" +#include "ecmascript/js_api_list.h" +#include "ecmascript/js_api_list_iterator.h" +#include "ecmascript/js_function.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/tagged_array-inl.h" +#include "ecmascript/tagged_list.h" + +namespace panda::ecmascript::containers { +JSTaggedValue ContainersList::ListConstructor(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, Constructor); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle newTarget = GetNewTarget(argv); + if (newTarget->IsUndefined()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "new target can't be undefined", JSTaggedValue::Exception()); + } + JSHandle constructor = GetConstructor(argv); + JSHandle obj = factory->NewJSObjectByConstructor(JSHandle(constructor), newTarget); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + JSHandle list = JSHandle::Cast(obj); + + JSTaggedValue singleList = TaggedSingleList::Create(thread); + list->SetSingleList(thread, singleList); + + return list.GetTaggedValue(); +} + +JSTaggedValue ContainersList::Add(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, Add); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + + JSHandle value = GetCallArg(argv, 0); + JSHandle jSAPIList = JSHandle::Cast(self); + JSAPIList::Add(thread, jSAPIList, value); + return JSTaggedValue::True(); +} + +JSTaggedValue ContainersList::Insert(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, Insert); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + JSHandle value = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + if (!index->IsInteger()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "index is not integer", JSTaggedValue::Exception()); + } + JSHandle jSAPIList = JSHandle::Cast(self); + JSAPIList::Insert(thread, jSAPIList, value, index->GetInt()); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return JSTaggedValue::True(); +} + +JSTaggedValue ContainersList::GetFirst(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, GetFirst); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + JSHandle jSAPIList = JSHandle::Cast(self); + return jSAPIList->GetFirst(); +} + +JSTaggedValue ContainersList::GetLast(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, GetLast); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + JSHandle jSAPIList = JSHandle::Cast(self); + return jSAPIList->GetLast(); +} + +JSTaggedValue ContainersList::Has(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, Has); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + JSHandle jSAPIList = JSHandle::Cast(self); + JSHandle element= GetCallArg(argv, 0); + return GetTaggedBoolean(jSAPIList->Has(element.GetTaggedValue())); +} + +JSTaggedValue ContainersList::IsEmpty(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, IsEmpty); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + JSHandle jSAPIList = JSHandle::Cast(self); + return GetTaggedBoolean(jSAPIList->IsEmpty()); +} + +JSTaggedValue ContainersList::Get(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, Get); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + JSHandle jsAPIList = JSHandle::Cast(self); + JSHandle index = GetCallArg(argv, 0); + if (!index->IsInteger()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "index is not integer", JSTaggedValue::Exception()); + } + return jsAPIList->Get(index->GetInt()); +} + +JSTaggedValue ContainersList::GetIndexOf(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, GetIndexOf); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + JSHandle jsAPIList = JSHandle::Cast(self); + JSHandle element = GetCallArg(argv, 0); + return jsAPIList->GetIndexOf(element.GetTaggedValue()); +} + +JSTaggedValue ContainersList::GetLastIndexOf(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, GetLastIndexOf); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + JSHandle jsAPIList = JSHandle::Cast(self); + JSHandle element = GetCallArg(argv, 0); + return jsAPIList->GetLastIndexOf(element.GetTaggedValue()); +} + +JSTaggedValue ContainersList::Set(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, Set); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + JSHandle index = GetCallArg(argv, 0); + JSHandle element = GetCallArg(argv, 1); + if (!index->IsInteger()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "index is not integer", JSTaggedValue::Exception()); + } + JSHandle jsAPIList = JSHandle::Cast(self); + JSTaggedValue oldValue = JSAPIList::Set(thread, jsAPIList, index->GetInt(), element); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return oldValue; +} + +JSTaggedValue ContainersList::ForEach(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, ForEach); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + // get and check List object + JSHandle thisHandle = GetThis(argv); + if (!thisHandle->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + + // get and check callback function + JSHandle callbackFnHandle(GetCallArg(argv, 0)); + if (!callbackFnHandle->IsCallable()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "The first arg is not Callable", JSTaggedValue::Exception()); + } + + // If thisArgHandle was supplied, let T be thisArgHandle; else let T be undefined. + JSHandle thisArgHandle = GetCallArg(argv, 1); + JSHandle list = JSHandle::Cast(thisHandle); + JSHandle singleList(thread, list->GetSingleList()); + int length = list->Length(); + + JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); + int index = 0; + const uint32_t argsLength = 3; // 3: «kValue, k, O» + while (index < length) { + JSTaggedValue value = singleList->Get(index); + EcmaRuntimeCallInfo info = + EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFnHandle, thisArgHandle, undefined, argsLength); + info.SetCallArg(value, JSTaggedValue(index), thisHandle.GetTaggedValue()); + JSTaggedValue funcResult = JSFunction::Call(&info); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult); + index++; + } + return JSTaggedValue::Undefined(); +} + +JSTaggedValue ContainersList::Clear(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, Clear); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + JSHandle jsAPIList = JSHandle::Cast(self); + jsAPIList->Clear(thread); + return JSTaggedValue::Undefined(); +} + +JSTaggedValue ContainersList::RemoveByIndex(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, RemoveByIndex); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + JSHandle index = GetCallArg(argv, 0); + if (!index->IsInteger()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "index is not integer", JSTaggedValue::Exception()); + } + JSHandle jsAPIList = JSHandle::Cast(self); + JSTaggedValue result = JSAPIList::RemoveByIndex(thread, jsAPIList, index->GetInt()); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return result; +} + +JSTaggedValue ContainersList::Remove(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, Remove); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + JSHandle element = GetCallArg(argv, 0); + JSHandle jsAPIList = JSHandle::Cast(self); + return jsAPIList->Remove(thread, element.GetTaggedValue()); +} + +JSTaggedValue ContainersList::ReplaceAllElements(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, ReplaceAllElements); + JSHandle thisHandle = GetThis(argv); + JSHandle callbackFnHandle = GetCallArg(argv, 0); + if (!callbackFnHandle->IsCallable()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "the callbackfun is not callable.", JSTaggedValue::Exception()); + } + JSHandle thisArgHandle = GetCallArg(argv, 1); + return JSAPIList::ReplaceAllElements(thread, thisHandle, callbackFnHandle, thisArgHandle); +} + +JSTaggedValue ContainersList::Equal(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, Equal); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + JSHandle jsAPIList = JSHandle::Cast(self); + JSHandle obj = GetCallArg(argv, 0); + if (!obj->IsJSAPIList()) { + return JSTaggedValue::False(); + } + JSHandle handleObj = JSHandle::Cast(obj); + return jsAPIList->Equal(thread, handleObj); +} + +JSTaggedValue ContainersList::Sort(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, Sort); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not IsJSAPIList", JSTaggedValue::Exception()); + } + JSHandle callbackFnHandle = GetCallArg(argv, 0); + if (!callbackFnHandle->IsUndefined() && !callbackFnHandle->IsCallable()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "Callable is false", JSTaggedValue::Exception()); + } + return JSAPIList::Sort(thread, self, callbackFnHandle); +} + +JSTaggedValue ContainersList::GetIteratorObj(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, GetIteratorObj); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + JSHandle iter = JSAPIListIterator::CreateListIterator(thread, self); + return iter.GetTaggedValue(); +} + +JSTaggedValue ContainersList::ConvertToArray(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, ConvertToArray); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + JSHandle jsAPIList = JSHandle::Cast(self); + return JSAPIList::ConvertToArray(thread, jsAPIList); +} + +JSTaggedValue ContainersList::GetSubList(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, GetSubList); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + JSHandle fromIndex= GetCallArg(argv, 0); + + if (!fromIndex->IsInteger()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "index is not integer", JSTaggedValue::Exception()); + } + + JSHandle toIndex = GetCallArg(argv, 1); + + if (!toIndex->IsInteger()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "index is not integer", JSTaggedValue::Exception()); + } + + JSHandle jsAPIList = JSHandle::Cast(self); + JSTaggedValue newList = JSAPIList::GetSubList(thread, jsAPIList, fromIndex->GetInt(), toIndex->GetInt()); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return newList; +} + +JSTaggedValue ContainersList::Length(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv != nullptr); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, List, Length); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle self = GetThis(argv); + if (!self->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", JSTaggedValue::Exception()); + } + JSHandle jsAPIList = JSHandle::Cast(self); + return JSTaggedValue(jsAPIList->Length()); +} +} // namespace panda::ecmascript::containers diff --git a/ecmascript/containers/containers_list.h b/ecmascript/containers/containers_list.h new file mode 100644 index 0000000000..7375de141a --- /dev/null +++ b/ecmascript/containers/containers_list.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef ECMASCRIPT_CONTAINERS_CONTAINERS_LIST_H +#define ECMASCRIPT_CONTAINERS_CONTAINERS_LIST_H + +#include "ecmascript/base/builtins_base.h" +#include "ecmascript/ecma_runtime_call_info.h" + +namespace panda::ecmascript::containers { +class ContainersList : public base::BuiltinsBase { +public: + static JSTaggedValue ListConstructor(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Add(EcmaRuntimeCallInfo *argv); + static JSTaggedValue GetFirst(EcmaRuntimeCallInfo *argv); + static JSTaggedValue GetLast(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Insert(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Clear(EcmaRuntimeCallInfo *argv); + static JSTaggedValue RemoveByIndex(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Remove(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Has(EcmaRuntimeCallInfo *argv); + static JSTaggedValue IsEmpty(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Get(EcmaRuntimeCallInfo *argv); + static JSTaggedValue GetIndexOf(EcmaRuntimeCallInfo *argv); + static JSTaggedValue GetLastIndexOf(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Set(EcmaRuntimeCallInfo *argv); + static JSTaggedValue ForEach(EcmaRuntimeCallInfo *argv); + static JSTaggedValue ReplaceAllElements(EcmaRuntimeCallInfo *argv); + static JSTaggedValue GetIteratorObj(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Equal(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Sort(EcmaRuntimeCallInfo *argv); + static JSTaggedValue ConvertToArray(EcmaRuntimeCallInfo *argv); + static JSTaggedValue GetSubList(EcmaRuntimeCallInfo *argv); + static JSTaggedValue Length(EcmaRuntimeCallInfo *argv); +}; +} // namespace panda::ecmascript::containers +#endif // ECMASCRIPT_CONTAINERS_CONTAINERS_LIST_H diff --git a/ecmascript/containers/containers_plainarray.cpp b/ecmascript/containers/containers_plainarray.cpp index 209a3d8d2d..a84aef5389 100644 --- a/ecmascript/containers/containers_plainarray.cpp +++ b/ecmascript/containers/containers_plainarray.cpp @@ -57,7 +57,7 @@ JSTaggedValue ContainersPlainArray::Add(EcmaRuntimeCallInfo *argv) } JSHandle key(GetCallArg(argv, 0)); JSHandle value(GetCallArg(argv, 1)); - if (!key->IsNumber()) { + if (!key->IsInteger()) { THROW_TYPE_ERROR_AND_RETURN(thread, "the index is not integer", JSTaggedValue::Exception()); } JSAPIPlainArray::Add(thread, JSHandle::Cast(self), key, value); @@ -125,7 +125,7 @@ JSTaggedValue ContainersPlainArray::Get(EcmaRuntimeCallInfo *argv) THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception()); } JSHandle key(GetCallArg(argv, 0)); - if (!key->IsNumber()) { + if (!key->IsInteger()) { THROW_TYPE_ERROR_AND_RETURN(thread, "the key is not integer", JSTaggedValue::Exception()); } JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); @@ -253,7 +253,7 @@ JSTaggedValue ContainersPlainArray::Remove(EcmaRuntimeCallInfo *argv) THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception()); } JSHandle key(GetCallArg(argv, 0)); - if (!key->IsNumber()) { + if (!key->IsInteger()) { THROW_TYPE_ERROR_AND_RETURN(thread, "the key is not integer", JSTaggedValue::Undefined()); } JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); @@ -271,7 +271,7 @@ JSTaggedValue ContainersPlainArray::RemoveAt(EcmaRuntimeCallInfo *argv) THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception()); } JSHandle index(GetCallArg(argv, 0)); - if (!index->IsNumber()) { + if (!index->IsInteger()) { THROW_TYPE_ERROR_AND_RETURN(thread, "the index is not integer", JSTaggedValue::Undefined()); } JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); @@ -290,7 +290,7 @@ JSTaggedValue ContainersPlainArray::RemoveRangeFrom(EcmaRuntimeCallInfo *argv) } JSHandle valueIndex(GetCallArg(argv, 0)); JSHandle valueSize(GetCallArg(argv, 1)); - if (!valueIndex->IsNumber() || !valueSize->IsNumber()) { + if (!valueIndex->IsInteger() || !valueSize->IsInteger()) { THROW_TYPE_ERROR_AND_RETURN(thread, "the index or the value is not integer", JSTaggedValue::Undefined()); } int32_t index = valueIndex->GetNumber(); @@ -312,7 +312,7 @@ JSTaggedValue ContainersPlainArray::SetValueAt(EcmaRuntimeCallInfo *argv) } JSHandle index(GetCallArg(argv, 0)); JSHandle value(GetCallArg(argv, 1)); - if (!index->IsNumber()) { + if (!index->IsInteger()) { THROW_TYPE_ERROR_AND_RETURN(thread, "the index is not integer", JSTaggedValue::Exception()); } JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); @@ -331,7 +331,7 @@ JSTaggedValue ContainersPlainArray::GetValueAt(EcmaRuntimeCallInfo *argv) THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIPlainArray", JSTaggedValue::Exception()); } JSHandle idx(GetCallArg(argv, 0)); - if (!idx->IsNumber()) { + if (!idx->IsInteger()) { THROW_TYPE_ERROR_AND_RETURN(thread, "the index is not integer", JSTaggedValue::Undefined()); } JSAPIPlainArray *array = JSAPIPlainArray::Cast(self->GetTaggedObject()); diff --git a/ecmascript/containers/containers_private.cpp b/ecmascript/containers/containers_private.cpp index 3d6204248c..f599f3479c 100644 --- a/ecmascript/containers/containers_private.cpp +++ b/ecmascript/containers/containers_private.cpp @@ -17,6 +17,8 @@ #include "containers_arraylist.h" #include "containers_deque.h" +#include "containers_linked_list.h" +#include "containers_list.h" #include "containers_plainarray.h" #include "containers_queue.h" #include "containers_stack.h" @@ -30,6 +32,10 @@ #include "ecmascript/js_api_arraylist_iterator.h" #include "ecmascript/js_api_deque.h" #include "ecmascript/js_api_deque_iterator.h" +#include "ecmascript/js_api_linked_list.h" +#include "ecmascript/js_api_linked_list_iterator.h" +#include "ecmascript/js_api_list.h" +#include "ecmascript/js_api_list_iterator.h" #include "ecmascript/js_api_plain_array.h" #include "ecmascript/js_api_plain_array_iterator.h" #include "ecmascript/js_api_queue.h" @@ -92,8 +98,14 @@ JSTaggedValue ContainersPrivate::Load(EcmaRuntimeCallInfo *msg) res = InitializeContainer(thread, thisValue, InitializeVector, "VectorConstructor"); break; } - case ContainerTag::List: - case ContainerTag::LinkedList: + case ContainerTag::List: { + res = InitializeContainer(thread, thisValue, InitializeList, "ListConstructor"); + break; + } + case ContainerTag::LinkedList: { + res = InitializeContainer(thread, thisValue, InitializeLinkedList, "LinkedListConstructor"); + break; + } case ContainerTag::HashMap: case ContainerTag::HashSet: case ContainerTag::LightWeightMap: @@ -237,7 +249,8 @@ JSHandle ContainersPrivate::InitializeArrayList(JSThread *thread) // ArrayList() = new Function() JSHandle arrayListFunction(NewContainerConstructor( thread, prototype, ContainersArrayList::ArrayListConstructor, "ArrayList", FuncLength::ZERO)); - JSHandle(arrayListFunction)->SetFunctionPrototype(thread, arrayListInstanceDynclass.GetTaggedValue()); + JSHandle::Cast(arrayListFunction)->SetFunctionPrototype(thread, + arrayListInstanceDynclass.GetTaggedValue()); // "constructor" property on the prototype JSHandle constructorKey = globalConst->GetHandledConstructorString(); @@ -311,7 +324,7 @@ JSHandle ContainersPrivate::InitializeTreeMap(JSThread *thread) // TreeMap() = new Function() JSHandle mapFunction(NewContainerConstructor( thread, mapFuncPrototype, ContainersTreeMap::TreeMapConstructor, "TreeMap", FuncLength::ZERO)); - JSHandle(mapFunction)->SetFunctionPrototype(thread, mapInstanceDynclass.GetTaggedValue()); + JSHandle::Cast(mapFunction)->SetFunctionPrototype(thread, mapInstanceDynclass.GetTaggedValue()); // "constructor" property on the prototype JSHandle constructorKey = globalConst->GetHandledConstructorString(); @@ -386,7 +399,7 @@ JSHandle ContainersPrivate::InitializeTreeSet(JSThread *thread) // TreeSet() = new Function() JSHandle setFunction(NewContainerConstructor( thread, setFuncPrototype, ContainersTreeSet::TreeSetConstructor, "TreeSet", FuncLength::ZERO)); - JSHandle(setFunction)->SetFunctionPrototype(thread, setInstanceDynclass.GetTaggedValue()); + JSHandle::Cast(setFunction)->SetFunctionPrototype(thread, setInstanceDynclass.GetTaggedValue()); // "constructor" property on the prototype JSHandle constructorKey = globalConst->GetHandledConstructorString(); @@ -458,8 +471,9 @@ JSHandle ContainersPrivate::InitializePlainArray(JSThread *thread JSHandle plainArrayFunction( NewContainerConstructor(thread, plainArrayFuncPrototype, ContainersPlainArray::PlainArrayConstructor, "PlainArray", FuncLength::ZERO)); - JSHandle(plainArrayFunction)->SetFunctionPrototype(thread, - plainArrayInstanceDynclass.GetTaggedValue()); + JSHandle::Cast(plainArrayFunction)->SetFunctionPrototype(thread, + plainArrayInstanceDynclass.GetTaggedValue()); + // "constructor" property on the prototype JSHandle constructorKey = globalConst->GetHandledConstructorString(); JSObject::SetProperty(thread, JSHandle(plainArrayFuncPrototype), constructorKey, @@ -531,7 +545,7 @@ JSHandle ContainersPrivate::InitializeStack(JSThread *thread) // Stack() = new Function() JSHandle stackFunction(NewContainerConstructor( thread, stackFuncPrototype, ContainersStack::StackConstructor, "Stack", FuncLength::ZERO)); - JSHandle(stackFunction)->SetFunctionPrototype(thread, stackInstanceDynclass.GetTaggedValue()); + JSHandle::Cast(stackFunction)->SetFunctionPrototype(thread, stackInstanceDynclass.GetTaggedValue()); // "constructor" property on the prototype JSHandle constructorKey = globalConst->GetHandledConstructorString(); @@ -589,7 +603,7 @@ JSHandle ContainersPrivate::InitializeVector(JSThread *thread) // Vector() = new Function() JSHandle vectorFunction(NewContainerConstructor( thread, prototype, ContainersVector::VectorConstructor, "Vector", FuncLength::ZERO)); - JSHandle(vectorFunction)->SetFunctionPrototype(thread, vectorInstanceDynclass.GetTaggedValue()); + JSHandle::Cast(vectorFunction)->SetFunctionPrototype(thread, vectorInstanceDynclass.GetTaggedValue()); // "constructor" property on the prototype JSHandle constructorKey = globalConst->GetHandledConstructorString(); @@ -668,7 +682,7 @@ JSHandle ContainersPrivate::InitializeQueue(JSThread *thread) // Queue() = new Function() JSHandle queueFunction(NewContainerConstructor( thread, queueFuncPrototype, ContainersQueue::QueueConstructor, "Queue", FuncLength::ZERO)); - JSHandle(queueFunction)->SetFunctionPrototype(thread, queueInstanceDynclass.GetTaggedValue()); + JSHandle::Cast(queueFunction)->SetFunctionPrototype(thread, queueInstanceDynclass.GetTaggedValue()); // "constructor" property on the prototype JSHandle constructorKey = globalConst->GetHandledConstructorString(); @@ -721,7 +735,7 @@ JSHandle ContainersPrivate::InitializeDeque(JSThread *thread) // Deque() = new Function() JSHandle dequeFunction(NewContainerConstructor( thread, dequeFuncPrototype, ContainersDeque::DequeConstructor, "Deque", FuncLength::ZERO)); - JSHandle(dequeFunction)->SetFunctionPrototype(thread, dequeInstanceDynclass.GetTaggedValue()); + JSHandle::Cast(dequeFunction)->SetFunctionPrototype(thread, dequeInstanceDynclass.GetTaggedValue()); // "constructor" property on the prototype JSHandle constructorKey = globalConst->GetHandledConstructorString(); @@ -762,4 +776,135 @@ void ContainersPrivate::InitializeDequeIterator(JSThread *thread, const JSHandle SetStringTagSymbol(thread, env, dequeIteratorPrototype, "Deque Iterator"); globalConst->SetConstant(ConstantIndex::DEQUE_ITERATOR_PROTOTYPE_INDEX, dequeIteratorPrototype.GetTaggedValue()); } + +JSHandle ContainersPrivate::InitializeList(JSThread *thread) +{ + auto globalConst = const_cast(thread->GlobalConstants()); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle listFuncPrototype = factory->NewEmptyJSObject(); + JSHandle listFuncPrototypeValue(listFuncPrototype); + JSHandle listInstanceDynclass = + factory->NewEcmaDynClass(JSAPIList::SIZE, JSType::JS_API_LIST, listFuncPrototypeValue); + JSHandle listFunction(NewContainerConstructor( + thread, listFuncPrototype, ContainersList::ListConstructor, "List", FuncLength::ZERO)); + JSHandle::Cast(listFunction)->SetFunctionPrototype(thread, listInstanceDynclass.GetTaggedValue()); + + JSHandle constructorKey = globalConst->GetHandledConstructorString(); + JSObject::SetProperty(thread, JSHandle(listFuncPrototype), constructorKey, listFunction); + + SetFrozenFunction(thread, listFuncPrototype, "add", ContainersList::Add, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "getFirst", ContainersList::GetFirst, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "getLast", ContainersList::GetLast, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "insert", ContainersList::Insert, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "clear", ContainersList::Clear, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "removeByIndex", ContainersList::RemoveByIndex, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "remove", ContainersList::Remove, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "has", ContainersList::Has, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "isEmpty", ContainersList::IsEmpty, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "get", ContainersList::Get, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "getIndexOf", ContainersList::GetIndexOf, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "getLastIndexOf", ContainersList::GetLastIndexOf, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "set", ContainersList::Set, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "forEach", ContainersList::ForEach, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "replaceAllElements", ContainersList::ReplaceAllElements, + FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "equal", ContainersList::Equal, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "sort", ContainersList::Sort, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "convertToArray", ContainersList::ConvertToArray, FuncLength::ONE); + SetFrozenFunction(thread, listFuncPrototype, "getSubList", ContainersList::GetSubList, FuncLength::ONE); + + JSHandle lengthGetter = CreateGetter(thread, ContainersList::Length, "length", FuncLength::ZERO); + JSHandle lengthKey(factory->NewFromASCII("length")); + SetGetter(thread, listFuncPrototype, lengthKey, lengthGetter); + + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + SetFunctionAtSymbol(thread, env, listFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]", + ContainersList::GetIteratorObj, FuncLength::ONE); + + InitializeListIterator(thread, env); + globalConst->SetConstant(ConstantIndex::LIST_FUNCTION_INDEX, listFunction.GetTaggedValue()); + return listFunction; +} + +JSHandle ContainersPrivate::InitializeLinkedList(JSThread *thread) +{ + auto globalConst = const_cast(thread->GlobalConstants()); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle linkedListFuncPrototype = factory->NewEmptyJSObject(); + JSHandle linkedListFuncPrototypeValue(linkedListFuncPrototype); + JSHandle linkedListInstanceDynclass = + factory->NewEcmaDynClass(JSAPILinkedList::SIZE, JSType::JS_API_LINKED_LIST, linkedListFuncPrototypeValue); + JSHandle linkedListFunction(NewContainerConstructor( + thread, linkedListFuncPrototype, ContainersLinkedList::LinkedListConstructor, "LinkedList", FuncLength::ZERO)); + JSHandle::Cast(linkedListFunction)->SetFunctionPrototype(thread, + linkedListInstanceDynclass.GetTaggedValue()); + + JSHandle constructorKey = globalConst->GetHandledConstructorString(); + JSObject::SetProperty(thread, JSHandle(linkedListFuncPrototype), constructorKey, linkedListFunction); + + SetFrozenFunction(thread, linkedListFuncPrototype, "add", ContainersLinkedList::Add, FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "insert", ContainersLinkedList::Insert, FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "clear", ContainersLinkedList::Clear, FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "clone", ContainersLinkedList::Clone, FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "removeFirst", ContainersLinkedList::RemoveFirst, + FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "removeLast", ContainersLinkedList::RemoveLast, FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "removeFirstFound", ContainersLinkedList::RemoveFirstFound, + FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "removeByIndex", ContainersLinkedList::RemoveByIndex, + FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "remove", ContainersLinkedList::Remove, FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "removeLastFound", ContainersLinkedList::RemoveLastFound, + FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "has", ContainersLinkedList::Has, FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "get", ContainersLinkedList::Get, FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "addFirst", ContainersLinkedList::AddFirst, FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "getFirst", ContainersLinkedList::GetFirst, FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "getLast", ContainersLinkedList::GetLast, FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "getIndexOf", ContainersLinkedList::GetIndexOf, FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "getLastIndexOf", ContainersLinkedList::GetLastIndexOf, + FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "convertToArray", ContainersLinkedList::ConvertToArray, + FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "set", ContainersLinkedList::Set, FuncLength::ONE); + SetFrozenFunction(thread, linkedListFuncPrototype, "forEach", ContainersLinkedList::ForEach, FuncLength::ONE); + + JSHandle lengthGetter = CreateGetter(thread, ContainersLinkedList::Length, "length", + FuncLength::ZERO); + JSHandle lengthKey(factory->NewFromASCII("length")); + SetGetter(thread, linkedListFuncPrototype, lengthKey, lengthGetter); + + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + SetFunctionAtSymbol(thread, env, linkedListFuncPrototype, env->GetIteratorSymbol(), "[Symbol.iterator]", + ContainersLinkedList::GetIteratorObj, FuncLength::ONE); + + InitializeLinkedListIterator(thread, env); + globalConst->SetConstant(ConstantIndex::LINKED_LIST_FUNCTION_INDEX, linkedListFunction.GetTaggedValue()); + return linkedListFunction; +} + +void ContainersPrivate::InitializeLinkedListIterator(JSThread *thread, const JSHandle &env) +{ + auto globalConst = const_cast(thread->GlobalConstants()); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle iteratorDynclass = + JSHandle(thread, globalConst->GetHandledJSAPIIteratorFuncDynClass().GetObject()); + JSHandle setIteratorPrototype(factory->NewJSObject(iteratorDynclass)); + SetFrozenFunction(thread, setIteratorPrototype, "next", JSAPILinkedListIterator::Next, FuncLength::ONE); + SetStringTagSymbol(thread, env, setIteratorPrototype, "linkedlist Iterator"); + globalConst->SetConstant(ConstantIndex::LINKED_LIST_ITERATOR_PROTOTYPE_INDEX, + setIteratorPrototype.GetTaggedValue()); +} + +void ContainersPrivate::InitializeListIterator(JSThread *thread, const JSHandle &env) +{ + auto globalConst = const_cast(thread->GlobalConstants()); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle iteratorDynclass = + JSHandle(thread, globalConst->GetHandledJSAPIIteratorFuncDynClass().GetObject()); + JSHandle setIteratorPrototype(factory->NewJSObject(iteratorDynclass)); + SetFrozenFunction(thread, setIteratorPrototype, "next", JSAPIListIterator::Next, FuncLength::ONE); + SetStringTagSymbol(thread, env, setIteratorPrototype, "list Iterator"); + globalConst->SetConstant(ConstantIndex::LIST_ITERATOR_PROTOTYPE_INDEX, setIteratorPrototype.GetTaggedValue()); +} } // namespace panda::ecmascript::containers diff --git a/ecmascript/containers/containers_private.h b/ecmascript/containers/containers_private.h index cdaf2988c4..c3e27ef86c 100644 --- a/ecmascript/containers/containers_private.h +++ b/ecmascript/containers/containers_private.h @@ -87,6 +87,10 @@ private: GlobalEnvConstants *globalConst); static JSHandle InitializeStack(JSThread *thread); static void InitializeStackIterator(JSThread *thread, GlobalEnvConstants *globalConst); + static JSHandle InitializeList(JSThread *thread); + static JSHandle InitializeLinkedList(JSThread *thread); + static void InitializeLinkedListIterator(JSThread *thread, const JSHandle &env); + static void InitializeListIterator(JSThread *thread, const JSHandle &env); }; } // namespace panda::ecmascript::containers diff --git a/ecmascript/containers/tests/BUILD.gn b/ecmascript/containers/tests/BUILD.gn index 908f7e9097..54ff4c5e41 100644 --- a/ecmascript/containers/tests/BUILD.gn +++ b/ecmascript/containers/tests/BUILD.gn @@ -23,6 +23,8 @@ host_unittest_action("ContainersTest") { sources = [ # test file "containers_deque_test.cpp", + "containers_linked_list_test.cpp", + "containers_list_test.cpp", "containers_plainarray_test.cpp", "containers_stack_test.cpp", "containers_treemap_test.cpp", diff --git a/ecmascript/containers/tests/containers_linked_list_test.cpp b/ecmascript/containers/tests/containers_linked_list_test.cpp new file mode 100644 index 0000000000..0bc05130b7 --- /dev/null +++ b/ecmascript/containers/tests/containers_linked_list_test.cpp @@ -0,0 +1,453 @@ +/* + * 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. + */ + +#include "ecmascript/containers/containers_linked_list.h" +#include "ecmascript/containers/containers_private.h" +#include "ecmascript/ecma_runtime_call_info.h" +#include "ecmascript/global_env.h" +#include "ecmascript/js_api_linked_list.h" +#include "ecmascript/js_api_linked_list_iterator.h" +#include "ecmascript/js_handle.h" +#include "ecmascript/js_tagged_value-inl.h" +#include "ecmascript/js_thread.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; +using namespace panda::ecmascript::containers; + +namespace panda::test { +class ContainersLinkedListTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(instance, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + + EcmaVM *instance {nullptr}; + EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; + + class TestClass : public base::BuiltinsBase { + public: + static JSTaggedValue TestForEachFunc(EcmaRuntimeCallInfo *argv) + { + JSThread *thread = argv->GetThread(); + JSHandle value = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + JSHandle list = GetCallArg(argv, 2); // 2 means the secode arg + if (!list->IsUndefined()) { + if (index->IsNumber() && value->IsNumber()) { + JSHandle newValue(thread, JSTaggedValue(value->GetInt() * 2)); // 2 means mul by 2 + JSAPILinkedList::Set(thread, JSHandle::Cast(list), index->GetInt(), newValue); + } + } + return JSTaggedValue::True(); + } + }; +protected: + JSTaggedValue InitializeLinkedListConstructor() + { + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + + JSHandle globalObject = env->GetJSGlobalObject(); + JSHandle key(factory->NewFromASCII("ArkPrivate")); + JSHandle value = + JSObject::GetProperty(thread, JSHandle(globalObject), key).GetValue(); + + auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + objCallInfo->SetFunction(JSTaggedValue::Undefined()); + objCallInfo->SetThis(value.GetTaggedValue()); + objCallInfo->SetCallArg(0, JSTaggedValue(static_cast(ContainerTag::LinkedList))); + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo.get()); + JSTaggedValue result = ContainersPrivate::Load(objCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + + return result; + } + + JSHandle CreateJSAPILinkedList(JSTaggedValue compare = JSTaggedValue::Undefined()) + { + JSHandle compareHandle(thread, compare); + JSHandle newTarget(thread, InitializeLinkedListConstructor()); + auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + objCallInfo->SetFunction(newTarget.GetTaggedValue()); + objCallInfo->SetNewTarget(newTarget.GetTaggedValue()); + objCallInfo->SetThis(JSTaggedValue::Undefined()); + objCallInfo->SetCallArg(0, compareHandle.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo.get()); + JSTaggedValue result = ContainersLinkedList::LinkedListConstructor(objCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + JSHandle linkedlist(thread, result); + return linkedlist; + } +}; + +HWTEST_F_L0(ContainersLinkedListTest, LinkedListConstructor) +{ + InitializeLinkedListConstructor(); + JSHandle newTarget(thread, InitializeLinkedListConstructor()); + + auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + objCallInfo->SetFunction(newTarget.GetTaggedValue()); + objCallInfo->SetNewTarget(newTarget.GetTaggedValue()); + objCallInfo->SetThis(JSTaggedValue::Undefined()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo.get()); + JSTaggedValue result = ContainersLinkedList::LinkedListConstructor(objCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + + ASSERT_TRUE(result.IsJSAPILinkedList()); + JSHandle list(thread, result); + JSTaggedValue resultProto = JSTaggedValue::GetPrototype(thread, JSHandle(list)); + JSTaggedValue funcProto = newTarget->GetFunctionPrototype(); + ASSERT_EQ(resultProto, funcProto); + int size = list->Length(); + ASSERT_EQ(size, 0); +} + +HWTEST_F_L0(ContainersLinkedListTest, InsertAndGet) +{ + constexpr uint32_t NODE_NUMBERS = 8; + JSHandle linkedlist = CreateJSAPILinkedList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + callInfo->SetCallArg(1, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersLinkedList::Insert(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(linkedlist->Length(), static_cast(i + 1)); + } + + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersLinkedList::Get(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue(i)); + } +} + +HWTEST_F_L0(ContainersLinkedListTest, Remove) +{ + constexpr uint32_t NODE_NUMBERS = 20; + JSHandle linkedlist = CreateJSAPILinkedList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + callInfo->SetCallArg(1, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersLinkedList::Insert(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(linkedlist->Length(), static_cast(i + 1)); + } + + { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(NODE_NUMBERS / 2)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue rvalue = ContainersLinkedList::Remove(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(rvalue, JSTaggedValue::True()); + EXPECT_EQ(linkedlist->Length(), static_cast(NODE_NUMBERS - 1)); + } + + { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(6)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue rvalue = ContainersLinkedList::RemoveByIndex(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(rvalue, JSTaggedValue(6)); + EXPECT_EQ(linkedlist->Length(), static_cast(NODE_NUMBERS - 2)); + } +} + +HWTEST_F_L0(ContainersLinkedListTest, RemoveFirst) +{ + constexpr uint32_t NODE_NUMBERS = 20; + JSHandle linkedlist = CreateJSAPILinkedList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + callInfo->SetCallArg(1, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersLinkedList::Insert(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(linkedlist->Length(), static_cast(i + 1)); + } + + { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue rvalue = ContainersLinkedList::RemoveFirst(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(rvalue, JSTaggedValue(0)); + EXPECT_EQ(linkedlist->Length(), static_cast(NODE_NUMBERS - 1)); + } + + { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(15)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue rvalue = ContainersLinkedList::RemoveFirstFound(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(rvalue, JSTaggedValue::True()); + EXPECT_EQ(linkedlist->Length(), static_cast(NODE_NUMBERS - 2)); + } +} + +HWTEST_F_L0(ContainersLinkedListTest, RemoveLast) +{ + constexpr uint32_t NODE_NUMBERS = 20; + JSHandle linkedlist = CreateJSAPILinkedList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + callInfo->SetCallArg(1, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersLinkedList::Insert(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(linkedlist->Length(), static_cast(i + 1)); + } + + { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue rvalue = ContainersLinkedList::RemoveLast(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(rvalue, JSTaggedValue(19)); + EXPECT_EQ(linkedlist->Length(), static_cast(NODE_NUMBERS - 1)); + } + + { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(8)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue rvalue = ContainersLinkedList::RemoveLastFound(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(rvalue, JSTaggedValue::True()); + EXPECT_EQ(linkedlist->Length(), static_cast(NODE_NUMBERS - 2)); + } +} + +HWTEST_F_L0(ContainersLinkedListTest, Clear) +{ + constexpr uint32_t NODE_NUMBERS = 8; + JSHandle linkedlist = CreateJSAPILinkedList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersLinkedList::Add(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(linkedlist->Length(), static_cast(i + 1)); + } + + { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + ContainersLinkedList::Clear(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(linkedlist->Length(), 0); + } +} + +HWTEST_F_L0(ContainersLinkedListTest, Clone) +{ + constexpr uint32_t NODE_NUMBERS = 8; + JSHandle linkedList = CreateJSAPILinkedList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedList.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + callInfo->SetCallArg(1, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersLinkedList::Add(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(linkedList->Length(), static_cast(i + 1)); + } + + linkedList->Dump(); + + auto callInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + callInfo1->SetFunction(JSTaggedValue::Undefined()); + callInfo1->SetThis(linkedList.GetTaggedValue()); + JSTaggedValue newlinkedList = ContainersLinkedList::Clone(callInfo1.get()); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(newlinkedList); + callInfo->SetCallArg(0, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersLinkedList::Get(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue(i)); + } +} + +HWTEST_F_L0(ContainersLinkedListTest, Values) +{ + constexpr uint32_t NODE_NUMBERS = 8; + JSHandle linkedlist = CreateJSAPILinkedList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + callInfo->SetCallArg(1, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersLinkedList::Add(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(linkedlist->Length(), static_cast(i + 1)); + } + + // test values + auto callInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + callInfo1->SetFunction(JSTaggedValue::Undefined()); + callInfo1->SetThis(linkedlist.GetTaggedValue()); + [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo1.get()); + JSHandle iterValues(thread, ContainersLinkedList::GetIteratorObj(callInfo1.get())); + TestHelper::TearDownFrame(thread, prev1); + EXPECT_TRUE(iterValues->IsJSAPILinkedListIterator()); + + JSMutableHandle result(thread, JSTaggedValue::Undefined()); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(iterValues.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + result.Update(JSAPILinkedListIterator::Next(callInfo.get())); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(static_cast(i), JSIterator::IteratorValue(thread, result)->GetInt()); + } +} + +HWTEST_F_L0(ContainersLinkedListTest, ForEach) +{ + constexpr uint32_t NODE_NUMBERS = 8; + JSHandle linkedlist = CreateJSAPILinkedList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + callInfo->SetCallArg(1, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersLinkedList::Add(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(linkedlist->Length(), static_cast(i + 1)); + } + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle newLinkedlist = CreateJSAPILinkedList(); + { + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + JSHandle func = factory->NewJSFunction(env, reinterpret_cast(TestClass::TestForEachFunc)); + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, func.GetTaggedValue()); + callInfo->SetCallArg(1, newLinkedlist.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + ContainersLinkedList::ForEach(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + } + + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(linkedlist.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersLinkedList::Get(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue(i * 2)); + } +} +} // namespace panda::test diff --git a/ecmascript/containers/tests/containers_list_test.cpp b/ecmascript/containers/tests/containers_list_test.cpp new file mode 100644 index 0000000000..e6ebce0211 --- /dev/null +++ b/ecmascript/containers/tests/containers_list_test.cpp @@ -0,0 +1,461 @@ +/* + * 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. + */ + +#include "ecmascript/containers/containers_list.h" +#include "ecmascript/containers/containers_private.h" +#include "ecmascript/ecma_runtime_call_info.h" +#include "ecmascript/global_env.h" +#include "ecmascript/js_api_list.h" +#include "ecmascript/js_api_list_iterator.h" +#include "ecmascript/js_handle.h" +#include "ecmascript/js_tagged_value-inl.h" +#include "ecmascript/js_thread.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; +using namespace panda::ecmascript::containers; + +namespace panda::test { +class ContainersListTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(instance, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + + EcmaVM *instance {nullptr}; + EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; + + class TestClass : public base::BuiltinsBase { + public: + static JSTaggedValue TestForEachFunc(EcmaRuntimeCallInfo *argv) + { + JSThread *thread = argv->GetThread(); + JSHandle value = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + JSHandle list = GetCallArg(argv, 2); // 2 means the secode arg + if (!list->IsUndefined()) { + if (index->IsNumber() && value->IsNumber()) { + JSHandle newValue(thread, JSTaggedValue(value->GetInt() * 2)); // 2 means mul by 2 + JSAPIList::Set(thread, JSHandle::Cast(list), index->GetInt(), newValue); + } + } + return JSTaggedValue::True(); + } + }; +protected: + JSTaggedValue InitializeListConstructor() + { + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + + JSHandle globalObject = env->GetJSGlobalObject(); + JSHandle key(factory->NewFromASCII("ArkPrivate")); + JSHandle value = + JSObject::GetProperty(thread, JSHandle(globalObject), key).GetValue(); + + auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + objCallInfo->SetFunction(JSTaggedValue::Undefined()); + objCallInfo->SetThis(value.GetTaggedValue()); + objCallInfo->SetCallArg(0, JSTaggedValue(static_cast(ContainerTag::List))); + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo.get()); + JSTaggedValue result = ContainersPrivate::Load(objCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + + return result; + } + + JSHandle CreateJSAPIList(JSTaggedValue compare = JSTaggedValue::Undefined()) + { + JSHandle compareHandle(thread, compare); + JSHandle newTarget(thread, InitializeListConstructor()); + auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + objCallInfo->SetFunction(newTarget.GetTaggedValue()); + objCallInfo->SetNewTarget(newTarget.GetTaggedValue()); + objCallInfo->SetThis(JSTaggedValue::Undefined()); + objCallInfo->SetCallArg(0, compareHandle.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo.get()); + JSTaggedValue result = ContainersList::ListConstructor(objCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + JSHandle list(thread, result); + return list; + } +}; + +HWTEST_F_L0(ContainersListTest, ListConstructor) +{ + InitializeListConstructor(); + JSHandle newTarget(thread, InitializeListConstructor()); + + auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + objCallInfo->SetFunction(newTarget.GetTaggedValue()); + objCallInfo->SetNewTarget(newTarget.GetTaggedValue()); + objCallInfo->SetThis(JSTaggedValue::Undefined()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo.get()); + JSTaggedValue result = ContainersList::ListConstructor(objCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + + ASSERT_TRUE(result.IsJSAPIList()); + JSHandle list(thread, result); + JSTaggedValue resultProto = JSTaggedValue::GetPrototype(thread, JSHandle(list)); + JSTaggedValue funcProto = newTarget->GetFunctionPrototype(); + ASSERT_EQ(resultProto, funcProto); + int size = list->Length(); + ASSERT_EQ(size, 0); +} + +HWTEST_F_L0(ContainersListTest, InsertAndGet) +{ + constexpr uint32_t NODE_NUMBERS = 8; + JSHandle list = CreateJSAPIList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + callInfo->SetCallArg(1, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersList::Insert(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(list->Length(), static_cast(i + 1)); + } + + { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(20)); + callInfo->SetCallArg(1, JSTaggedValue(20)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersList::Insert(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::Exception()); + } + + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersList::Get(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue(i)); + } +} + +HWTEST_F_L0(ContainersListTest, Remove) +{ + constexpr uint32_t NODE_NUMBERS = 20; + JSHandle list = CreateJSAPIList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + callInfo->SetCallArg(1, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersList::Insert(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(list->Length(), static_cast(i + 1)); + } + + { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(NODE_NUMBERS / 2)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue rvalue = ContainersList::Remove(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(rvalue, JSTaggedValue::True()); + EXPECT_EQ(list->Length(), static_cast(NODE_NUMBERS - 1)); + } + + { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(6)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue rvalue = ContainersList::RemoveByIndex(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(rvalue, JSTaggedValue(6)); + EXPECT_EQ(list->Length(), static_cast(NODE_NUMBERS - 2)); + } +} + +HWTEST_F_L0(ContainersListTest, Equal) +{ + constexpr uint32_t NODE_NUMBERS = 8; + JSHandle list = CreateJSAPIList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersList::Add(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(list->Length(), static_cast(i + 1)); + } + + JSHandle list1 = CreateJSAPIList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list1.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersList::Add(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(list1->Length(), static_cast(i + 1)); + } + + { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, list1.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue res = ContainersList::Equal(callInfo.get()); + EXPECT_EQ(res, JSTaggedValue::True()); + TestHelper::TearDownFrame(thread, prev); + } +} + +HWTEST_F_L0(ContainersListTest, GetSubList) +{ + constexpr uint32_t NODE_NUMBERS = 10; + JSHandle list = CreateJSAPIList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersList::Add(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(list->Length(), static_cast(i + 1)); + } + + { + auto callInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo1->SetFunction(JSTaggedValue::Undefined()); + callInfo1->SetThis(list.GetTaggedValue()); + callInfo1->SetCallArg(0, JSTaggedValue(2)); + callInfo1->SetCallArg(1, JSTaggedValue(5)); + [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo1.get()); + JSTaggedValue newList = ContainersList::GetSubList(callInfo1.get()); + TestHelper::TearDownFrame(thread, prev1); + EXPECT_EQ(list->Length(), 10); + for (uint32_t i = 0; i < 3; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(newList); + callInfo->SetCallArg(0, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersList::Get(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue(i + 2)); + } + } +} + +HWTEST_F_L0(ContainersListTest, ConvertToArray) +{ + constexpr uint32_t NODE_NUMBERS = 8; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle list = CreateJSAPIList(); + JSHandle oldArray(factory->NewTaggedArray(NODE_NUMBERS, JSTaggedValue::Hole())); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersList::Add(callInfo.get()); + oldArray->Set(thread, i, JSTaggedValue(i)); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(list->Length(), static_cast(i + 1)); + } + + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue newArray = ContainersList::ConvertToArray(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue newArrayValue = + JSTaggedValue::ToObject(thread, JSHandle(thread, newArray))->GetElements(); + JSHandle newArrayHandle(thread, newArrayValue); + + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + EXPECT_EQ(newArrayHandle->Get(i), oldArray->Get(i)); + } +} + +HWTEST_F_L0(ContainersListTest, Clear) +{ + constexpr uint32_t NODE_NUMBERS = 8; + JSHandle list = CreateJSAPIList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersList::Add(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(list->Length(), static_cast(i + 1)); + } + + { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + ContainersList::Clear(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(list->Length(), 0); + } +} + +HWTEST_F_L0(ContainersListTest, Values) +{ + constexpr int NODE_NUMBERS = 8; + JSHandle list = CreateJSAPIList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + callInfo->SetCallArg(1, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersList::Add(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(list->Length(), static_cast(i + 1)); + } + + auto callInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + callInfo1->SetFunction(JSTaggedValue::Undefined()); + callInfo1->SetThis(list.GetTaggedValue()); + [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, callInfo1.get()); + JSHandle iterValues(thread, ContainersList::GetIteratorObj(callInfo1.get())); + TestHelper::TearDownFrame(thread, prev1); + EXPECT_TRUE(iterValues->IsJSAPIListIterator()); + + JSMutableHandle result(thread, JSTaggedValue::Undefined()); + for (int i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(iterValues.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + result.Update(JSAPIListIterator::Next(callInfo.get())); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(i, JSIterator::IteratorValue(thread, result)->GetInt()); + } +} + +HWTEST_F_L0(ContainersListTest, ForEach) +{ + constexpr uint32_t NODE_NUMBERS = 8; + JSHandle list = CreateJSAPIList(); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + callInfo->SetCallArg(1, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersList::Add(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue::True()); + EXPECT_EQ(list->Length(), static_cast(i + 1)); + } + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle dlist = CreateJSAPIList(); + { + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + JSHandle func = factory->NewJSFunction(env, reinterpret_cast(TestClass::TestForEachFunc)); + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, func.GetTaggedValue()); + callInfo->SetCallArg(1, dlist.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + ContainersList::ForEach(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + } + + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + auto callInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + callInfo->SetFunction(JSTaggedValue::Undefined()); + callInfo->SetThis(list.GetTaggedValue()); + callInfo->SetCallArg(0, JSTaggedValue(i)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, callInfo.get()); + JSTaggedValue result = ContainersList::Get(callInfo.get()); + TestHelper::TearDownFrame(thread, prev); + EXPECT_EQ(result, JSTaggedValue(i * 2)); + } +} +} // namespace panda::test diff --git a/ecmascript/dfx/hprof/heap_snapshot.cpp b/ecmascript/dfx/hprof/heap_snapshot.cpp index 11b38e33a3..d74c7b8140 100644 --- a/ecmascript/dfx/hprof/heap_snapshot.cpp +++ b/ecmascript/dfx/hprof/heap_snapshot.cpp @@ -361,6 +361,10 @@ CString *HeapSnapshot::GenerateNodeName(TaggedObject *entry) return GetString("Stack"); case JSType::JS_API_STACK_ITERATOR: return GetString("StackIterator"); + case JSType::JS_API_LIST: + return GetString("List"); + case JSType::JS_API_LINKED_LIST: + return GetString("LinkedList"); case JSType::SOURCE_TEXT_MODULE_RECORD: return GetString("SourceTextModule"); case JSType::IMPORTENTRY_RECORD: diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index be4944b046..3411f630e0 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -34,6 +34,10 @@ #include "ecmascript/js_api_arraylist_iterator.h" #include "ecmascript/js_api_deque.h" #include "ecmascript/js_api_deque_iterator.h" +#include "ecmascript/js_api_linked_list.h" +#include "ecmascript/js_api_linked_list_iterator.h" +#include "ecmascript/js_api_list.h" +#include "ecmascript/js_api_list_iterator.h" #include "ecmascript/js_api_plain_array.h" #include "ecmascript/js_api_plain_array_iterator.h" #include "ecmascript/js_api_queue.h" @@ -93,6 +97,7 @@ #include "ecmascript/module/js_module_source_text.h" #include "ecmascript/tagged_array.h" #include "ecmascript/tagged_dictionary.h" +#include "ecmascript/tagged_list.h" #include "ecmascript/tagged_tree.h" #include "ecmascript/template_map.h" #include "ecmascript/transitions_dictionary.h" @@ -341,6 +346,14 @@ CString JSHClass::DumpJSType(JSType type) return "Stack"; case JSType::JS_API_STACK_ITERATOR: return "StackIterator"; + case JSType::JS_API_LIST: + return "List"; + case JSType::JS_API_LIST_ITERATOR: + return "ListIterator"; + case JSType::JS_API_LINKED_LIST: + return "LinkedList"; + case JSType::JS_API_LINKED_LIST_ITERATOR: + return "LinkedListIterator"; default: { CString ret = "unknown type "; return ret + static_cast(type); @@ -764,6 +777,18 @@ static void DumpObject(TaggedObject *obj, std::ostream &os) case JSType::JS_API_STACK_ITERATOR: JSAPIStackIterator::Cast(obj)->Dump(os); break; + case JSType::JS_API_LIST: + JSAPIList::Cast(obj)->Dump(os); + break; + case JSType::JS_API_LIST_ITERATOR: + JSAPIListIterator::Cast(obj)->Dump(os); + break; + case JSType::JS_API_LINKED_LIST: + JSAPILinkedList::Cast(obj)->Dump(os); + break; + case JSType::JS_API_LINKED_LIST_ITERATOR: + JSAPILinkedListIterator::Cast(obj)->Dump(os); + break; case JSType::SOURCE_TEXT_MODULE_RECORD: SourceTextModule::Cast(obj)->Dump(os); break; @@ -1007,6 +1032,58 @@ void LinkedHashMap::Dump(std::ostream &os) const } } +void TaggedDoubleList::Dump(std::ostream &os) const +{ + DISALLOW_GARBAGE_COLLECTION; + int capacity = NumberOfNodes(); + os << " - node num: " << std::dec << capacity << "\n"; + os << " - delete node num: " << std::dec << NumberOfDeletedNodes() << "\n"; + os << "head-next: "; + // 5 : 5 first element next ptr + GetElement(5).D(); + os << "head-pre: "; + // 6 : 6 first element per ptr + GetElement(6).D(); + os << "\n"; + int i = 0; + int next = GetElement(5).GetInt(); + while (capacity > i) { + os << " value: "; + GetElement(next).DumpTaggedValue(os); + os << " next: "; + // 1 : 1 current element next ptr offset + GetElement(next + 1).D(); + os << " pre: "; + // 2 : 2 current element pre ptr offset + GetElement(next + 2).D(); + os << "\n"; + next = GetElement(next + 1).GetInt(); + i++; + } +} + +void TaggedSingleList::Dump(std::ostream &os) const +{ + DISALLOW_GARBAGE_COLLECTION; + int capacity = NumberOfNodes(); + os << "head-next: "; + // 5 : 5 first element next ptr + GetElement(5).D(); + os << "\n"; + int i = 0; + int next = GetElement(5).GetInt(); + while (capacity > i) { + os << " value: "; + GetElement(next).DumpTaggedValue(os); + os << " next: "; + // 1 : 1 current element next ptr offset + GetElement(next + 1).D(); + os << "\n"; + next = GetElement(next + 1).GetInt(); + i++; + } +} + void JSObject::Dump(std::ostream &os) const { DISALLOW_GARBAGE_COLLECTION; @@ -1561,14 +1638,14 @@ void JSArray::Dump(std::ostream &os) const void JSAPIArrayList::Dump(std::ostream &os) const { - os << " - length: " << std::dec << GetLength().GetArrayLength() << "\n"; + os << " - length: " << std::dec << GetSize() << "\n"; JSObject::Dump(os); } void JSAPIArrayListIterator::Dump(std::ostream &os) const { JSAPIArrayList *arrayList = JSAPIArrayList::Cast(GetIteratedArrayList().GetTaggedObject()); - os << " - length: " << std::dec << arrayList->GetLength().GetArrayLength() << "\n"; + os << " - length: " << std::dec << arrayList->GetSize() << "\n"; os << " - nextIndex: " << std::dec << GetNextIndex() << "\n"; JSObject::Dump(os); } @@ -1611,6 +1688,80 @@ void JSArrayIterator::Dump(std::ostream &os) const JSObject::Dump(os); } +void JSAPIList::Dump(std::ostream &os) const +{ + TaggedSingleList *list = TaggedSingleList::Cast(GetSingleList().GetTaggedObject()); + os << " - length: " << std::dec << list->GetCapacityFromTaggedArray() << "\n"; + os << " - node num: " << std::dec << list->NumberOfNodes() << "\n"; + os << " - delete node num: " << std::dec << list->NumberOfDeletedNodes() << "\n"; + JSObject::Dump(os); + list->Dump(os); +} + +void JSAPIList::DumpForSnapshot(std::vector> &vec) const +{ + TaggedSingleList *map = TaggedSingleList::Cast(GetSingleList().GetTaggedObject()); + map->DumpForSnapshot(vec); + + JSObject::DumpForSnapshot(vec); +} + +void JSAPIListIterator::Dump(std::ostream &os) const +{ + TaggedSingleList *list = TaggedSingleList::Cast(GetIteratedList().GetTaggedObject()); + os << " - length: " << std::dec << list->GetCapacityFromTaggedArray() << "\n"; + os << " - node num: " << std::dec << list->NumberOfNodes() << "\n"; + os << " - delete node num: " << std::dec << list->NumberOfDeletedNodes() << "\n"; + os << " - nextIndex: " << std::dec << GetNextIndex() << "\n"; + JSObject::Dump(os); + list->Dump(os); +} + +void JSAPIListIterator::DumpForSnapshot(std::vector> &vec) const +{ + TaggedSingleList *list = TaggedSingleList::Cast(GetIteratedList().GetTaggedObject()); + list->DumpForSnapshot(vec); + vec.push_back(std::make_pair(CString("NextIndex"), JSTaggedValue(GetNextIndex()))); + JSObject::DumpForSnapshot(vec); +} + +void JSAPILinkedList::Dump(std::ostream &os) const +{ + TaggedDoubleList *linkedList = TaggedDoubleList::Cast(GetDoubleList().GetTaggedObject()); + os << " - length: " << std::dec << linkedList->GetCapacityFromTaggedArray() << "\n"; + os << " - node num: " << std::dec << linkedList->NumberOfNodes() << "\n"; + os << " - delete node num: " << std::dec << linkedList->NumberOfDeletedNodes() << "\n"; + JSObject::Dump(os); + linkedList->Dump(os); +} + +void JSAPILinkedList::DumpForSnapshot(std::vector> &vec) const +{ + TaggedDoubleList *map = TaggedDoubleList::Cast(GetDoubleList().GetTaggedObject()); + map->DumpForSnapshot(vec); + + JSObject::DumpForSnapshot(vec); +} + +void JSAPILinkedListIterator::Dump(std::ostream &os) const +{ + TaggedDoubleList *linkedList = TaggedDoubleList::Cast(GetIteratedLinkedList().GetTaggedObject()); + os << " - length: " << std::dec << linkedList->GetCapacityFromTaggedArray() << "\n"; + os << " - node num: " << std::dec << linkedList->NumberOfNodes() << "\n"; + os << " - delete node num: " << std::dec << linkedList->NumberOfDeletedNodes() << "\n"; + os << " - nextIndex: " << std::dec << GetNextIndex() << "\n"; + JSObject::Dump(os); + linkedList->Dump(os); +} + +void JSAPILinkedListIterator::DumpForSnapshot(std::vector> &vec) const +{ + TaggedDoubleList *linkedList = TaggedDoubleList::Cast(GetIteratedLinkedList().GetTaggedObject()); + linkedList->DumpForSnapshot(vec); + vec.push_back(std::make_pair(CString("NextIndex"), JSTaggedValue(GetNextIndex()))); + JSObject::DumpForSnapshot(vec); +} + void JSAPIQueue::Dump(std::ostream &os) const { os << " - length: " << std::dec << GetSize() << "\n"; @@ -3082,6 +3233,18 @@ static void DumpObject(TaggedObject *obj, case JSType::JS_API_STACK_ITERATOR: JSAPIStackIterator::Cast(obj)->DumpForSnapshot(vec); return; + case JSType::JS_API_LIST: + JSAPIList::Cast(obj)->DumpForSnapshot(vec); + return; + case JSType::JS_API_LINKED_LIST: + JSAPILinkedList::Cast(obj)->DumpForSnapshot(vec); + return; + case JSType::JS_API_LIST_ITERATOR: + JSAPIListIterator::Cast(obj)->DumpForSnapshot(vec); + return; + case JSType::JS_API_LINKED_LIST_ITERATOR: + JSAPILinkedListIterator::Cast(obj)->DumpForSnapshot(vec); + return; case JSType::SOURCE_TEXT_MODULE_RECORD: SourceTextModule::Cast(obj)->DumpForSnapshot(vec); return; @@ -3312,6 +3475,30 @@ void TaggedTreeSet::DumpForSnapshot(std::vector> &vec) const +{ + DISALLOW_GARBAGE_COLLECTION; + int capacity = NumberOfNodes(); + for (int index = 0; index < capacity; index++) { + JSTaggedValue val = GetElement(index); + CString str; + KeyToStd(str, JSTaggedValue(index)); + vec.push_back(std::make_pair(str, val)); + } +} + +void TaggedSingleList::DumpForSnapshot(std::vector> &vec) const +{ + DISALLOW_GARBAGE_COLLECTION; + int capacity = NumberOfNodes(); + for (int index = 0; index < capacity; index++) { + JSTaggedValue val = GetElement(index); + CString str; + KeyToStd(str, JSTaggedValue(index)); + vec.push_back(std::make_pair(str, val)); + } +} + void JSObject::DumpForSnapshot(std::vector> &vec) const { DISALLOW_GARBAGE_COLLECTION; @@ -3769,6 +3956,9 @@ void GlobalEnv::DumpForSnapshot(std::vector> & std::make_pair(CString("PlainArrayIteratorPrototype"), globalConst->GetPlainArrayIteratorPrototype())); vec.push_back(std::make_pair(CString("DequeIteratorPrototype"), globalConst->GetDequeIteratorPrototype())); vec.push_back(std::make_pair(CString("StackIteratorPrototype"), globalConst->GetStackIteratorPrototype())); + vec.push_back(std::make_pair(CString( + "LinkedListIteratorPrototype"), globalConst->GetLinkedListIteratorPrototype())); + vec.push_back(std::make_pair(CString("ListIteratorPrototype"), globalConst->GetListIteratorPrototype())); } void JSDataView::DumpForSnapshot(std::vector> &vec) const diff --git a/ecmascript/global_env_constants.cpp b/ecmascript/global_env_constants.cpp index 550339f457..34809cbe4b 100644 --- a/ecmascript/global_env_constants.cpp +++ b/ecmascript/global_env_constants.cpp @@ -29,6 +29,8 @@ #include "ecmascript/jobs/pending_job.h" #include "ecmascript/js_api_arraylist_iterator.h" #include "ecmascript/js_api_deque_iterator.h" +#include "ecmascript/js_api_linked_list_iterator.h" +#include "ecmascript/js_api_list_iterator.h" #include "ecmascript/js_api_plain_array_iterator.h" #include "ecmascript/js_api_queue_iterator.h" #include "ecmascript/js_api_stack_iterator.h" @@ -190,6 +192,11 @@ void GlobalEnvConstants::InitRootsClass([[maybe_unused]] JSThread *thread, JSHCl factory->NewEcmaDynClass(dynClassClass, JSAPIArrayListIterator::SIZE, JSType::JS_API_ARRAYLIST_ITERATOR)); SetConstant(ConstantIndex::JS_API_DEQUE_ITERATOR_CLASS_INDEX, factory->NewEcmaDynClass(dynClassClass, JSAPIDequeIterator::SIZE, JSType::JS_API_DEQUE_ITERATOR)); + SetConstant( + ConstantIndex::JS_API_LINKED_LIST_ITERATOR_CLASS_INDEX, + factory->NewEcmaDynClass(dynClassClass, JSAPILinkedListIterator::SIZE, JSType::JS_API_LINKED_LIST_ITERATOR)); + SetConstant(ConstantIndex::JS_API_LIST_ITERATOR_CLASS_INDEX, + factory->NewEcmaDynClass(dynClassClass, JSAPIListIterator::SIZE, JSType::JS_API_LIST_ITERATOR)); SetConstant( ConstantIndex::JS_API_PLAIN_ARRAY_ITERATOR_CLASS_INDEX, factory->NewEcmaDynClass(dynClassClass, JSAPIPlainArrayIterator::SIZE, JSType::JS_API_PLAIN_ARRAY_ITERATOR)); @@ -246,6 +253,10 @@ void GlobalEnvConstants::InitGlobalConstant(JSThread *thread) SetConstant(ConstantIndex::STACK_ITERATOR_PROTOTYPE_INDEX, JSTaggedValue::Undefined()); SetConstant(ConstantIndex::VECTOR_FUNCTION_INDEX, JSTaggedValue::Undefined()); SetConstant(ConstantIndex::VECTOR_ITERATOR_PROTOTYPE_INDEX, JSTaggedValue::Undefined()); + SetConstant(ConstantIndex::LIST_FUNCTION_INDEX, JSTaggedValue::Undefined()); + SetConstant(ConstantIndex::LINKED_LIST_FUNCTION_INDEX, JSTaggedValue::Undefined()); + SetConstant(ConstantIndex::LIST_ITERATOR_PROTOTYPE_INDEX, JSTaggedValue::Undefined()); + SetConstant(ConstantIndex::LINKED_LIST_ITERATOR_PROTOTYPE_INDEX, JSTaggedValue::Undefined()); /* SymbolTable *RegisterSymbols */ SetConstant(ConstantIndex::NAME_STRING_INDEX, factory->NewFromASCIINonMovable("name")); SetConstant(ConstantIndex::GETPROTOTYPEOF_STRING_INDEX, factory->NewFromASCIINonMovable("getPrototypeOf")); diff --git a/ecmascript/global_env_constants.h b/ecmascript/global_env_constants.h index 933a6d500a..44d0e77fdc 100644 --- a/ecmascript/global_env_constants.h +++ b/ecmascript/global_env_constants.h @@ -85,6 +85,8 @@ class JSThread; V(JSTaggedValue, JSAPIArrayListIteratorClass, JS_API_ARRAYLIST_ITERATOR_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, JSAPIDequeIteratorClass, JS_API_DEQUE_ITERATOR_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, JSAPIPlainArrayIteratorClass, JS_API_PLAIN_ARRAY_ITERATOR_CLASS_INDEX, ecma_roots_class) \ + V(JSTaggedValue, JSAPILinkedListIteratorClass, JS_API_LINKED_LIST_ITERATOR_CLASS_INDEX, ecma_roots_class) \ + V(JSTaggedValue, JSAPIListIteratorClass, JS_API_LIST_ITERATOR_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, JSAPIQueueIteratorClass, JS_API_QUEUE_ITERATOR_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, JSAPIStackIteratorClass, JS_API_STACK_ITERATOR_CLASS_INDEX, ecma_roots_class) \ V(JSTaggedValue, JSAPIVectorIteratorClass, JS_API_VECTOR_ITERATOR_CLASS_INDEX, ecma_roots_class) \ @@ -125,6 +127,10 @@ class JSThread; V(JSTaggedValue, PlainArrayFunction, PLAIN_ARRAY_FUNCTION_INDEX, PlainArrayFunction) \ V(JSTaggedValue, DequeIteratorPrototype, DEQUE_ITERATOR_PROTOTYPE_INDEX, DequeIterator) \ V(JSTaggedValue, StackIteratorPrototype, STACK_ITERATOR_PROTOTYPE_INDEX, StackIterator) \ + V(JSTaggedValue, ListFunction, LIST_FUNCTION_INDEX, ListFunction) \ + V(JSTaggedValue, LinkedListFunction, LINKED_LIST_FUNCTION_INDEX, LinkedListFunction) \ + V(JSTaggedValue, ListIteratorPrototype, LIST_ITERATOR_PROTOTYPE_INDEX, ListIterator) \ + V(JSTaggedValue, LinkedListIteratorPrototype, LINKED_LIST_ITERATOR_PROTOTYPE_INDEX, LinkedListIterator) \ /* SymbolTable*RegisterSymbols */ \ V(JSTaggedValue, NameString, NAME_STRING_INDEX, name) \ V(JSTaggedValue, GetPrototypeOfString, GETPROTOTYPEOF_STRING_INDEX, getPrototypeOf) \ diff --git a/ecmascript/ic/ic_runtime.cpp b/ecmascript/ic/ic_runtime.cpp index 92a435ee4c..85f1921ab2 100644 --- a/ecmascript/ic/ic_runtime.cpp +++ b/ecmascript/ic/ic_runtime.cpp @@ -135,7 +135,7 @@ void ICRuntime::TraceIC([[maybe_unused]] JSHandle receiver, JSTaggedValue LoadICRuntime::LoadMiss(JSHandle receiver, JSHandle key) { - if (receiver->IsTypedArray() || !receiver->IsJSObject()) { + if (receiver->IsTypedArray() || !receiver->IsJSObject() || receiver->IsSpecialContainer()) { return JSTaggedValue::GetProperty(thread_, receiver, key).GetValue().GetTaggedValue(); } diff --git a/ecmascript/interpreter/fast_runtime_stub-inl.h b/ecmascript/interpreter/fast_runtime_stub-inl.h index 62f347e8fa..ccf68f35d0 100644 --- a/ecmascript/interpreter/fast_runtime_stub-inl.h +++ b/ecmascript/interpreter/fast_runtime_stub-inl.h @@ -23,6 +23,8 @@ #include "ecmascript/interpreter/interpreter.h" #include "ecmascript/js_api_arraylist.h" #include "ecmascript/js_api_deque.h" +#include "ecmascript/js_api_linked_list.h" +#include "ecmascript/js_api_list.h" #include "ecmascript/js_api_plain_array.h" #include "ecmascript/js_api_queue.h" #include "ecmascript/js_api_stack.h" @@ -1411,6 +1413,14 @@ JSTaggedValue FastRuntimeStub::GetContainerProperty(JSThread *thread, JSTaggedVa res = JSAPIVector::Get(thread, JSHandle::Cast(self), index); break; } + case JSType::JS_API_LIST: { + res = JSAPIList::Cast(receiver.GetTaggedObject())->Get(index); + break; + } + case JSType::JS_API_LINKED_LIST: { + res = JSAPILinkedList::Cast(receiver.GetTaggedObject())->Get(index); + break; + } default: break; } @@ -1428,9 +1438,11 @@ JSTaggedValue FastRuntimeStub::SetContainerProperty(JSThread *thread, JSTaggedVa case JSType::JS_API_QUEUE: res = JSAPIQueue::Cast(receiver.GetTaggedObject())->Set(thread, index, value); break; - case JSType::JS_API_PLAIN_ARRAY: - res = JSAPIPlainArray::Set(thread, JSHandle (thread, receiver), index, value); + case JSType::JS_API_PLAIN_ARRAY: { + JSHandle plainArray(thread, receiver); + res = JSAPIPlainArray::Set(thread, plainArray, index, value); break; + } case JSType::JS_API_DEQUE: res = JSAPIDeque::Cast(receiver.GetTaggedObject())->Set(thread, index, value); break; @@ -1440,6 +1452,16 @@ JSTaggedValue FastRuntimeStub::SetContainerProperty(JSThread *thread, JSTaggedVa case JSType::JS_API_VECTOR: res = JSAPIVector::Cast(receiver.GetTaggedObject())->Set(thread, index, value); break; + case JSType::JS_API_LIST: { + JSHandle singleList(thread, receiver); + res = JSAPIList::Set(thread, singleList, index, JSHandle(thread, value)); + break; + } + case JSType::JS_API_LINKED_LIST: { + JSHandle doubleList(thread, receiver); + res = JSAPILinkedList::Set(thread, doubleList, index, JSHandle(thread, value)); + break; + } default: break; } diff --git a/ecmascript/js_api_arraylist.cpp b/ecmascript/js_api_arraylist.cpp index b21f0e7e03..f50d2ed1e8 100644 --- a/ecmascript/js_api_arraylist.cpp +++ b/ecmascript/js_api_arraylist.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 @@ -117,7 +117,7 @@ JSTaggedValue JSAPIArrayList::Get(JSThread *thread, const uint32_t index) bool JSAPIArrayList::IsEmpty(const JSHandle &arrayList) { - return arrayList->GetLength().GetArrayLength() == 0; + return arrayList->GetSize() == 0; } int JSAPIArrayList::GetIndexOf(JSThread *thread, const JSHandle &arrayList, @@ -226,14 +226,14 @@ JSTaggedValue JSAPIArrayList::ReplaceAllElements(JSThread *thread, const JSHandl const JSHandle &callbackFn, const JSHandle &thisArg) { - JSHandle arraylist = JSHandle::Cast(thisHandle); - uint32_t length = static_cast(arraylist->GetSize()); + JSHandle arrayList = JSHandle::Cast(thisHandle); + uint32_t length = static_cast(arrayList->GetSize()); JSMutableHandle key(thread, JSTaggedValue::Undefined()); JSMutableHandle kValue(thread, JSTaggedValue::Undefined()); const size_t argsLength = 3; JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); for (uint32_t k = 0; k < length; k++) { - kValue.Update(arraylist->Get(thread, k)); + kValue.Update(arrayList->Get(thread, k)); key.Update(JSTaggedValue(k)); EcmaRuntimeCallInfo info = EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFn, thisArg, undefined, argsLength); @@ -241,7 +241,7 @@ JSTaggedValue JSAPIArrayList::ReplaceAllElements(JSThread *thread, const JSHandl JSTaggedValue funcResult = JSFunction::Call(&info); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult); - arraylist->Set(thread, k, funcResult); + arrayList->Set(thread, k, funcResult); } return JSTaggedValue::Undefined(); @@ -338,7 +338,7 @@ JSHandle JSAPIArrayList::GrowCapacity(const JSThread *thread, const return newElements; } -bool JSAPIArrayList::Has(JSTaggedValue value) const +bool JSAPIArrayList::Has(const JSTaggedValue value) const { TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject()); int32_t length = GetSize(); @@ -368,10 +368,10 @@ JSHandle JSAPIArrayList::OwnKeys(JSThread *thread, const JSHandle &obj, - const JSHandle &key, PropertyDescriptor &desc) + const JSHandle &key) { uint32_t index = 0; - if (!UNLIKELY(JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) { + if (UNLIKELY(!JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) { THROW_TYPE_ERROR_AND_RETURN(thread, "Can not obtain attributes of no-number type", false); } @@ -379,7 +379,10 @@ bool JSAPIArrayList::GetOwnProperty(JSThread *thread, const JSHandle= length) { THROW_RANGE_ERROR_AND_RETURN(thread, "GetOwnProperty index out-of-bounds", false); } - return JSObject::GetOwnProperty(thread, JSHandle::Cast(obj), key, desc); + + obj->Get(thread, index); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false); + return true; } JSTaggedValue JSAPIArrayList::GetIteratorObj(JSThread *thread, const JSHandle &obj) @@ -389,4 +392,17 @@ JSTaggedValue JSAPIArrayList::GetIteratorObj(JSThread *thread, const JSHandle &obj, + const JSHandle &key) +{ + int length = obj->GetLength().GetInt(); + int index = key->GetInt(); + if (index < 0 || index >= length) { + THROW_RANGE_ERROR_AND_RETURN(thread, "GetProperty index out-of-bounds", + OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false))); + } + + return OperationResult(thread, obj->Get(thread, index), PropertyMetaData(false)); +} } // namespace panda::ecmascript diff --git a/ecmascript/js_api_arraylist.h b/ecmascript/js_api_arraylist.h index 41ab8b1765..2561062129 100644 --- a/ecmascript/js_api_arraylist.h +++ b/ecmascript/js_api_arraylist.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 @@ -67,13 +67,15 @@ public: JSTaggedValue Set(JSThread *thread, const uint32_t index, JSTaggedValue value); JSTaggedValue Get(JSThread *thread, const uint32_t index); - bool Has(JSTaggedValue value) const; + bool Has(const JSTaggedValue value) const; static JSHandle OwnKeys(JSThread *thread, const JSHandle &obj); static bool GetOwnProperty(JSThread *thread, const JSHandle &obj, - const JSHandle &key, PropertyDescriptor &desc); + const JSHandle &key); + static OperationResult GetProperty(JSThread *thread, const JSHandle &obj, + const JSHandle &key); inline int GetSize() const { - return GetLength().GetArrayLength(); + return GetLength().GetInt(); } static constexpr size_t LENGTH_OFFSET = JSObject::SIZE; diff --git a/ecmascript/js_api_arraylist_iterator.cpp b/ecmascript/js_api_arraylist_iterator.cpp index 70f9a823a3..e74bbd06d2 100644 --- a/ecmascript/js_api_arraylist_iterator.cpp +++ b/ecmascript/js_api_arraylist_iterator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/js_api_arraylist_iterator.h b/ecmascript/js_api_arraylist_iterator.h index 6067b5aff0..377ff00c27 100644 --- a/ecmascript/js_api_arraylist_iterator.h +++ b/ecmascript/js_api_arraylist_iterator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/js_api_deque.cpp b/ecmascript/js_api_deque.cpp index c8ac13db46..c7eb35c695 100644 --- a/ecmascript/js_api_deque.cpp +++ b/ecmascript/js_api_deque.cpp @@ -161,6 +161,7 @@ JSTaggedValue JSAPIDeque::Get(const uint32_t index) JSTaggedValue JSAPIDeque::Set(JSThread *thread, const uint32_t index, JSTaggedValue value) { + ASSERT(index < GetSize()); TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject()); uint32_t capacity = elements->GetLength(); uint32_t first = GetFirst(); @@ -214,10 +215,10 @@ JSHandle JSAPIDeque::OwnKeys(JSThread *thread, const JSHandle &deque, - const JSHandle &key, PropertyDescriptor &desc) + const JSHandle &key) { uint32_t index = 0; - if (UNLIKELY(JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) { + if (UNLIKELY(!JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) { THROW_TYPE_ERROR_AND_RETURN(thread, "Can not obtain attributes of no-number type", false); } @@ -225,7 +226,9 @@ bool JSAPIDeque::GetOwnProperty(JSThread *thread, const JSHandle &de if (index >= length) { THROW_RANGE_ERROR_AND_RETURN(thread, "GetOwnProperty index out-of-bounds", false); } - return JSObject::GetOwnProperty(thread, JSHandle::Cast(deque), key, desc); + + deque->Get(index); + return true; } JSTaggedValue JSAPIDeque::GetIteratorObj(JSThread *thread, const JSHandle &deque) @@ -235,4 +238,17 @@ JSTaggedValue JSAPIDeque::GetIteratorObj(JSThread *thread, const JSHandle &obj, + const JSHandle &key) +{ + int length = static_cast(obj->GetSize()); + int index = key->GetInt(); + if (index < 0 || index >= length) { + THROW_RANGE_ERROR_AND_RETURN(thread, "GetProperty index out-of-bounds", + OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false))); + } + + return OperationResult(thread, obj->Get(index), PropertyMetaData(false)); +} } // namespace panda::ecmascript diff --git a/ecmascript/js_api_deque.h b/ecmascript/js_api_deque.h index afce0c6a87..ed56b1bea0 100644 --- a/ecmascript/js_api_deque.h +++ b/ecmascript/js_api_deque.h @@ -39,9 +39,9 @@ public: static JSHandle OwnKeys(JSThread *thread, const JSHandle &deque); - static bool GetOwnProperty(JSThread *thread, const JSHandle &deque, const JSHandle &key, - PropertyDescriptor &desc); - + static bool GetOwnProperty(JSThread *thread, const JSHandle &deque, const JSHandle &key); + static OperationResult GetProperty(JSThread *thread, const JSHandle &obj, + const JSHandle &key); JSTaggedValue GetFront(); JSTaggedValue GetTail(); diff --git a/ecmascript/js_api_deque_iterator.cpp b/ecmascript/js_api_deque_iterator.cpp index f4905b22f5..ab77f9179a 100644 --- a/ecmascript/js_api_deque_iterator.cpp +++ b/ecmascript/js_api_deque_iterator.cpp @@ -1,4 +1,3 @@ - /* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -36,23 +35,26 @@ JSTaggedValue JSAPIDequeIterator::Next(EcmaRuntimeCallInfo *argv) THROW_TYPE_ERROR_AND_RETURN(thread, "this value is not an deque iterator", JSTaggedValue::Exception()); } JSHandle iter(input); - JSHandle deque(thread, iter->GetIteratedDeque()); + JSHandle iteratorDeque(thread, iter->GetIteratedDeque()); JSHandle undefinedHandle = thread->GlobalConstants()->GetHandledUndefined(); - if (deque->IsUndefined()) { + if (iteratorDeque->IsUndefined()) { return JSIterator::CreateIterResultObject(thread, undefinedHandle, true).GetTaggedValue(); } + JSHandle deque = JSHandle::Cast(iteratorDeque); uint32_t index = iter->GetNextIndex(); - JSHandle elements(thread, JSHandle(deque)->GetElements()); + JSHandle elements(thread, deque->GetElements()); array_size_t capacity = elements->GetLength(); - uint32_t last = JSHandle(deque)->GetLast(); + uint32_t first = deque->GetFirst(); + uint32_t last = deque->GetLast(); if (index == last) { iter->SetIteratedDeque(thread, undefinedHandle); return JSIterator::CreateIterResultObject(thread, undefinedHandle, true).GetTaggedValue(); } ASSERT(capacity != 0); iter->SetNextIndex((index + 1) % capacity); - JSHandle value = JSTaggedValue::GetProperty(thread, deque, index).GetValue(); + uint32_t elementIndex = (index + capacity - first) % capacity; + JSHandle value = JSTaggedValue::GetProperty(thread, iteratorDeque, elementIndex).GetValue(); return JSIterator::CreateIterResultObject(thread, value, false).GetTaggedValue(); } diff --git a/ecmascript/js_api_linked_list.cpp b/ecmascript/js_api_linked_list.cpp new file mode 100644 index 0000000000..7b62f5760b --- /dev/null +++ b/ecmascript/js_api_linked_list.cpp @@ -0,0 +1,234 @@ +/* + * 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. + */ + +#include "js_api_linked_list.h" +#include "ecmascript/js_api_linked_list_iterator.h" +#include "ecmascript/js_tagged_value.h" +#include "ecmascript/object_factory.h" +#include "tagged_list.h" + +namespace panda::ecmascript { +JSTaggedValue JSAPILinkedList::Insert(JSThread *thread, const JSHandle &list, + const JSHandle &value, const int index) +{ + JSHandle doubleList(thread, list->GetDoubleList()); + int nodeLength = doubleList->Length(); + if (index < 0 || index > nodeLength) { + THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", + JSTaggedValue::Exception()); + } + JSTaggedValue newList = TaggedDoubleList::Insert(thread, doubleList, value, index); + list->SetDoubleList(thread, newList); + return JSTaggedValue::True(); +} + +void JSAPILinkedList::Clear(JSThread *thread) +{ + TaggedDoubleList *doubleList = TaggedDoubleList::Cast(GetDoubleList().GetTaggedObject()); + doubleList->Clear(thread); +} + +JSHandle JSAPILinkedList::Clone(JSThread *thread, const JSHandle &list) +{ + JSHandle doubleList(thread, list->GetDoubleList()); + int capacity = doubleList->NumberOfNodes(); + JSHandle newLinkedList = thread->GetEcmaVM()->GetFactory()->NewJSAPILinkedList(); + JSTaggedValue newTaggedList = TaggedDoubleList::Create(thread, capacity); + JSHandle newDoubleList(thread, newTaggedList); + doubleList->CopyArray(thread, newDoubleList); + newLinkedList->SetDoubleList(thread, newDoubleList.GetTaggedValue()); + return newLinkedList; +} + +JSTaggedValue JSAPILinkedList::RemoveFirst(JSThread *thread, const JSHandle &list) +{ + JSHandle doubleList(thread, list->GetDoubleList()); + int nodeLength = doubleList->Length(); + if (nodeLength < 0) { + THROW_RANGE_ERROR_AND_RETURN(thread, "there is no element", JSTaggedValue::Exception()); + } + return doubleList->RemoveFirst(thread); +} + +JSTaggedValue JSAPILinkedList::RemoveLast(JSThread *thread, const JSHandle &list) +{ + JSHandle doubleList(thread, list->GetDoubleList()); + int nodeLength = doubleList->Length(); + if (nodeLength < 0) { + THROW_RANGE_ERROR_AND_RETURN(thread, "there is no element", JSTaggedValue::Exception()); + } + return doubleList->RemoveLast(thread); +} + +JSTaggedValue JSAPILinkedList::RemoveByIndex(JSThread *thread, JSHandle &list, const int index) +{ + JSHandle doubleList(thread, list->GetDoubleList()); + int nodeLength = doubleList->Length(); + if (index < 0 || index >= nodeLength) { + THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", JSTaggedValue::Exception()); + } + return doubleList->RemoveByIndex(thread, index); +} + +JSTaggedValue JSAPILinkedList::Remove(JSThread *thread, const JSTaggedValue &element) +{ + TaggedDoubleList *doubleList = TaggedDoubleList::Cast(GetDoubleList().GetTaggedObject()); + int nodeLength = doubleList->Length(); + if (nodeLength < 0) { + return JSTaggedValue::False(); + } + return doubleList->Remove(thread, element); +} + +JSTaggedValue JSAPILinkedList::RemoveFirstFound(JSThread *thread, JSHandle &list, + const JSTaggedValue &element) +{ + JSHandle doubleList(thread, list->GetDoubleList()); + int nodeLength = doubleList->Length(); + if (nodeLength < 0) { + THROW_RANGE_ERROR_AND_RETURN(thread, "there is no element", JSTaggedValue::Exception()); + } + return TaggedDoubleList::RemoveFirstFound(thread, doubleList, element); +} + +JSTaggedValue JSAPILinkedList::RemoveLastFound(JSThread *thread, JSHandle &list, + const JSTaggedValue &element) +{ + JSHandle doubleList(thread, list->GetDoubleList()); + int nodeLength = doubleList->Length(); + if (nodeLength < 0) { + THROW_RANGE_ERROR_AND_RETURN(thread, "there is no element", JSTaggedValue::Exception()); + } + return TaggedDoubleList::RemoveLastFound(thread, doubleList, element); +} + +void JSAPILinkedList::Add(JSThread *thread, const JSHandle &list, const JSHandle &value) +{ + JSHandle doubleList(thread, list->GetDoubleList()); + JSTaggedValue newLinkedList = TaggedDoubleList::Add(thread, doubleList, value); + list->SetDoubleList(thread, newLinkedList); +} + +void JSAPILinkedList::AddFirst(JSThread *thread, const JSHandle &list, + const JSHandle &value) +{ + JSHandle doubleList(thread, list->GetDoubleList()); + JSTaggedValue newLinkedList = TaggedDoubleList::AddFirst(thread, doubleList, value); + list->SetDoubleList(thread, newLinkedList); +} + +JSTaggedValue JSAPILinkedList::GetFirst() +{ + JSTaggedValue res = TaggedDoubleList::Cast(GetDoubleList().GetTaggedObject())->GetFirst(); + if (res.IsHole()) { + return JSTaggedValue::Undefined(); + } + return res; +} + +JSTaggedValue JSAPILinkedList::GetLast() +{ + JSTaggedValue res = TaggedDoubleList::Cast(GetDoubleList().GetTaggedObject())->GetLast(); + if (res.IsHole()) { + return JSTaggedValue::Undefined(); + } + return res; +} + +JSTaggedValue JSAPILinkedList::Set(JSThread *thread, const JSHandle &list, + const int index, const JSHandle &value) +{ + JSHandle doubleList(thread, list->GetDoubleList()); + int nodeLength = doubleList->Length(); + if (index < 0 || index >= nodeLength) { + THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", JSTaggedValue::Exception()); + } + JSTaggedValue oldValue = doubleList->Get(index); + TaggedDoubleList::Set(thread, doubleList, index, value); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return oldValue; +} + +bool JSAPILinkedList::Has(const JSTaggedValue &element) +{ + TaggedDoubleList *doubleList = TaggedDoubleList::Cast(GetDoubleList().GetTaggedObject()); + return doubleList->Has(element); +} + +JSTaggedValue JSAPILinkedList::Get(const int index) +{ + TaggedDoubleList *doubleList = TaggedDoubleList::Cast(GetDoubleList().GetTaggedObject()); + int nodeLength = doubleList->Length(); + if (index < 0 || index >= nodeLength) { + return JSTaggedValue::Undefined(); + } + return doubleList->Get(index); +} + +JSTaggedValue JSAPILinkedList::GetIndexOf(const JSTaggedValue &element) +{ + TaggedDoubleList *doubleList = TaggedDoubleList::Cast(GetDoubleList().GetTaggedObject()); + return JSTaggedValue(doubleList->GetIndexOf(element)); +} + +JSTaggedValue JSAPILinkedList::GetLastIndexOf(const JSTaggedValue &element) +{ + TaggedDoubleList *doubleList = TaggedDoubleList::Cast(GetDoubleList().GetTaggedObject()); + return JSTaggedValue(doubleList->GetLastIndexOf(element)); +} + +JSTaggedValue JSAPILinkedList::ConvertToArray(const JSThread *thread, const JSHandle &list) +{ + JSHandle doubleList(thread, list->GetDoubleList()); + return TaggedDoubleList::ConvertToArray(thread, doubleList); +} + +JSHandle JSAPILinkedList::OwnKeys(JSThread *thread, const JSHandle &list) +{ + JSHandle doubleList(thread, list->GetDoubleList().GetTaggedObject()); + return TaggedDoubleList::OwnKeys(thread, doubleList); +} + +bool JSAPILinkedList::GetOwnProperty(JSThread *thread, const JSHandle &list, + const JSHandle &key) +{ + uint32_t index = 0; + if (UNLIKELY(!JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) { + THROW_TYPE_ERROR_AND_RETURN(thread, "Can not obtain attributes of no-number type", false); + } + JSHandle doubleList(thread, list->GetDoubleList()); + uint32_t length = static_cast(doubleList->Length()); + if (index >= length) { + THROW_RANGE_ERROR_AND_RETURN(thread, "the index out-of-bounds", false); + } + + list->Get(index); + return true; +} + +OperationResult JSAPILinkedList::GetProperty(JSThread *thread, const JSHandle &list, + const JSHandle &key) +{ + JSHandle doubleList(thread, list->GetDoubleList()); + int nodeLength = doubleList->Length(); + int index = key->GetInt(); + if (index < 0 || index >= nodeLength) { + THROW_RANGE_ERROR_AND_RETURN(thread, "the index out-of-bounds", + OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false))); + } + + return OperationResult(thread, doubleList->Get(index), PropertyMetaData(false)); +} +} // namespace panda::ecmascript diff --git a/ecmascript/js_api_linked_list.h b/ecmascript/js_api_linked_list.h new file mode 100644 index 0000000000..c317f5f18e --- /dev/null +++ b/ecmascript/js_api_linked_list.h @@ -0,0 +1,72 @@ +/* + * 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. + */ + +#ifndef ECMASCRIPT_JSAPILINKEDLIST_H +#define ECMASCRIPT_JSAPILINKEDLIST_H + +#include "js_object.h" +#include "js_tagged_value-inl.h" +#include "tagged_list.h" + +namespace panda::ecmascript { +class JSAPILinkedList : public JSObject { +public: + static constexpr int DEFAULT_CAPACITY_LENGTH = 10; + static JSAPILinkedList *Cast(ObjectHeader *object) + { + ASSERT(JSTaggedValue(object).IsJSAPILinkedList()); + return static_cast(object); + } + + static void Add(JSThread *thread, const JSHandle &list, const JSHandle &value); + static JSHandle Clone(JSThread *thread, const JSHandle &list); + static void AddFirst(JSThread *thread, const JSHandle &list, const JSHandle &value); + static JSTaggedValue Insert(JSThread *thread, const JSHandle &list, + const JSHandle &value, const int index); + static JSTaggedValue Set(JSThread *thread, const JSHandle &list, + const int index, const JSHandle &value); + static JSTaggedValue ConvertToArray(const JSThread *thread, const JSHandle &list); + static JSHandle OwnKeys(JSThread *thread, const JSHandle &list); + static bool GetOwnProperty(JSThread *thread, const JSHandle &list, + const JSHandle &key); + static OperationResult GetProperty(JSThread *thread, const JSHandle &list, + const JSHandle &key); + static JSTaggedValue RemoveFirst(JSThread *thread, const JSHandle &list); + static JSTaggedValue RemoveLast(JSThread *thread, const JSHandle &list); + static JSTaggedValue RemoveByIndex(JSThread *thread, JSHandle &list, const int index); + static JSTaggedValue RemoveFirstFound(JSThread *thread, JSHandle &list, + const JSTaggedValue &element); + static JSTaggedValue RemoveLastFound(JSThread *thread, JSHandle &list, + const JSTaggedValue &element); + void Clear(JSThread *thread); + bool Has(const JSTaggedValue &element); + JSTaggedValue GetFirst(); + JSTaggedValue GetLast(); + JSTaggedValue Get(const int index); + JSTaggedValue Remove(JSThread *thread, const JSTaggedValue &element); + JSTaggedValue GetIndexOf(const JSTaggedValue &element); + JSTaggedValue GetLastIndexOf(const JSTaggedValue &element); + inline int Length() + { + return TaggedDoubleList::Cast(GetDoubleList().GetTaggedObject())->Length(); + } + static constexpr size_t DOUBLE_LIST_OFFSET = JSObject::SIZE; + ACCESSORS(DoubleList, DOUBLE_LIST_OFFSET, SIZE); + DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, DOUBLE_LIST_OFFSET, SIZE) + DECL_DUMP() +}; +} // namespace panda::ecmascript + +#endif // ECMASCRIPT_JSAPILinkedLIST_H diff --git a/ecmascript/js_api_linked_list_iterator.cpp b/ecmascript/js_api_linked_list_iterator.cpp new file mode 100644 index 0000000000..0579a10803 --- /dev/null +++ b/ecmascript/js_api_linked_list_iterator.cpp @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#include "js_api_linked_list_iterator.h" +#include "builtins/builtins_errors.h" +#include "ecmascript/base/typed_array_helper.h" +#include "ecmascript/base/typed_array_helper-inl.h" +#include "global_env.h" +#include "js_api_linked_list.h" +#include "js_array.h" +#include "object_factory.h" +#include "tagged_list.h" + +namespace panda::ecmascript { +using BuiltinsBase = base::BuiltinsBase; +JSTaggedValue JSAPILinkedListIterator::Next(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle input(BuiltinsBase::GetThis(argv)); + if (!input->IsJSAPILinkedListIterator()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "this value is not an linkedList iterator", JSTaggedValue::Exception()); + } + JSHandle iter(input); + JSHandle linkedList(thread, iter->GetIteratedLinkedList()); + JSHandle undefinedHandle = thread->GlobalConstants()->GetHandledUndefined(); + JSHandle list(linkedList); + if (linkedList->IsUndefined()) { + return JSIterator::CreateIterResultObject(thread, undefinedHandle, true).GetTaggedValue(); + } + int index = iter->GetNextIndex(); + int length = list->Length(); + if (index >= length) { + iter->SetIteratedLinkedList(thread, undefinedHandle); + return JSIterator::CreateIterResultObject(thread, undefinedHandle, true).GetTaggedValue(); + } + iter->SetNextIndex(index + 1); + JSHandle value(thread, list->Get(index)); + return JSIterator::CreateIterResultObject(thread, value, false).GetTaggedValue(); +} + +JSHandle JSAPILinkedListIterator::CreateLinkedListIterator(JSThread *thread, + const JSHandle &obj) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + if (!obj->IsJSAPILinkedList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPILinkedList", + thread->GlobalConstants()->GetHandledUndefined()); + } + JSHandle iter(factory->NewJSAPILinkedListIterator(JSHandle(obj))); + return iter; +} +} // namespace panda::ecmascript diff --git a/ecmascript/js_api_linked_list_iterator.h b/ecmascript/js_api_linked_list_iterator.h new file mode 100644 index 0000000000..ae3fddd12e --- /dev/null +++ b/ecmascript/js_api_linked_list_iterator.h @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#ifndef ECMASCRIPT_JS_API_LINKED_LIST_ITERATOR_H +#define ECMASCRIPT_JS_API_LINKED_LIST_ITERATOR_H + +#include "js_iterator.h" +#include "js_object.h" + +namespace panda::ecmascript { +class JSAPILinkedListIterator : public JSObject { +public: + static JSAPILinkedListIterator *Cast(ObjectHeader *obj) + { + ASSERT(JSTaggedValue(obj).IsJSAPILinkedListIterator()); + return static_cast(obj); + } + static JSTaggedValue Next(EcmaRuntimeCallInfo *argv); + static JSHandle CreateLinkedListIterator(JSThread *thread, const JSHandle &obj); + static constexpr size_t ITERATED_LINKED_LIST_OFFSET = JSObject::SIZE; + ACCESSORS(IteratedLinkedList, ITERATED_LINKED_LIST_OFFSET, NEXT_INDEX_OFFSET) + ACCESSORS_PRIMITIVE_FIELD(NextIndex, uint32_t, NEXT_INDEX_OFFSET, LAST_OFFSET) + DEFINE_ALIGN_SIZE(LAST_OFFSET); + + DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, ITERATED_LINKED_LIST_OFFSET, NEXT_INDEX_OFFSET) + + DECL_DUMP() +}; +} // namespace panda::ecmascript + +#endif // ECMASCRIPT_JS_LinkedList_ITERATOR_H \ No newline at end of file diff --git a/ecmascript/js_api_list.cpp b/ecmascript/js_api_list.cpp new file mode 100644 index 0000000000..811a854261 --- /dev/null +++ b/ecmascript/js_api_list.cpp @@ -0,0 +1,218 @@ +/* + * 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. + */ + +#include "js_api_list.h" +#include "ecmascript/js_api_list_iterator.h" +#include "ecmascript/js_array.h" +#include "ecmascript/js_function.h" +#include "ecmascript/js_handle.h" +#include "ecmascript/js_tagged_number.h" +#include "ecmascript/js_tagged_value.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/tagged_list.h" + +namespace panda::ecmascript { +void JSAPIList::Add(JSThread *thread, const JSHandle &list, const JSHandle &value) +{ + JSHandle singleList(thread, list->GetSingleList()); + JSTaggedValue newList = TaggedSingleList::Add(thread, singleList, value); + list->SetSingleList(thread, newList); +} + +JSTaggedValue JSAPIList::GetFirst() +{ + JSTaggedValue res = TaggedSingleList::Cast(GetSingleList().GetTaggedObject())->GetFirst(); + if (res.IsHole()) { + return JSTaggedValue::Undefined(); + } + return res; +} + +JSTaggedValue JSAPIList::GetLast() +{ + JSTaggedValue res = TaggedSingleList::Cast(GetSingleList().GetTaggedObject())->GetLast(); + if (res.IsHole()) { + return JSTaggedValue::Undefined(); + } + return res; +} + +JSTaggedValue JSAPIList::Insert(JSThread *thread, const JSHandle &list, const JSHandle &value, + const int index) +{ + JSHandle singleList(thread, list->GetSingleList()); + int nodeLength = singleList->Length(); + if (index < 0 || index > nodeLength) { + THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", JSTaggedValue::Exception()); + } + JSTaggedValue newList = TaggedSingleList::Insert(thread, singleList, value, index); + list->SetSingleList(thread, newList); + return JSTaggedValue::True(); +} + +JSTaggedValue JSAPIList::Set(JSThread *thread, const JSHandle &list, + const int index, const JSHandle &value) +{ + JSHandle singleList(thread, list->GetSingleList()); + int nodeLength = singleList->Length(); + if (index < 0 || index >= nodeLength) { + THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", JSTaggedValue::Exception()); + } + JSTaggedValue oldValue = singleList->Get(index); + TaggedSingleList::Set(thread, singleList, index, value); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + return oldValue; +} + +bool JSAPIList::Has(const JSTaggedValue &element) +{ + TaggedSingleList *singleList = TaggedSingleList::Cast(GetSingleList().GetTaggedObject()); + return singleList->Has(element); +} + +bool JSAPIList::IsEmpty() +{ + return TaggedSingleList::Cast(GetSingleList().GetTaggedObject())->IsEmpty(); +} + +JSTaggedValue JSAPIList::Get(const int index) +{ + TaggedSingleList *singleList = TaggedSingleList::Cast(GetSingleList().GetTaggedObject()); + int nodeLength = singleList->Length(); + if (index < 0 || index >= nodeLength) { + return JSTaggedValue::Undefined(); + } + return singleList->Get(index); +} + +JSTaggedValue JSAPIList::GetIndexOf(const JSTaggedValue &element) +{ + TaggedSingleList *singleList = TaggedSingleList::Cast(GetSingleList().GetTaggedObject()); + return JSTaggedValue(singleList->GetIndexOf(element)); +} + +JSTaggedValue JSAPIList::GetLastIndexOf(const JSTaggedValue &element) +{ + TaggedSingleList *singleList = TaggedSingleList::Cast(GetSingleList().GetTaggedObject()); + return JSTaggedValue(singleList->GetLastIndexOf(element)); +} + +void JSAPIList::Clear(JSThread *thread) +{ + TaggedSingleList *singleList = TaggedSingleList::Cast(GetSingleList().GetTaggedObject()); + singleList->Clear(thread); +} + +JSTaggedValue JSAPIList::RemoveByIndex(JSThread *thread, const JSHandle &list, const int &index) +{ + JSHandle singleList(thread, list->GetSingleList()); + int nodeLength = singleList->Length(); + if (index < 0 || index >= nodeLength) { + THROW_RANGE_ERROR_AND_RETURN(thread, "the index is out-of-bounds", JSTaggedValue::Exception()); + } + return singleList->RemoveByIndex(thread, index); +} + +JSTaggedValue JSAPIList::Remove(JSThread *thread, const JSTaggedValue &element) +{ + TaggedSingleList *singleList = TaggedSingleList::Cast(GetSingleList().GetTaggedObject()); + return singleList->Remove(thread, element); +} + +JSTaggedValue JSAPIList::ReplaceAllElements(JSThread *thread, const JSHandle &thisHandle, + const JSHandle &callbackFn, + const JSHandle &thisArg) +{ + JSHandle list = JSHandle::Cast(thisHandle); + JSHandle singleList(thread, list->GetSingleList()); + return TaggedSingleList::ReplaceAllElements(thread, thisHandle, callbackFn, thisArg, singleList); +} + +JSTaggedValue JSAPIList::Sort(JSThread *thread, const JSHandle &thisHandle, + const JSHandle &callbackFn) +{ + JSHandle list = JSHandle::Cast(thisHandle); + JSHandle singleList(thread, list->GetSingleList()); + return TaggedSingleList::Sort(thread, callbackFn, singleList); +} + +JSTaggedValue JSAPIList::Equal(JSThread *thread, const JSHandle &list) +{ + JSHandle compareList(thread, list->GetSingleList()); + return TaggedSingleList::Cast(GetSingleList().GetTaggedObject())->Equal(compareList); +} + +JSTaggedValue JSAPIList::ConvertToArray(const JSThread *thread, const JSHandle &list) +{ + JSHandle singleList(thread, list->GetSingleList()); + return TaggedSingleList::ConvertToArray(thread, singleList); +} + +JSTaggedValue JSAPIList::GetSubList(JSThread *thread, const JSHandle &list, + const int fromIndex, const int toIndex) +{ + JSHandle singleList(thread, list->GetSingleList()); + int nodeLength = singleList->Length(); + if (fromIndex < 0 || toIndex < 0 || toIndex >= nodeLength) { + THROW_RANGE_ERROR_AND_RETURN(thread, "the fromIndex or the toIndex is out-of-bounds", + JSTaggedValue::Exception()); + } + if (fromIndex >= nodeLength) { + THROW_RANGE_ERROR_AND_RETURN(thread, "the toIndex cannot be less than or equal to fromIndex", + JSTaggedValue::Exception()); + } + int len = TaggedSingleList::ELEMENTS_START_INDEX + (toIndex - fromIndex) * TaggedSingleList::ENTRY_SIZE; + JSHandle sublist = thread->GetEcmaVM()->GetFactory()->NewJSAPIList(); + JSHandle subSingleList(thread, TaggedSingleList::Create(thread, len)); + TaggedSingleList::GetSubList(thread, singleList, fromIndex, toIndex, subSingleList); + sublist->SetSingleList(thread, subSingleList); + return sublist.GetTaggedValue(); +} + +JSHandle JSAPIList::OwnKeys(JSThread *thread, const JSHandle &list) +{ + JSHandle singleList(thread, list->GetSingleList()); + return TaggedSingleList::OwnKeys(thread, singleList); +} + +bool JSAPIList::GetOwnProperty(JSThread *thread, const JSHandle &list, const JSHandle &key) +{ + uint32_t index = 0; + if (UNLIKELY(!JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) { + THROW_TYPE_ERROR_AND_RETURN(thread, "Can not obtain attributes of no-number type", false); + } + JSHandle singleList(thread, list->GetSingleList()); + uint32_t length = static_cast(singleList->Length()); + if (index >= length) { + THROW_RANGE_ERROR_AND_RETURN(thread, "GetOwnProperty index out-of-bounds", false); + } + list->Get(index); + return true; +} + +OperationResult JSAPIList::GetProperty(JSThread *thread, const JSHandle &list, + const JSHandle &key) +{ + JSHandle singleList(thread, list->GetSingleList()); + int nodeLength = singleList->Length(); + int index = key->GetInt(); + if (index < 0 || index >= nodeLength) { + THROW_RANGE_ERROR_AND_RETURN(thread, "GetProperty index out-of-bounds", + OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false))); + } + + return OperationResult(thread, singleList->Get(index), PropertyMetaData(false)); +} +} // namespace panda::ecmascript diff --git a/ecmascript/js_api_list.h b/ecmascript/js_api_list.h new file mode 100644 index 0000000000..6655f17e49 --- /dev/null +++ b/ecmascript/js_api_list.h @@ -0,0 +1,75 @@ +/* + * 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. + */ + +#ifndef ECMASCRIPT_JSAPILIST_H +#define ECMASCRIPT_JSAPILIST_H + +#include "js_object.h" +#include "js_tagged_value-inl.h" +#include "tagged_list.h" + +namespace panda::ecmascript { +class JSAPIList : public JSObject { +public: + static constexpr int DEFAULT_CAPACITY_LENGTH = 10; + static JSAPIList *Cast(ObjectHeader *object) + { + ASSERT(JSTaggedValue(object).IsJSAPIList()); + return static_cast(object); + } + + static void Add(JSThread *thread, const JSHandle &list, const JSHandle &value); + static JSTaggedValue Insert(JSThread *thread, const JSHandle &list, + const JSHandle &value, const int index); + static JSTaggedValue Set(JSThread *thread, const JSHandle &list, + const int index, const JSHandle &value); + static JSTaggedValue ReplaceAllElements(JSThread *thread, const JSHandle &thisHandle, + const JSHandle &callbackFn, + const JSHandle &thisArg); + static JSTaggedValue Sort(JSThread *thread, const JSHandle &thisHandle, + const JSHandle &callbackFn); + static JSTaggedValue ConvertToArray(const JSThread *thread, const JSHandle &list); + static JSTaggedValue GetSubList(JSThread *thread, const JSHandle &list, + const int fromIndex, const int toIndex); + static JSTaggedValue RemoveByIndex(JSThread *thread, const JSHandle &list, const int &index); + static JSHandle OwnKeys(JSThread *thread, const JSHandle &list); + static bool GetOwnProperty(JSThread *thread, const JSHandle &list, + const JSHandle &key); + static OperationResult GetProperty(JSThread *thread, const JSHandle &list, + const JSHandle &key); + + JSTaggedValue GetFirst(); + JSTaggedValue GetLast(); + bool IsEmpty(); + JSTaggedValue Get(const int index); + bool Has(const JSTaggedValue &element); + JSTaggedValue GetIndexOf(const JSTaggedValue &element); + JSTaggedValue GetLastIndexOf(const JSTaggedValue &element); + JSTaggedValue Equal(JSThread *thread, const JSHandle &list); + void Clear(JSThread *thread); + JSTaggedValue Remove(JSThread *thread, const JSTaggedValue &element); + inline int Length() + { + return TaggedSingleList::Cast(GetSingleList().GetTaggedObject())->Length(); + } + + static constexpr size_t SINGLY_LIST_OFFSET = JSObject::SIZE; + ACCESSORS(SingleList, SINGLY_LIST_OFFSET, SIZE); + DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, SINGLY_LIST_OFFSET, SIZE) + DECL_DUMP() +}; +} // namespace panda::ecmascript + +#endif // ECMASCRIPT_JSAPILIST_H diff --git a/ecmascript/js_api_list_iterator.cpp b/ecmascript/js_api_list_iterator.cpp new file mode 100644 index 0000000000..f68bd879ce --- /dev/null +++ b/ecmascript/js_api_list_iterator.cpp @@ -0,0 +1,63 @@ +/* + * 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. + */ + +#include "js_api_list_iterator.h" +#include "builtins/builtins_errors.h" +#include "ecmascript/base/typed_array_helper.h" +#include "ecmascript/base/typed_array_helper-inl.h" +#include "global_env.h" +#include "js_api_list.h" +#include "object_factory.h" +#include "tagged_list.h" + +namespace panda::ecmascript { +using BuiltinsBase = base::BuiltinsBase; +JSTaggedValue JSAPIListIterator::Next(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle input(BuiltinsBase::GetThis(argv)); + if (!input->IsJSAPIListIterator()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "this value is not an List iterator", JSTaggedValue::Exception()); + } + JSHandle iter(input); + JSHandle list(thread, iter->GetIteratedList()); + JSHandle undefinedHandle = thread->GlobalConstants()->GetHandledUndefined(); + JSHandle singleList(list); + if (list->IsUndefined()) { + return JSIterator::CreateIterResultObject(thread, undefinedHandle, true).GetTaggedValue(); + } + int index = iter->GetNextIndex(); + int length = singleList->Length(); + if (index >= length) { + iter->SetIteratedList(thread, undefinedHandle); + return JSIterator::CreateIterResultObject(thread, undefinedHandle, true).GetTaggedValue(); + } + iter->SetNextIndex(index + 1); + JSHandle value(thread, singleList->Get(index)); + return JSIterator::CreateIterResultObject(thread, value, false).GetTaggedValue(); +} + +JSHandle JSAPIListIterator::CreateListIterator(JSThread *thread, const JSHandle &obj) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + if (!obj->IsJSAPIList()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "obj is not JSAPIList", thread->GlobalConstants()->GetHandledUndefined()); + } + JSHandle iter(factory->NewJSAPIListIterator(JSHandle(obj))); + return iter; +} +} // namespace panda::ecmascript diff --git a/ecmascript/js_api_list_iterator.h b/ecmascript/js_api_list_iterator.h new file mode 100644 index 0000000000..82bbe56377 --- /dev/null +++ b/ecmascript/js_api_list_iterator.h @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#ifndef ECMASCRIPT_JS_API_LIST_ITERATOR_H +#define ECMASCRIPT_JS_API_LIST_ITERATOR_H + +#include "js_iterator.h" +#include "js_object.h" + +namespace panda::ecmascript { +class JSAPIListIterator : public JSObject { +public: + static JSAPIListIterator *Cast(ObjectHeader *obj) + { + ASSERT(JSTaggedValue(obj).IsJSAPIListIterator()); + return static_cast(obj); + } + static JSTaggedValue Next(EcmaRuntimeCallInfo *argv); + static JSHandle CreateListIterator(JSThread *thread, const JSHandle &obj); + static constexpr size_t ITERATED_LIST_OFFSET = JSObject::SIZE; + ACCESSORS(IteratedList, ITERATED_LIST_OFFSET, NEXT_INDEX_OFFSET) + ACCESSORS_PRIMITIVE_FIELD(NextIndex, uint32_t, NEXT_INDEX_OFFSET, LAST_OFFSET) + DEFINE_ALIGN_SIZE(LAST_OFFSET); + + DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, ITERATED_LIST_OFFSET, NEXT_INDEX_OFFSET) + + DECL_DUMP() +}; +} // namespace panda::ecmascript + +#endif // ECMASCRIPT_JS_List_ITERATOR_H \ No newline at end of file diff --git a/ecmascript/js_api_plain_array.cpp b/ecmascript/js_api_plain_array.cpp index 3a39bc505a..765cc66fc7 100644 --- a/ecmascript/js_api_plain_array.cpp +++ b/ecmascript/js_api_plain_array.cpp @@ -154,15 +154,17 @@ JSTaggedValue JSAPIPlainArray::Set(JSThread *thread, const JSHandle &obj, - const JSHandle &key, PropertyDescriptor &desc) + const JSHandle &key) { TaggedArray *keyArray = TaggedArray::Cast(obj->GetKeys().GetTaggedObject()); int32_t size = obj->GetLength(); - int32_t index = obj->BinarySearch(keyArray, 0, size, key.GetTaggedValue().GetNumber()); - if (index < 0 || index > size) { + int32_t index = obj->BinarySearch(keyArray, 0, size, key.GetTaggedValue().GetInt()); + if (index < 0 || index >= size) { THROW_RANGE_ERROR_AND_RETURN(thread, "GetOwnProperty index out-of-bounds", false); } - return JSObject::GetOwnProperty(thread, JSHandle::Cast(obj), key, desc); + + obj->Get(key.GetTaggedValue()); + return true; } OperationResult JSAPIPlainArray::GetProperty(JSThread *thread, const JSHandle &obj, @@ -170,8 +172,8 @@ OperationResult JSAPIPlainArray::GetProperty(JSThread *thread, const JSHandleGetKeys().GetTaggedObject()); int32_t size = obj->GetLength(); - int32_t index = obj->BinarySearch(keyArray, 0, size, key.GetTaggedValue().GetNumber()); - if (index < 0 || index > size) { + int32_t index = obj->BinarySearch(keyArray, 0, size, key.GetTaggedValue().GetInt()); + if (index < 0 || index >= size) { THROW_RANGE_ERROR_AND_RETURN(thread, "GetProperty index out-of-bounds", OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false))); } diff --git a/ecmascript/js_api_plain_array.h b/ecmascript/js_api_plain_array.h index ee0186ccf1..89f1ee48b4 100644 --- a/ecmascript/js_api_plain_array.h +++ b/ecmascript/js_api_plain_array.h @@ -31,7 +31,7 @@ public: static void Add(JSThread *thread, const JSHandle &obj, JSHandle key, JSHandle value); static bool GetOwnProperty(JSThread *thread, const JSHandle &obj, - const JSHandle &key, PropertyDescriptor &desc); + const JSHandle &key); static JSHandle CreateSlot(const JSThread *thread, const uint32_t capacity); static JSHandle Clone(JSThread *thread, const JSHandle &plainArray); static JSHandle GetIteratorObj(JSThread *thread, const JSHandle &obj, diff --git a/ecmascript/js_api_queue.cpp b/ecmascript/js_api_queue.cpp index 08a4462de0..05a4c7de02 100644 --- a/ecmascript/js_api_queue.cpp +++ b/ecmascript/js_api_queue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 @@ -14,6 +14,7 @@ */ #include "js_api_queue.h" +#include "ecmascript/js_object.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/object_factory.h" #include "interpreter/fast_runtime_stub-inl.h" @@ -45,14 +46,13 @@ JSHandle JSAPIQueue::GrowCapacity(const JSThread *thread, const JSH ASSERT(!oldElements->IsDictionaryMode()); uint32_t oldLength = oldElements->GetLength(); uint32_t newCapacity = 0; - // Set the oldLength(DEFAULT_CAPACITY_LENGTH = 8) of elements when constructing ASSERT(oldLength != 0); if (oldLength == 0) { newCapacity = ComputeCapacity(capacity); newElements = thread->GetEcmaVM()->GetFactory()->CopyArray(oldElements, oldLength, newCapacity); } else if ((tail + 1) % oldLength == front) { newCapacity = ComputeCapacity(capacity); - newElements = thread->GetEcmaVM()->GetFactory()->CopyQueue(oldElements, oldLength, newCapacity, front, tail); + newElements = thread->GetEcmaVM()->GetFactory()->CopyQueue(oldElements, newCapacity, front, tail); front = 0; tail = oldLength - 1; } else { @@ -101,12 +101,17 @@ JSTaggedValue JSAPIQueue::Pop(JSThread *thread, const JSHandle &queu JSTaggedValue JSAPIQueue::Get(JSThread *thread, const uint32_t index) { - if (index < 0) { + uint32_t length = GetSize(); + if (index >= length) { THROW_RANGE_ERROR_AND_RETURN(thread, "Get property index out-of-bounds", JSTaggedValue::Exception()); } TaggedArray *elements = TaggedArray::Cast(GetElements().GetTaggedObject()); - return elements->Get(index); + uint32_t capacity = elements->GetLength(); + uint32_t front = GetCurrentFront(); + ASSERT(capacity != 0); + uint32_t curIndex = (front + index) % capacity; + return elements->Get(curIndex); } JSTaggedValue JSAPIQueue::Set(JSThread *thread, const uint32_t index, JSTaggedValue value) @@ -132,7 +137,6 @@ bool JSAPIQueue::Has(JSTaggedValue value) const if (JSTaggedValue::SameValue(elements->Get(index), value)) { return true; } - // Set the capacity(DEFAULT_CAPACITY_LENGTH = 8) of elements when constructing ASSERT(capacity != 0); index = (index + 1) % capacity; } @@ -153,10 +157,10 @@ JSHandle JSAPIQueue::OwnKeys(JSThread *thread, const JSHandle &obj, - const JSHandle &key, PropertyDescriptor &desc) + const JSHandle &key) { uint32_t index = 0; - if (!UNLIKELY(JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) { + if (UNLIKELY(!JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) { THROW_TYPE_ERROR_AND_RETURN(thread, "Can not obtain attributes of no-number type", false); } @@ -164,7 +168,23 @@ bool JSAPIQueue::GetOwnProperty(JSThread *thread, const JSHandle &ob if (index < 0 || index >= length) { THROW_RANGE_ERROR_AND_RETURN(thread, "GetOwnProperty index out-of-bounds", false); } - return JSObject::GetOwnProperty(thread, JSHandle::Cast(obj), key, desc); + + obj->Get(thread, index); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false); + return true; +} + +OperationResult JSAPIQueue::GetProperty(JSThread *thread, const JSHandle &obj, + const JSHandle &key) +{ + int length = obj->GetLength().GetArrayLength(); + int index = key->GetInt(); + if (index < 0 || index >= length) { + THROW_RANGE_ERROR_AND_RETURN(thread, "GetProperty index out-of-bounds", + OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false))); + } + + return OperationResult(thread, obj->Get(thread, index), PropertyMetaData(false)); } uint32_t JSAPIQueue::GetArrayLength(JSThread *thread, const JSHandle &queue) diff --git a/ecmascript/js_api_queue.h b/ecmascript/js_api_queue.h index 630fb5b0fa..0df8f3c35d 100644 --- a/ecmascript/js_api_queue.h +++ b/ecmascript/js_api_queue.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 @@ -39,8 +39,9 @@ public: bool Has(JSTaggedValue value) const; static JSHandle OwnKeys(JSThread *thread, const JSHandle &obj); - static bool GetOwnProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key, - PropertyDescriptor &desc); + static bool GetOwnProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key); + static OperationResult GetProperty(JSThread *thread, const JSHandle &obj, + const JSHandle &key); inline uint32_t GetSize() const { diff --git a/ecmascript/js_api_queue_iterator.cpp b/ecmascript/js_api_queue_iterator.cpp index 184225fc3b..59d93235f2 100644 --- a/ecmascript/js_api_queue_iterator.cpp +++ b/ecmascript/js_api_queue_iterator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/js_api_queue_iterator.h b/ecmascript/js_api_queue_iterator.h index 26832e2ae8..470dd45106 100644 --- a/ecmascript/js_api_queue_iterator.h +++ b/ecmascript/js_api_queue_iterator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/js_api_stack.cpp b/ecmascript/js_api_stack.cpp index a70f4a2dc2..f333fe4a23 100644 --- a/ecmascript/js_api_stack.cpp +++ b/ecmascript/js_api_stack.cpp @@ -137,17 +137,32 @@ JSHandle JSAPIStack::OwnKeys(JSThread *thread, const JSHandle &obj, - const JSHandle &key, PropertyDescriptor &desc) + const JSHandle &key) { uint32_t index = 0; - if (UNLIKELY(JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) { + if (UNLIKELY(!JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) { THROW_TYPE_ERROR_AND_RETURN(thread, "Can not obtain attributes of no-number type", false); } uint32_t length = static_cast(obj->GetTop() + 1); - if (index + 1 > length) { + if (index >= length) { THROW_RANGE_ERROR_AND_RETURN(thread, "GetOwnProperty index out-of-bounds", false); } - return JSObject::GetOwnProperty(thread, JSHandle::Cast(obj), key, desc); + + obj->Get(index); + return true; +} + +OperationResult JSAPIStack::GetProperty(JSThread *thread, const JSHandle &obj, + const JSHandle &key) +{ + int length = obj->GetTop() + 1; + int index = key->GetInt(); + if (index < 0 || index >= length) { + THROW_RANGE_ERROR_AND_RETURN(thread, "GetProperty index out-of-bounds", + OperationResult(thread, JSTaggedValue::Exception(), PropertyMetaData(false))); + } + + return OperationResult(thread, obj->Get(index), PropertyMetaData(false)); } } // namespace panda::ecmascript diff --git a/ecmascript/js_api_stack.h b/ecmascript/js_api_stack.h index 3a485b6ccf..74a92c70d8 100644 --- a/ecmascript/js_api_stack.h +++ b/ecmascript/js_api_stack.h @@ -34,9 +34,9 @@ public: static JSHandle OwnKeys(JSThread *thread, const JSHandle &obj); - static bool GetOwnProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key, - PropertyDescriptor &desc); - + static bool GetOwnProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key); + static OperationResult GetProperty(JSThread *thread, const JSHandle &obj, + const JSHandle &key); bool Empty(); bool Has(JSTaggedValue value) const; diff --git a/ecmascript/js_api_tree_map.cpp b/ecmascript/js_api_tree_map.cpp index a510230b6a..cac064a4bc 100644 --- a/ecmascript/js_api_tree_map.cpp +++ b/ecmascript/js_api_tree_map.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/js_api_tree_map.h b/ecmascript/js_api_tree_map.h index e996679d73..2e948deb0b 100644 --- a/ecmascript/js_api_tree_map.h +++ b/ecmascript/js_api_tree_map.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/js_api_tree_map_iterator.cpp b/ecmascript/js_api_tree_map_iterator.cpp index 9bd5d1d576..d91eb8da51 100644 --- a/ecmascript/js_api_tree_map_iterator.cpp +++ b/ecmascript/js_api_tree_map_iterator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/js_api_tree_map_iterator.h b/ecmascript/js_api_tree_map_iterator.h index e7f5056d29..dc950c50c0 100644 --- a/ecmascript/js_api_tree_map_iterator.h +++ b/ecmascript/js_api_tree_map_iterator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/js_api_tree_set.cpp b/ecmascript/js_api_tree_set.cpp index 6b45454681..ec43549f1a 100644 --- a/ecmascript/js_api_tree_set.cpp +++ b/ecmascript/js_api_tree_set.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/js_api_tree_set.h b/ecmascript/js_api_tree_set.h index 1b19bc44a0..83d5e3653f 100644 --- a/ecmascript/js_api_tree_set.h +++ b/ecmascript/js_api_tree_set.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/js_api_tree_set_iterator.cpp b/ecmascript/js_api_tree_set_iterator.cpp index f20ce9419c..d66a5d03ef 100644 --- a/ecmascript/js_api_tree_set_iterator.cpp +++ b/ecmascript/js_api_tree_set_iterator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/js_api_tree_set_iterator.h b/ecmascript/js_api_tree_set_iterator.h index 97915d67e0..ed25ee7cba 100644 --- a/ecmascript/js_api_tree_set_iterator.h +++ b/ecmascript/js_api_tree_set_iterator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/js_api_vector.cpp b/ecmascript/js_api_vector.cpp index 57f6388034..327716a6f5 100644 --- a/ecmascript/js_api_vector.cpp +++ b/ecmascript/js_api_vector.cpp @@ -416,10 +416,10 @@ JSHandle JSAPIVector::OwnKeys(JSThread *thread, const JSHandle &obj, - const JSHandle &key, PropertyDescriptor &desc) + const JSHandle &key) { uint32_t index = 0; - if (UNLIKELY(JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) { + if (UNLIKELY(!JSTaggedValue::ToElementIndex(key.GetTaggedValue(), &index))) { THROW_TYPE_ERROR_AND_RETURN(thread, "Can not obtain attributes of no-number type", false); } @@ -427,7 +427,10 @@ bool JSAPIVector::GetOwnProperty(JSThread *thread, const JSHandle & if (index >= length) { THROW_RANGE_ERROR_AND_RETURN(thread, "GetOwnProperty index out-of-bounds", false); } - return JSObject::GetOwnProperty(thread, JSHandle::Cast(obj), key, desc); + + JSAPIVector::Get(thread, obj, index); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false); + return true; } void JSAPIVector::TrimToCurrentLength(JSThread *thread, const JSHandle &obj) diff --git a/ecmascript/js_api_vector.h b/ecmascript/js_api_vector.h index 41a23eb34f..ce19d96fc5 100644 --- a/ecmascript/js_api_vector.h +++ b/ecmascript/js_api_vector.h @@ -83,8 +83,7 @@ public: bool Has(const JSTaggedValue &value) const; static JSHandle OwnKeys(JSThread *thread, const JSHandle &obj); - static bool GetOwnProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key, - PropertyDescriptor &desc); + static bool GetOwnProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key); static void TrimToCurrentLength(JSThread *thread, const JSHandle &vector); diff --git a/ecmascript/js_hclass.h b/ecmascript/js_hclass.h index c99dec9b3b..fed3f974e9 100644 --- a/ecmascript/js_hclass.h +++ b/ecmascript/js_hclass.h @@ -106,6 +106,8 @@ class ProtoChangeDetails; JS_API_TREEMAP_ITERATOR, /* ///////////////////////////////////////////////////////////////////////-PADDING */ \ JS_API_TREESET_ITERATOR, /* ///////////////////////////////////////////////////////////////////////-PADDING */ \ JS_API_VECTOR_ITERATOR, /* ///////////////////////////////////////////////////////////////////////-PADDING */ \ + JS_API_LINKED_LIST_ITERATOR, /* ///////////////////////////////////////////////////////////////////-PADDING */ \ + JS_API_LIST_ITERATOR, /* ///////////////////////////////////////////////////////////////////////-PADDING */ \ JS_ARRAY_ITERATOR, /* ///////////////////////////////////////////////////////////////////////-PADDING */ \ JS_STRING_ITERATOR, /* ///////////////////////////////////////////////////////////////////////-PADDING */ \ JS_INTL, /* ///////////////////////////////////////////////////////////////////////////////////////-PADDING */ \ @@ -130,6 +132,8 @@ class ProtoChangeDetails; JS_ARRAY, /* ////////////////////////////////////////////////////////////////////////////////-PADDING */ \ JS_API_ARRAY_LIST, /* /////////////////////////////////////////////////////////////////////////////-PADDING */ \ JS_API_VECTOR, /* /////////////////////////////////////////////////////////////////////////////-PADDING */ \ + JS_API_LINKED_LIST, /* ////////////////////////////////////////////////////////////////////////////-PADDING */ \ + JS_API_LIST, /* /////////////////////////////////////////////////////////////////////////////-PADDING */ \ JS_API_TREE_MAP, /* /////////////////////////////////////////////////////////////////////////////-PADDING */ \ JS_API_TREE_SET, /* /////////////////////////////////////////////////////////////////////////////-PADDING */ \ JS_API_DEQUE, /* /////////////////////////////////////////////////////////////////////////////-PADDING */ \ @@ -718,7 +722,14 @@ public: { return GetObjectType() == JSType::JS_API_QUEUE_ITERATOR; } - + inline bool IsJSAPIList() const + { + return GetObjectType() == JSType::JS_API_LIST; + } + inline bool IsJSAPILinkedList() const + { + return GetObjectType() == JSType::JS_API_LINKED_LIST; + } inline bool IsJSAPITreeMap() const { return GetObjectType() == JSType::JS_API_TREE_MAP; @@ -823,6 +834,16 @@ public: return GetObjectType() == JSType::JS_API_STACK_ITERATOR; } + inline bool IsJSAPILinkedListIterator() const + { + return GetObjectType() == JSType::JS_API_LINKED_LIST_ITERATOR; + } + + inline bool IsJSAPIListIterator() const + { + return GetObjectType() == JSType::JS_API_LIST_ITERATOR; + } + inline bool IsPrototypeHandler() const { return GetObjectType() == JSType::PROTOTYPE_HANDLER; diff --git a/ecmascript/js_object-inl.h b/ecmascript/js_object-inl.h index 3eeac9c9ff..aceba78b30 100644 --- a/ecmascript/js_object-inl.h +++ b/ecmascript/js_object-inl.h @@ -196,6 +196,16 @@ inline bool JSObject::IsJSAPIVectorIterator() const return GetJSHClass()->IsJSAPIVectorIterator(); } +inline bool JSObject::IsJSAPILinkedListIterator() const +{ + return GetJSHClass()->IsJSAPILinkedListIterator(); +} + +inline bool JSObject::IsJSAPIListIterator() const +{ + return GetJSHClass()->IsJSAPIListIterator(); +} + inline bool JSObject::IsJSPrimitiveRef() const { return GetJSHClass()->IsJsPrimitiveRef(); diff --git a/ecmascript/js_object.h b/ecmascript/js_object.h index be3e2b4d13..ffe8c978b7 100644 --- a/ecmascript/js_object.h +++ b/ecmascript/js_object.h @@ -542,6 +542,8 @@ public: bool IsJSAPIArrayListIterator() const; bool IsJSAPIStackIterator() const; bool IsJSAPIVectorIterator() const; + bool IsJSAPILinkedListIterator() const; + bool IsJSAPIListIterator() const; bool IsJSPrimitiveRef() const; bool IsElementDict() const; bool IsPropertiesDict() const; diff --git a/ecmascript/js_tagged_value-inl.h b/ecmascript/js_tagged_value-inl.h index dd8660db75..6986b74003 100644 --- a/ecmascript/js_tagged_value-inl.h +++ b/ecmascript/js_tagged_value-inl.h @@ -626,6 +626,26 @@ inline bool JSTaggedValue::IsJSAPIVector() const return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPIVector(); } +inline bool JSTaggedValue::IsJSAPIList() const +{ + return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPIList(); +} + +inline bool JSTaggedValue::IsJSAPILinkedList() const +{ + return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPILinkedList(); +} + +inline bool JSTaggedValue::IsJSAPILinkedListIterator() const +{ + return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPILinkedListIterator(); +} + +inline bool JSTaggedValue::IsJSAPIListIterator() const +{ + return IsHeapObject() && GetTaggedObject()->GetClass()->IsJSAPIListIterator(); +} + inline bool JSTaggedValue::IsSpecialContainer() const { return IsHeapObject() && GetTaggedObject()->GetClass()->IsSpecialContainer(); diff --git a/ecmascript/js_tagged_value.cpp b/ecmascript/js_tagged_value.cpp index c94dcb1511..5a94d046d7 100644 --- a/ecmascript/js_tagged_value.cpp +++ b/ecmascript/js_tagged_value.cpp @@ -18,13 +18,15 @@ #include "ecmascript/ecma_vm.h" #include "ecmascript/global_env.h" #include "ecmascript/interpreter/interpreter.h" +#include "ecmascript/js_api_arraylist.h" #include "ecmascript/js_api_deque.h" +#include "ecmascript/js_api_linked_list.h" +#include "ecmascript/js_api_list.h" #include "ecmascript/js_api_plain_array.h" #include "ecmascript/js_api_queue.h" #include "ecmascript/js_api_stack.h" -#include "ecmascript/js_array.h" -#include "ecmascript/js_api_arraylist.h" #include "ecmascript/js_api_vector.h" +#include "ecmascript/js_array.h" #include "ecmascript/js_handle.h" #include "ecmascript/js_primitive_ref.h" #include "ecmascript/js_proxy.h" @@ -941,6 +943,14 @@ bool JSTaggedValue::HasContainerProperty(JSThread *thread, const JSHandle::Cast(obj)->Has(key.GetTaggedValue()); } + case JSType::JS_API_LIST: { + JSHandle list = JSHandle::Cast(obj); + return list->Has(key.GetTaggedValue()); + } + case JSType::JS_API_LINKED_LIST: { + JSHandle linkedList = JSHandle::Cast(obj); + return linkedList->Has(key.GetTaggedValue()); + } case JSType::JS_API_TREE_MAP: case JSType::JS_API_TREE_SET: { return JSObject::HasProperty(thread, JSHandle(obj), key); @@ -975,6 +985,12 @@ JSHandle JSTaggedValue::GetOwnContainerPropertyKeys(JSThread *threa case JSType::JS_API_STACK: { return JSAPIStack::OwnKeys(thread, JSHandle::Cast(obj)); } + case JSType::JS_API_LIST: { + return JSAPIList::OwnKeys(thread, JSHandle::Cast(obj)); + } + case JSType::JS_API_LINKED_LIST: { + return JSAPILinkedList::OwnKeys(thread, JSHandle::Cast(obj)); + } case JSType::JS_API_TREE_MAP: case JSType::JS_API_TREE_SET: { return JSObject::GetOwnPropertyKeys(thread, JSHandle(obj)); @@ -992,34 +1008,40 @@ JSHandle JSTaggedValue::GetOwnContainerPropertyKeys(JSThread *threa bool JSTaggedValue::GetContainerProperty(JSThread *thread, const JSHandle &obj, const JSHandle &key, PropertyDescriptor &desc) { - auto *hclass = obj->GetTaggedObject()->GetClass(); - JSType jsType = hclass->GetObjectType(); - switch (jsType) { - case JSType::JS_API_ARRAY_LIST: { - return JSAPIArrayList::GetOwnProperty(thread, JSHandle::Cast(obj), key, desc); - } - case JSType::JS_API_QUEUE: { - return JSAPIQueue::GetOwnProperty(thread, JSHandle::Cast(obj), key, desc); - } - case JSType::JS_API_PLAIN_ARRAY: { - return JSAPIPlainArray::GetOwnProperty(thread, JSHandle::Cast(obj), key, desc); - } - case JSType::JS_API_DEQUE: { - return JSAPIDeque::GetOwnProperty(thread, JSHandle::Cast(obj), key, desc); - } - case JSType::JS_API_STACK: { - return JSAPIStack::GetOwnProperty(thread, JSHandle::Cast(obj), key, desc); - } - case JSType::JS_API_TREE_MAP: - case JSType::JS_API_TREE_SET: { - return JSObject::GetOwnProperty(thread, JSHandle(obj), key, desc); - } - case JSType::JS_API_VECTOR: { - return JSAPIVector::GetOwnProperty(thread, JSHandle::Cast(obj), key, desc); - } - default: { - UNREACHABLE(); + if (key->IsInteger()) { + auto *hclass = obj->GetTaggedObject()->GetClass(); + JSType jsType = hclass->GetObjectType(); + switch (jsType) { + case JSType::JS_API_ARRAY_LIST: { + return JSAPIArrayList::GetOwnProperty(thread, JSHandle::Cast(obj), key); + } + case JSType::JS_API_QUEUE: { + return JSAPIQueue::GetOwnProperty(thread, JSHandle::Cast(obj), key); + } + case JSType::JS_API_DEQUE: { + return JSAPIDeque::GetOwnProperty(thread, JSHandle::Cast(obj), key); + } + case JSType::JS_API_STACK: { + return JSAPIStack::GetOwnProperty(thread, JSHandle::Cast(obj), key); + } + case JSType::JS_API_LIST: { + return JSAPIList::GetOwnProperty(thread, JSHandle::Cast(obj), key); + } + case JSType::JS_API_LINKED_LIST: { + return JSAPILinkedList::GetOwnProperty(thread, JSHandle::Cast(obj), key); + } + case JSType::JS_API_PLAIN_ARRAY: { + return JSAPIPlainArray::GetOwnProperty(thread, JSHandle::Cast(obj), key); + } + case JSType::JS_API_VECTOR: { + return JSAPIVector::GetOwnProperty(thread, JSHandle::Cast(obj), key); + } + default: { + return JSObject::GetOwnProperty(thread, JSHandle(obj), key, desc); + } } + } else { + return JSObject::GetOwnProperty(thread, JSHandle(obj), key, desc); } return false; } @@ -1041,12 +1063,31 @@ JSHandle JSTaggedValue::ToNumeric(JSThread *thread, JSHandle &obj, const JSHandle &key) { - auto *hclass = obj->GetTaggedObject()->GetClass(); - JSType jsType = hclass->GetObjectType(); - if (key->IsNumber()) { + if (key->IsInteger()) { + auto *hclass = obj->GetTaggedObject()->GetClass(); + JSType jsType = hclass->GetObjectType(); switch (jsType) { - case JSType::JS_API_PLAIN_ARRAY: + case JSType::JS_API_ARRAY_LIST: { + return JSAPIArrayList::GetProperty(thread, JSHandle::Cast(obj), key); + } + case JSType::JS_API_LIST: { + return JSAPIList::GetProperty(thread, JSHandle::Cast(obj), key); + } + case JSType::JS_API_LINKED_LIST: { + return JSAPILinkedList::GetProperty(thread, JSHandle::Cast(obj), key); + } + case JSType::JS_API_QUEUE: { + return JSAPIQueue::GetProperty(thread, JSHandle::Cast(obj), key); + } + case JSType::JS_API_DEQUE: { + return JSAPIDeque::GetProperty(thread, JSHandle::Cast(obj), key); + } + case JSType::JS_API_STACK: { + return JSAPIStack::GetProperty(thread, JSHandle::Cast(obj), key); + } + case JSType::JS_API_PLAIN_ARRAY: { return JSAPIPlainArray::GetProperty(thread, JSHandle::Cast(obj), key); + } default: { return JSObject::GetProperty(thread, JSHandle(obj), key); } diff --git a/ecmascript/js_tagged_value.h b/ecmascript/js_tagged_value.h index 806199488a..9118050ba5 100644 --- a/ecmascript/js_tagged_value.h +++ b/ecmascript/js_tagged_value.h @@ -583,6 +583,10 @@ public: bool IsJSAPIDequeIterator() const; bool IsJSAPIStack() const; bool IsJSAPIStackIterator() const; + bool IsJSAPIList() const; + bool IsJSAPILinkedList() const; + bool IsJSAPIListIterator() const; + bool IsJSAPILinkedListIterator() const; bool IsSpecialContainer() const; bool IsPrototypeHandler() const; diff --git a/ecmascript/mem/object_xray.h b/ecmascript/mem/object_xray.h index 6268adaf5d..2484939a3b 100644 --- a/ecmascript/mem/object_xray.h +++ b/ecmascript/mem/object_xray.h @@ -30,6 +30,10 @@ #include "ecmascript/js_api_arraylist_iterator.h" #include "ecmascript/js_api_deque.h" #include "ecmascript/js_api_deque_iterator.h" +#include "ecmascript/js_api_linked_list.h" +#include "ecmascript/js_api_linked_list_iterator.h" +#include "ecmascript/js_api_list.h" +#include "ecmascript/js_api_list_iterator.h" #include "ecmascript/js_api_plain_array.h" #include "ecmascript/js_api_plain_array_iterator.h" #include "ecmascript/js_api_queue.h" @@ -484,6 +488,18 @@ public: case JSType::JS_API_VECTOR_ITERATOR: JSAPIVectorIterator::Cast(object)->VisitRangeSlot(visitor); break; + case JSType::JS_API_LIST: + JSAPIList::Cast(object)->VisitRangeSlot(visitor); + break; + case JSType::JS_API_LINKED_LIST: + JSAPILinkedList::Cast(object)->VisitRangeSlot(visitor); + break; + case JSType::JS_API_LIST_ITERATOR: + JSAPIListIterator::Cast(object)->VisitRangeSlot(visitor); + break; + case JSType::JS_API_LINKED_LIST_ITERATOR: + JSAPILinkedListIterator::Cast(object)->VisitRangeSlot(visitor); + break; case JSType::BIGINT: BigInt::Cast(object)->VisitRangeSlot(visitor); break; diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index cf58710370..effa0444b6 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -45,6 +45,10 @@ #include "ecmascript/js_api_arraylist_iterator.h" #include "ecmascript/js_api_deque.h" #include "ecmascript/js_api_deque_iterator.h" +#include "ecmascript/js_api_linked_list.h" +#include "ecmascript/js_api_linked_list_iterator.h" +#include "ecmascript/js_api_list.h" +#include "ecmascript/js_api_list_iterator.h" #include "ecmascript/js_api_plain_array.h" #include "ecmascript/js_api_plain_array_iterator.h" #include "ecmascript/js_api_queue.h" @@ -61,8 +65,6 @@ #include "ecmascript/js_array.h" #include "ecmascript/js_array_iterator.h" #include "ecmascript/js_arraybuffer.h" -#include "ecmascript/js_api_arraylist.h" -#include "ecmascript/js_api_arraylist_iterator.h" #include "ecmascript/js_async_function.h" #include "ecmascript/js_bigint.h" #include "ecmascript/js_collator.h" @@ -107,6 +109,7 @@ #include "ecmascript/record.h" #include "ecmascript/shared_mm/shared_mm.h" #include "ecmascript/symbol_table.h" +#include "ecmascript/tagged_list.h" #include "ecmascript/tagged_tree.h" #include "ecmascript/template_map.h" #include "ecmascript/ts_types/ts_obj_layout_info.h" @@ -1113,6 +1116,12 @@ void ObjectFactory::InitializeJSObject(const JSHandle &obj, const JSHa case JSType::JS_API_VECTOR: JSAPIVector::Cast(*obj)->SetLength(0); break; + case JSType::JS_API_LIST: + JSAPIList::Cast(*obj)->SetSingleList(thread_, JSTaggedValue::Undefined()); + break; + case JSType::JS_API_LINKED_LIST: + JSAPILinkedList::Cast(*obj)->SetDoubleList(thread_, JSTaggedValue::Undefined()); + break; case JSType::JS_ASYNC_FUNC_OBJECT: JSAsyncFuncObject::Cast(*obj)->SetGeneratorContext(thread_, JSTaggedValue::Undefined()); JSAsyncFuncObject::Cast(*obj)->SetResumeResult(thread_, JSTaggedValue::Undefined()); @@ -2941,9 +2950,8 @@ JSHandle ObjectFactory::NewJSAPIDequeIterator(const JSHandle return iter; } -JSHandle ObjectFactory::CopyQueue(const JSHandle &old, uint32_t oldLength, - uint32_t newLength, [[maybe_unused]] uint32_t front, - [[maybe_unused]] uint32_t tail) +JSHandle ObjectFactory::CopyQueue(const JSHandle &old, uint32_t newLength, + uint32_t front, uint32_t tail) { NewObjectHook(); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), newLength); @@ -2953,11 +2961,17 @@ JSHandle ObjectFactory::CopyQueue(const JSHandle &old, newArray->InitializeWithSpecialValue(JSTaggedValue::Hole(), newLength); newArray->SetLength(newLength); - for (uint32_t i = 0; i < oldLength; i++) { - JSTaggedValue value = old->Get(i); - newArray->Set(thread_, i, value); + uint32_t curIndex = front; + // newIndex use in new TaggedArray, 0 : New TaggedArray index + uint32_t newIndex = 0; + uint32_t oldCapacity = old->GetLength(); + while (curIndex != tail) { + JSTaggedValue value = old->Get(curIndex); + newArray->Set(thread_, newIndex, value); + ASSERT(oldCapacity != 0); + curIndex = (curIndex + 1) % oldCapacity; + newIndex = newIndex + 1; } - return newArray; } @@ -3042,6 +3056,48 @@ JSHandle ObjectFactory::NewJSAPIVectorIterator(const JSHand return iter; } +JSHandle ObjectFactory::NewJSAPILinkedListIterator(const JSHandle &linkedList) +{ + NewObjectHook(); + JSHandle proto(thread_, thread_->GlobalConstants()->GetLinkedListIteratorPrototype()); + const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); + JSHandle dynHandle(globalConst->GetHandledJSAPILinkedListIteratorClass()); + dynHandle->SetPrototype(thread_, proto); + JSHandle iter(NewJSObject(dynHandle)); + iter->GetJSHClass()->SetExtensible(true); + iter->SetIteratedLinkedList(thread_, linkedList->GetDoubleList()); + iter->SetNextIndex(0); + return iter; +} + +JSHandle ObjectFactory::NewJSAPIListIterator(const JSHandle &List) +{ + NewObjectHook(); + JSHandle proto(thread_, thread_->GlobalConstants()->GetListIteratorPrototype()); + const GlobalEnvConstants *globalConst = thread_->GlobalConstants(); + JSHandle dynHandle(globalConst->GetHandledJSAPIListIteratorClass()); + dynHandle->SetPrototype(thread_, proto); + JSHandle iter(NewJSObject(dynHandle)); + iter->GetJSHClass()->SetExtensible(true); + iter->SetIteratedList(thread_, List->GetSingleList()); + iter->SetNextIndex(0); + return iter; +} + +JSHandle ObjectFactory::NewJSAPIList() +{ + NewObjectHook(); + JSHandle function(thread_, thread_->GlobalConstants()->GetListFunction()); + return JSHandle::Cast(NewJSObjectByConstructor(JSHandle(function), function)); +} + +JSHandle ObjectFactory::NewJSAPILinkedList() +{ + NewObjectHook(); + JSHandle function(thread_, thread_->GlobalConstants()->GetLinkedListFunction()); + return JSHandle::Cast(NewJSObjectByConstructor(JSHandle(function), function)); +} + JSHandle ObjectFactory::NewImportEntry() { JSHandle defautValue = thread_->GlobalConstants()->GetHandledUndefined(); diff --git a/ecmascript/object_factory.h b/ecmascript/object_factory.h index 8a86c977a2..7a2deb65a5 100644 --- a/ecmascript/object_factory.h +++ b/ecmascript/object_factory.h @@ -114,6 +114,10 @@ class JSAPITreeSetIterator; class JSAPITreeMapIterator; class JSAPIVector; class JSAPIVectorIterator; +class JSAPILinkedList; +class JSAPIList; +class JSAPILinkedListIterator; +class JSAPIListIterator; class ModuleNamespace; class ImportEntry; class ExportEntry; @@ -442,13 +446,17 @@ public: JSHandle NewJSAPIPlainArrayIterator(const JSHandle &plainarray, IterationKind kind); JSHandle NewJSAPIArrayList(uint32_t capacity); - JSHandle CopyQueue(const JSHandle &old, uint32_t oldLength, - uint32_t newLength, uint32_t front, uint32_t tail); + JSHandle CopyQueue(const JSHandle &old, uint32_t newLength, + uint32_t front, uint32_t tail); JSHandle NewJSAPIQueueIterator(const JSHandle &queue); JSHandle CopyDeque(const JSHandle &old, uint32_t newLength, uint32_t oldLength, uint32_t first, uint32_t last); JSHandle NewJSAPIDequeIterator(const JSHandle &deque); JSHandle NewJSAPIArrayListIterator(const JSHandle &arrayList); + JSHandle NewJSAPIList(); + JSHandle NewJSAPILinkedList(); + JSHandle NewJSAPILinkedListIterator(const JSHandle &linkedList); + JSHandle NewJSAPIListIterator(const JSHandle &list); JSHandle NewJSAPITreeMapIterator(const JSHandle &map, IterationKind kind); JSHandle NewJSAPITreeSetIterator(const JSHandle &set, IterationKind kind); JSHandle NewJSAPIStackIterator(const JSHandle &stack); diff --git a/ecmascript/runtime_call_id.h b/ecmascript/runtime_call_id.h index 01e54348b7..f7181831d3 100644 --- a/ecmascript/runtime_call_id.h +++ b/ecmascript/runtime_call_id.h @@ -684,7 +684,52 @@ namespace panda::ecmascript { V(Queue, Pop) \ V(Queue, ForEach) \ V(Queue, GetIteratorObj) \ - V(Queue, GetSize) + V(Queue, GetSize) \ + V(List, Constructor) \ + V(List, Add) \ + V(List, GetFirst) \ + V(List, GetLast) \ + V(List, Insert) \ + V(List, Clear) \ + V(List, RemoveByIndex) \ + V(List, Remove) \ + V(List, Has) \ + V(List, IsEmpty) \ + V(List, Get) \ + V(List, GetIndexOf) \ + V(List, GetLastIndexOf) \ + V(List, Set) \ + V(List, ForEach) \ + V(List, ReplaceAllElements) \ + V(List, GetIteratorObj) \ + V(List, Equal) \ + V(List, Sort) \ + V(List, ConvertToArray) \ + V(List, GetSubList) \ + V(List, Length) \ + V(LinkedList, Constructor) \ + V(LinkedList, Length) \ + V(LinkedList, Add) \ + V(LinkedList, GetFirst) \ + V(LinkedList, GetLast) \ + V(LinkedList, Insert) \ + V(LinkedList, AddFirst) \ + V(LinkedList, Clear) \ + V(LinkedList, Clone) \ + V(LinkedList, Has) \ + V(LinkedList, Get) \ + V(LinkedList, GetIndexOf) \ + V(LinkedList, GetLastIndexOf) \ + V(LinkedList, RemoveByIndex) \ + V(LinkedList, Remove) \ + V(LinkedList, RemoveFirst) \ + V(LinkedList, RemoveLast) \ + V(LinkedList, RemoveFirstFound) \ + V(LinkedList, RemoveLastFound) \ + V(LinkedList, Set) \ + V(LinkedList, ConvertToArray) \ + V(LinkedList, ForEach) \ + V(LinkedList, GetIteratorObj) #define ABSTRACT_OPERATION_LIST(V) \ V(JSTaggedValue, ToString) \ diff --git a/ecmascript/snapshot/mem/snapshot_processor.cpp b/ecmascript/snapshot/mem/snapshot_processor.cpp index af5ae52546..077a7ac0bc 100644 --- a/ecmascript/snapshot/mem/snapshot_processor.cpp +++ b/ecmascript/snapshot/mem/snapshot_processor.cpp @@ -57,6 +57,8 @@ #include "ecmascript/builtins/builtins_weak_set.h" #include "ecmascript/containers/containers_arraylist.h" #include "ecmascript/containers/containers_deque.h" +#include "ecmascript/containers/containers_linked_list.h" +#include "ecmascript/containers/containers_list.h" #include "ecmascript/containers/containers_plainarray.h" #include "ecmascript/containers/containers_private.h" #include "ecmascript/containers/containers_queue.h" @@ -68,7 +70,10 @@ #include "ecmascript/jspandafile/js_pandafile_manager.h" #include "ecmascript/jspandafile/program_object.h" #include "ecmascript/global_env.h" +#include "ecmascript/js_api_arraylist_iterator.h" #include "ecmascript/js_api_deque_iterator.h" +#include "ecmascript/js_api_linked_list_iterator.h" +#include "ecmascript/js_api_list_iterator.h" #include "ecmascript/js_api_plain_array_iterator.h" #include "ecmascript/js_api_queue_iterator.h" #include "ecmascript/js_api_stack_iterator.h" @@ -76,7 +81,6 @@ #include "ecmascript/js_api_tree_set_iterator.h" #include "ecmascript/js_api_vector_iterator.h" #include "ecmascript/js_array_iterator.h" -#include "ecmascript/js_api_arraylist_iterator.h" #include "ecmascript/js_for_in_iterator.h" #include "ecmascript/js_hclass.h" #include "ecmascript/js_map_iterator.h" @@ -143,6 +147,8 @@ using TreeMap = containers::ContainersTreeMap; using TreeSet = containers::ContainersTreeSet; using Vector = containers::ContainersVector; using Queue = containers::ContainersQueue; +using List = containers::ContainersList; +using LinkedList = containers::ContainersLinkedList; using PlainArray = containers::ContainersPlainArray; using Deque = containers::ContainersDeque; using ContainerStack = panda::ecmascript::containers::ContainersStack; @@ -740,6 +746,51 @@ static uintptr_t g_nativeTable[] = { reinterpret_cast(ContainerStack::ForEach), reinterpret_cast(ContainerStack::GetLength), reinterpret_cast(JSAPIStackIterator::Next), + reinterpret_cast(List::ListConstructor), + reinterpret_cast(List::Add), + reinterpret_cast(List::GetFirst), + reinterpret_cast(List::GetLast), + reinterpret_cast(List::Insert), + reinterpret_cast(List::Clear), + reinterpret_cast(List::RemoveByIndex), + reinterpret_cast(List::Remove), + reinterpret_cast(List::Has), + reinterpret_cast(List::IsEmpty), + reinterpret_cast(List::Get), + reinterpret_cast(List::GetIndexOf), + reinterpret_cast(List::GetLastIndexOf), + reinterpret_cast(List::Set), + reinterpret_cast(List::ForEach), + reinterpret_cast(List::ReplaceAllElements), + reinterpret_cast(List::GetIteratorObj), + reinterpret_cast(List::Equal), + reinterpret_cast(List::Sort), + reinterpret_cast(List::ConvertToArray), + reinterpret_cast(List::GetSubList), + reinterpret_cast(List::Length), + reinterpret_cast(JSAPIListIterator::Next), + reinterpret_cast(LinkedList::LinkedListConstructor), + reinterpret_cast(LinkedList::Add), + reinterpret_cast(LinkedList::GetFirst), + reinterpret_cast(LinkedList::GetLast), + reinterpret_cast(LinkedList::Insert), + reinterpret_cast(LinkedList::AddFirst), + reinterpret_cast(LinkedList::Clear), + reinterpret_cast(LinkedList::Clone), + reinterpret_cast(LinkedList::Has), + reinterpret_cast(LinkedList::Get), + reinterpret_cast(LinkedList::GetIndexOf), + reinterpret_cast(LinkedList::GetLastIndexOf), + reinterpret_cast(LinkedList::RemoveByIndex), + reinterpret_cast(LinkedList::Remove), + reinterpret_cast(LinkedList::RemoveFirst), + reinterpret_cast(LinkedList::RemoveLast), + reinterpret_cast(LinkedList::RemoveFirstFound), + reinterpret_cast(LinkedList::RemoveLastFound), + reinterpret_cast(LinkedList::Set), + reinterpret_cast(LinkedList::ConvertToArray), + reinterpret_cast(LinkedList::ForEach), + reinterpret_cast(JSAPILinkedListIterator::Next), // not builtins method reinterpret_cast(JSFunction::PrototypeSetter), diff --git a/ecmascript/tagged_list.cpp b/ecmascript/tagged_list.cpp new file mode 100644 index 0000000000..4219bc8db5 --- /dev/null +++ b/ecmascript/tagged_list.cpp @@ -0,0 +1,684 @@ +/* + * 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. + */ + +#include "tagged_list.h" +#include "ecmascript/base/array_helper.h" +#include "ecmascript/base/number_helper.h" +#include "ecmascript/base/typed_array_helper-inl.h" +#include "ecmascript/interpreter/interpreter.h" +#include "ecmascript/js_array.h" +#include "ecmascript/js_function.h" +#include "ecmascript/js_handle.h" +#include "ecmascript/js_object-inl.h" +#include "ecmascript/js_tagged_number.h" +#include "object_factory.h" + +namespace panda::ecmascript { +template +JSHandle TaggedList::Create(const JSThread *thread, int numberOfNodes) +{ + ASSERT_PRINT(numberOfNodes > 0, "size must be a non-negative integer"); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + int length = ELEMENTS_START_INDEX + Derived::ENTRY_SIZE + numberOfNodes * Derived::ENTRY_SIZE; + JSHandle taggedArray = factory->NewTaggedArray(length); + auto taggedList = JSHandle::Cast(taggedArray); + JSTaggedValue data = JSTaggedValue(ELEMENTS_START_INDEX); + taggedList->SetNumberOfNodes(thread, 0); + taggedList->SetNumberOfDeletedNodes(thread, 0); + taggedList->SetElement(thread, HEAD_TABLE_INDEX, data); + taggedList->SetElement(thread, TAIL_TABLE_INDEX, data); + taggedList->SetElement(thread, ELEMENTS_START_INDEX, JSTaggedValue::Hole()); + taggedList->SetElement(thread, ELEMENTS_START_INDEX + NEXT_PTR_OFFSET, data); + return taggedList; +} + +template +void TaggedList::CopyArray(const JSThread *thread, JSHandle &taggedList) +{ + int prevDataIndex = ELEMENTS_START_INDEX; + int nextDataIndex = GetElement(ELEMENTS_START_INDEX + NEXT_PTR_OFFSET).GetInt(); + int nodeNum = 0; + int nodeLength = NumberOfNodes(); + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + while (nodeLength > nodeNum) { + int finalDataIndex = ELEMENTS_START_INDEX + Derived::ENTRY_SIZE + nodeNum * Derived::ENTRY_SIZE; + value.Update(GetElement(nextDataIndex)); + taggedList->InsertNode(thread, value, prevDataIndex, finalDataIndex); + prevDataIndex = finalDataIndex; + nextDataIndex = GetElement(nextDataIndex + NEXT_PTR_OFFSET).GetInt(); + taggedList->SetElement(thread, TAIL_TABLE_INDEX, JSTaggedValue(finalDataIndex)); + nodeNum++; + } + taggedList->SetNumberOfDeletedNodes(thread, 0); +} + +template +JSHandle TaggedList::GrowCapacity(const JSThread *thread, const JSHandle &taggedList) +{ + int actualNodeNum = taggedList->NumberOfNodes(); + int deleteNodeNum = taggedList->NumberOfDeletedNodes(); + int needCapacity = actualNodeNum + 1; + int taggedArrayLength = taggedList->GetCapacityFromTaggedArray(); + int actualArrayCapacity = (taggedArrayLength - ELEMENTS_START_INDEX - (deleteNodeNum + 1) * Derived::ENTRY_SIZE); + if (needCapacity * Derived::ENTRY_SIZE < actualArrayCapacity) { + return taggedList; + } + int newCapacity = actualNodeNum + (actualNodeNum >> 1UL); + JSHandle list = Create(thread, newCapacity < DEFAULT_ARRAY_LENGHT ? DEFAULT_ARRAY_LENGHT : newCapacity); + taggedList->CopyArray(thread, list); + return list; +} + +template +JSTaggedValue TaggedList::AddNode(const JSThread *thread, const JSHandle &taggedList, + const JSHandle &value, const int index, int prevDataIndex) +{ + JSHandle list = GrowCapacity(thread, taggedList); + int deleteNodeLength = list->NumberOfDeletedNodes(); + int nodeLength = list->NumberOfNodes(); + int finalDataIndex = ELEMENTS_START_INDEX + (nodeLength + 1 + deleteNodeLength) * Derived::ENTRY_SIZE; + + list->InsertNode(thread, value, prevDataIndex, finalDataIndex); + if (index == -1 || nodeLength == index) { + list->SetElement(thread, TAIL_TABLE_INDEX, JSTaggedValue(finalDataIndex)); + } + return list.GetTaggedValue(); +} + +template +void TaggedList::Clear(const JSThread *thread) +{ + int numberOfElements = NumberOfNodes(); + int deleteNodesNum = NumberOfDeletedNodes(); + SetElement(thread, TAIL_TABLE_INDEX, JSTaggedValue(ELEMENTS_START_INDEX)); + SetElement(thread, ELEMENTS_START_INDEX + NEXT_PTR_OFFSET, JSTaggedValue(ELEMENTS_START_INDEX)); + SetNumberOfNodes(thread, 0); + SetNumberOfDeletedNodes(thread, numberOfElements + deleteNodesNum); +} + +template +JSTaggedValue TaggedList::TaggedListToArray(const JSThread *thread, const JSHandle &list) +{ + uint32_t length = static_cast(list->NumberOfNodes()); + JSHandle array = thread->GetEcmaVM()->GetFactory()->NewJSArray(); + array->SetArrayLength(thread, length); + JSHandle arrayElements(thread, array->GetElements()); + uint32_t oldLength = arrayElements->GetLength(); + JSHandle newElements = + thread->GetEcmaVM()->GetFactory()->CopyArray(arrayElements, oldLength, length); + for (uint32_t i = 0; i < length; i++) { + newElements->Set(thread, i, list->Get(i)); + } + array->SetElements(thread, newElements); + return array.GetTaggedValue(); +} + +template +JSHandle TaggedList::OwnKeys(JSThread *thread, const JSHandle &list) +{ + uint32_t length = static_cast(list->NumberOfNodes()); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle keys = factory->NewTaggedArray(length); + + for (uint32_t i = 0; i < length; i++) { + JSTaggedValue elementData = JSTaggedValue(i); + keys->Set(thread, i, elementData); + } + + return keys; +} + +template +int TaggedList::FindIndexByElement(const JSTaggedValue &element) +{ + int dataIndex = ELEMENTS_START_INDEX; + int nextDataIndex = GetElement(dataIndex + NEXT_PTR_OFFSET).GetInt(); + int nodeSum = 0; + while (nextDataIndex != ELEMENTS_START_INDEX) { + dataIndex = nextDataIndex; + JSTaggedValue data = GetElement(dataIndex); + nextDataIndex = GetElement(nextDataIndex + NEXT_PTR_OFFSET).GetInt(); + if (JSTaggedValue::SameValue(data, element)) { + return nodeSum; + } + nodeSum++; + } + return -1; +} + +template +int TaggedList::FindLastIndexByElement(const JSTaggedValue &element) +{ + int dataIndex = ELEMENTS_START_INDEX; + int nextIndex = GetElement(dataIndex + NEXT_PTR_OFFSET).GetInt(); + int nodeSum = 0; + int lastIndex = -1; + while (nextIndex != ELEMENTS_START_INDEX) { + dataIndex = nextIndex; + JSTaggedValue data = GetElement(dataIndex); + if (JSTaggedValue::SameValue(data, element)) { + lastIndex = nodeSum; + } + nextIndex = GetElement(nextIndex + NEXT_PTR_OFFSET).GetInt(); + nodeSum++; + } + return lastIndex; +} + +template +int TaggedList::FindDataIndexByNodeIndex(int index) const +{ + int dataIndex = ELEMENTS_START_INDEX; + int nextIndex = GetElement(dataIndex + NEXT_PTR_OFFSET).GetInt(); + int nodeSum = 0; + while (nextIndex != ELEMENTS_START_INDEX) { + dataIndex = nextIndex; + if (nodeSum == index) { + return dataIndex; + } + nextIndex = GetElement(nextIndex + NEXT_PTR_OFFSET).GetInt(); + nodeSum++; + } + return -1; +} + +template +void TaggedList::RemoveNode(JSThread *thread, int prevDataIndex) +{ + int tailTableIndex = GetElement(TAIL_TABLE_INDEX).GetInt(); + if (tailTableIndex != GetElement(HEAD_TABLE_INDEX).GetInt()) { + int dataIndex = GetElement(prevDataIndex + NEXT_PTR_OFFSET).GetInt(); + int nextDataIndex = GetElement(dataIndex + NEXT_PTR_OFFSET).GetInt(); + if (dataIndex == tailTableIndex) { + SetElement(thread, TAIL_TABLE_INDEX, JSTaggedValue(prevDataIndex)); + } + if (std::is_same_v) { + SetElement(thread, nextDataIndex + PREV_PTR_OFFSET, JSTaggedValue(prevDataIndex)); + } + SetElement(thread, dataIndex, JSTaggedValue::Hole()); + SetElement(thread, prevDataIndex + NEXT_PTR_OFFSET, JSTaggedValue(nextDataIndex)); + SetNumberOfNodes(thread, NumberOfNodes() - 1); + SetNumberOfDeletedNodes(thread, NumberOfDeletedNodes() + 1); + } +} + +template +int TaggedList::FindPrevNodeByIndex(int index) const +{ + int prevDataIndex = ELEMENTS_START_INDEX; + int nodeSum = 0; + int len = GetElement(NUMBER_OF_NODE_INDEX).GetInt(); + while (nodeSum <= len) { + if (nodeSum == index) { + return prevDataIndex; + } + prevDataIndex = GetElement(prevDataIndex + NEXT_PTR_OFFSET).GetInt(); + nodeSum++; + } + return -1; +} + +template +int TaggedList::FindPrevNodeByValue(const JSTaggedValue &element) +{ + int dataIndex = ELEMENTS_START_INDEX; + int nodeSum = 0; + int len = GetElement(NUMBER_OF_NODE_INDEX).GetInt(); + while (nodeSum <= len) { + int nextDataIndex = GetElement(dataIndex + NEXT_PTR_OFFSET).GetInt(); + JSTaggedValue data = GetElement(nextDataIndex); + if (JSTaggedValue::SameValue(data, element)) { + return dataIndex; + } + dataIndex = nextDataIndex; + nodeSum++; + } + return -1; +} + +template +JSTaggedValue TaggedList::FindElementByIndex(int index) const +{ + int dataIndex = ELEMENTS_START_INDEX; + int nextIndex = GetElement(dataIndex + NEXT_PTR_OFFSET).GetInt(); + int nodeSum = 0; + while (nextIndex != ELEMENTS_START_INDEX) { + dataIndex = nextIndex; + JSTaggedValue dataValue = GetElement(dataIndex); + if (nodeSum == index) { + return dataValue; + } + nextIndex = GetElement(nextIndex + NEXT_PTR_OFFSET).GetInt(); + nodeSum++; + } + return JSTaggedValue::Undefined(); +} + +template +JSTaggedValue TaggedList::RemoveByIndex(JSThread *thread, const int &index) +{ + int prevDataIndex = FindPrevNodeByIndex(index); + int curDataIndex = GetElement(prevDataIndex + NEXT_PTR_OFFSET).GetInt(); + JSTaggedValue data = GetElement(curDataIndex); + RemoveNode(thread, prevDataIndex); + return data; +} + +// TaggedSingleList +JSTaggedValue TaggedSingleList::Create(const JSThread *thread, int numberOfElements) +{ + return TaggedList::Create(thread, numberOfElements).GetTaggedValue(); +} + +JSTaggedValue TaggedSingleList::Add(const JSThread *thread, const JSHandle &taggedList, + const JSHandle &value) +{ + int prevDataIndex = taggedList->GetElement(TAIL_TABLE_INDEX).GetInt(); + return TaggedList::AddNode(thread, taggedList, value, -1, prevDataIndex); +} + +JSTaggedValue TaggedSingleList::ConvertToArray(const JSThread *thread, const JSHandle &taggedList) +{ + return JSTaggedValue(TaggedList::TaggedListToArray(thread, taggedList)); +} + +JSTaggedValue TaggedSingleList::Insert(JSThread *thread, const JSHandle &taggedList, + const JSHandle &value, const int index) +{ + int tailIndex = taggedList->GetElement(TAIL_TABLE_INDEX).GetInt(); + int prevDataIndex = (index == -1) ? tailIndex : taggedList->FindPrevNodeByIndex(index); + return TaggedList::AddNode(thread, taggedList, value, index, prevDataIndex); +} + +void TaggedSingleList::InsertNode(const JSThread *thread, const JSHandle &value, const int prevDataIndex, + const int finalDataIndex) +{ + int prevNextIndex = prevDataIndex + NEXT_PTR_OFFSET; + int nextDataIndex = GetElement(prevNextIndex).GetInt(); + SetElement(thread, prevNextIndex, JSTaggedValue(finalDataIndex)); + SetElement(thread, finalDataIndex, value.GetTaggedValue()); + SetElement(thread, finalDataIndex + 1, JSTaggedValue(nextDataIndex)); + SetNumberOfNodes(thread, NumberOfNodes() + 1); +} + +bool TaggedSingleList::Has(const JSTaggedValue &element) +{ + int dataIndex = FindIndexByElement(element); + return dataIndex != -1; +} + +bool TaggedSingleList::IsEmpty() const +{ + return NumberOfNodes() == 0; +} + +JSTaggedValue TaggedSingleList::Get(const int index) +{ + return FindElementByIndex(index); +} + +int TaggedSingleList::GetIndexOf(const JSTaggedValue &element) +{ + return FindIndexByElement(element); +} + +int TaggedSingleList::GetLastIndexOf(const JSTaggedValue &element) +{ + return FindLastIndexByElement(element); +} + +JSTaggedValue TaggedSingleList::Set(JSThread *thread, const JSHandle &taggedList, + const int index, const JSHandle &value) +{ + int dataIndex = taggedList->FindDataIndexByNodeIndex(index); + if (dataIndex == -1) { + return taggedList.GetTaggedValue(); + } + taggedList->SetElement(thread, dataIndex, value.GetTaggedValue()); + return taggedList.GetTaggedValue(); +} + +JSTaggedValue TaggedSingleList::ReplaceAllElements(JSThread *thread, const JSHandle &thisHandle, + const JSHandle &callbackFn, + const JSHandle &thisArg, + const JSHandle &taggedList) +{ + int length = taggedList->NumberOfNodes(); + JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); + for (int k = 0; k < length; k++) { + JSTaggedValue kValue = taggedList->Get(k); + JSTaggedValue key = JSTaggedValue(k); + EcmaRuntimeCallInfo info = + EcmaInterpreter::NewRuntimeCallInfo(thread, callbackFn, thisArg, undefined, 3); // 3:three args + info.SetCallArg(kValue, key, thisHandle.GetTaggedValue()); + JSTaggedValue funcResult = JSFunction::Call(&info); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, funcResult); + JSHandle funcResultValue = JSHandle(thread, funcResult); + TaggedSingleList::Set(thread, taggedList, k, funcResultValue); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + } + return JSTaggedValue::Undefined(); +} + +JSTaggedValue TaggedSingleList::Sort(JSThread *thread, const JSHandle &callbackFn, + const JSHandle &taggedList) +{ + int length = taggedList->NumberOfNodes(); + JSMutableHandle firstValue(thread, JSTaggedValue::Undefined()); + JSMutableHandle secondValue(thread, JSTaggedValue::Undefined()); + for (int i = 0; i < length; i++) { + for (int j = i + 1; j < length; j++) { + int firstIndex = taggedList->FindDataIndexByNodeIndex(i); + int secondIndex = taggedList->FindDataIndexByNodeIndex(j); + firstValue.Update(taggedList->GetElement(firstIndex)); + secondValue.Update(taggedList->GetElement(secondIndex)); + int32_t compareResult = base::ArrayHelper::SortCompare(thread, callbackFn, firstValue, secondValue); + if (compareResult > 0) { + taggedList->SetElement(thread, firstIndex, secondValue.GetTaggedValue()); + taggedList->SetElement(thread, secondIndex, firstValue.GetTaggedValue()); + } + } + } + return JSTaggedValue::Undefined(); +} + +JSTaggedValue TaggedSingleList::GetSubList(JSThread *thread, const JSHandle &taggedList, + const int fromIndex, const int toIndex, + const JSHandle &subList) +{ + int dataIndex = taggedList->FindDataIndexByNodeIndex(fromIndex); + int endIndex = taggedList->FindDataIndexByNodeIndex(toIndex); + int preDataIndex = ELEMENTS_START_INDEX; + int num = 0; + JSMutableHandle dataHandle(thread, JSTaggedValue::Undefined()); + JSHandle nextHandle(thread, JSTaggedValue(ELEMENTS_START_INDEX)); + while (dataIndex != endIndex) { + int elementDataIndex = ELEMENTS_START_INDEX + TaggedSingleList::ENTRY_SIZE + num * TaggedSingleList::ENTRY_SIZE; + dataHandle.Update(taggedList->GetElement(dataIndex)); + subList->SetElement(thread, preDataIndex + NEXT_PTR_OFFSET, JSTaggedValue(elementDataIndex)); + subList->SetElement(thread, elementDataIndex, dataHandle.GetTaggedValue()); + subList->SetElement(thread, elementDataIndex + NEXT_PTR_OFFSET, nextHandle.GetTaggedValue()); + subList->SetElement(thread, TAIL_TABLE_INDEX, JSTaggedValue(elementDataIndex)); + subList->SetNumberOfNodes(thread, num + 1); + dataIndex = taggedList->GetElement(dataIndex + NEXT_PTR_OFFSET).GetInt(); + preDataIndex = elementDataIndex; + num++; + } + subList->SetNumberOfDeletedNodes(thread, 0); + + return subList.GetTaggedValue(); +} + +JSTaggedValue TaggedSingleList::Equal(const JSHandle &compareList) +{ + int compareListLength = compareList->NumberOfNodes(); + if (compareListLength != NumberOfNodes()) { + return JSTaggedValue::False(); + } + int nodeSum = 0; + while (nodeSum < compareListLength) { + JSTaggedValue compareValue = compareList->Get(nodeSum); + JSTaggedValue value = Get(nodeSum); + if (compareValue != value) { + return JSTaggedValue::False(); + } + nodeSum++; + } + return JSTaggedValue::True(); +} + +void TaggedSingleList::Clear(const JSThread *thread) +{ + TaggedList::Clear(thread); +} + +JSTaggedValue TaggedSingleList::RemoveByIndex(JSThread *thread, const int &index) +{ + return TaggedList::RemoveByIndex(thread, index); +} + +JSTaggedValue TaggedSingleList::Remove(JSThread *thread, const JSTaggedValue &element) +{ + int prevDataIndex = FindPrevNodeByValue(element); + if (prevDataIndex == -1) { + return JSTaggedValue::False(); + } + RemoveNode(thread, prevDataIndex); + return JSTaggedValue::True(); +} + +JSHandle TaggedSingleList::OwnKeys(JSThread *thread, const JSHandle &taggedList) +{ + return TaggedList::OwnKeys(thread, taggedList); +} + +// TaggedDoubleList +JSTaggedValue TaggedDoubleList::Create(const JSThread *thread, int numberOfElements) +{ + JSHandle taggedList = TaggedList::Create(thread, numberOfElements); + taggedList->SetElement(thread, ELEMENTS_START_INDEX + PREV_PTR_OFFSET, JSTaggedValue(ELEMENTS_START_INDEX)); + return taggedList.GetTaggedValue(); +} + +JSTaggedValue TaggedDoubleList::Add(const JSThread *thread, const JSHandle &taggedList, + const JSHandle &value) +{ + int prevDataIndex = taggedList->GetElement(TAIL_TABLE_INDEX).GetInt(); + return TaggedList::AddNode(thread, taggedList, value, -1, prevDataIndex); +} + +JSTaggedValue TaggedDoubleList::AddFirst(const JSThread *thread, const JSHandle &taggedList, + const JSHandle &value) +{ + int prevDataIndex = taggedList->FindPrevNodeByIndex(0); + return TaggedList::AddNode(thread, taggedList, value, 0, prevDataIndex); +} + +JSTaggedValue TaggedDoubleList::ConvertToArray(const JSThread *thread, const JSHandle &taggedList) +{ + return JSTaggedValue(TaggedList::TaggedListToArray(thread, taggedList)); +} + +JSTaggedValue TaggedDoubleList::Insert(JSThread *thread, const JSHandle &taggedList, + const JSHandle &value, const int index) +{ + int prevDataIndex = 0; + int len = taggedList->NumberOfNodes(); + int leftNodeLen = len - 1 - index; + if (leftNodeLen == -1) { + prevDataIndex = taggedList->GetElement(TAIL_TABLE_INDEX).GetInt(); + } else { + // 2 : 2 MEANS the half + if ((len / 2) > index) { + prevDataIndex = taggedList->FindPrevNodeByIndex(index); + } else { + prevDataIndex = taggedList->FindPrevNodeByIndexAtLast(leftNodeLen); + } + } + return TaggedList::AddNode(thread, taggedList, value, index, prevDataIndex); +} + +void TaggedDoubleList::InsertNode(const JSThread *thread, const JSHandle &value, const int prevDataIndex, + const int finalDataIndex) +{ + int prevNextIndex = prevDataIndex + NEXT_PTR_OFFSET; + int nextDataIndex = GetElement(prevNextIndex).GetInt(); + int nextPrevIndex = nextDataIndex + PREV_PTR_OFFSET; + SetElement(thread, prevNextIndex, JSTaggedValue(finalDataIndex)); + SetElement(thread, nextPrevIndex, JSTaggedValue(finalDataIndex)); + SetElement(thread, finalDataIndex, value.GetTaggedValue()); + SetElement(thread, finalDataIndex + NEXT_PTR_OFFSET, JSTaggedValue(nextDataIndex)); + SetElement(thread, finalDataIndex + PREV_PTR_OFFSET, JSTaggedValue(prevDataIndex)); + SetNumberOfNodes(thread, NumberOfNodes() + 1); +} + +bool TaggedDoubleList::Has(const JSTaggedValue &element) +{ + int dataIndex = FindIndexByElement(element); + return dataIndex != -1; +} + +JSTaggedValue TaggedDoubleList::Get(const int index) +{ + int len = NumberOfNodes(); + // 2 : 2 MEANS the half + if (len / 2 > index) { + return FindElementByIndex(index); + } else { + return FindElementByIndexAtLast(index); + } +} + +int TaggedDoubleList::GetIndexOf(const JSTaggedValue &element) +{ + return FindIndexByElement(element); +} + +int TaggedDoubleList::GetLastIndexOf(const JSTaggedValue &element) +{ + return FindLastIndexByElement(element); +} + +JSTaggedValue TaggedDoubleList::Set(JSThread *thread, const JSHandle &taggedList, const int index, + const JSHandle &value) +{ + int nodeLength = taggedList->NumberOfNodes(); + if (index < 0 || index >= nodeLength) { + THROW_RANGE_ERROR_AND_RETURN(thread, "Set index out-of-bounds", JSTaggedValue::Exception()); + } + int dataIndex = taggedList->FindDataIndexByNodeIndex(index); + if (dataIndex == -1) { + THROW_RANGE_ERROR_AND_RETURN(thread, "Set index not exist", JSTaggedValue::Exception()); + } + taggedList->SetElement(thread, dataIndex, value.GetTaggedValue()); + return taggedList.GetTaggedValue(); +} + +void TaggedDoubleList::Clear(const JSThread *thread) +{ + TaggedList::Clear(thread); + SetElement(thread, ELEMENTS_START_INDEX + PREV_PTR_OFFSET, JSTaggedValue(ELEMENTS_START_INDEX)); +} + +JSTaggedValue TaggedDoubleList::RemoveFirst(JSThread *thread) +{ + int prevDataIndex = FindPrevNodeByIndex(0); + int firstDataIndex = GetElement(ELEMENTS_START_INDEX + NEXT_PTR_OFFSET).GetInt(); + JSTaggedValue firstData = GetElement(firstDataIndex); + RemoveNode(thread, prevDataIndex); + return firstData; +} + +JSTaggedValue TaggedDoubleList::RemoveLast(JSThread *thread) +{ + int prevDataIndex = FindPrevNodeByIndex(NumberOfNodes() - 1); + int lastDataIndex = GetElement(ELEMENTS_START_INDEX + 2).GetInt(); + JSTaggedValue lastData = GetElement(lastDataIndex); + RemoveNode(thread, prevDataIndex); + return lastData; +} + +JSTaggedValue TaggedDoubleList::RemoveByIndex(JSThread *thread, const int &index) +{ + return TaggedList::RemoveByIndex(thread, index); +} + +JSTaggedValue TaggedDoubleList::Remove(JSThread *thread, const JSTaggedValue &element) +{ + int prevDataIndex = FindPrevNodeByValue(element); + if (prevDataIndex == -1) { + return JSTaggedValue::False(); + } + RemoveNode(thread, prevDataIndex); + return JSTaggedValue::True(); +} + +JSTaggedValue TaggedDoubleList::RemoveFirstFound(JSThread *thread, const JSHandle &taggedList, + const JSTaggedValue &element) +{ + int prevDataIndex = taggedList->FindPrevNodeByValue(element); + if (prevDataIndex == -1) { + THROW_RANGE_ERROR_AND_RETURN(thread, "this element is not exist in this container", JSTaggedValue::Exception()); + } + taggedList->RemoveNode(thread, prevDataIndex); + return JSTaggedValue::True(); +} + +JSTaggedValue TaggedDoubleList::RemoveLastFound(JSThread *thread, const JSHandle &taggedList, + const JSTaggedValue &element) +{ + int prevDataIndex = taggedList->FindPrevNodeByValueAtLast(element); + if (prevDataIndex == -1) { + THROW_RANGE_ERROR_AND_RETURN(thread, "this element is not exist in this container", JSTaggedValue::Exception()); + } + taggedList->RemoveNode(thread, prevDataIndex); + return JSTaggedValue::True(); +} + +JSHandle TaggedDoubleList::OwnKeys(JSThread *thread, const JSHandle &taggedList) +{ + return TaggedList::OwnKeys(thread, taggedList); +} + +JSTaggedValue TaggedDoubleList::FindElementByIndexAtLast(int index) const +{ + int dataIndex = ELEMENTS_START_INDEX; + int preDataIndex = GetElement(dataIndex + PREV_PTR_OFFSET).GetInt(); + int nodeSum = GetElement(NUMBER_OF_NODE_INDEX).GetInt() - 1; + while (preDataIndex != ELEMENTS_START_INDEX) { + dataIndex = preDataIndex; + JSTaggedValue dataValue = GetElement(dataIndex); + if (nodeSum == index) { + return dataValue; + } + preDataIndex = GetElement(preDataIndex + PREV_PTR_OFFSET).GetInt(); + nodeSum--; + } + return JSTaggedValue::Undefined(); +} + +int TaggedDoubleList::FindPrevNodeByIndexAtLast(const int index) const +{ + int prevDataIndex = GetElement(ELEMENTS_START_INDEX + PREV_PTR_OFFSET).GetInt(); + int nodeSum = 0; + int len = GetElement(NUMBER_OF_NODE_INDEX).GetInt(); + while (nodeSum <= len) { + int prePreDataIndex = GetElement(prevDataIndex + PREV_PTR_OFFSET).GetInt(); + if (nodeSum == index) { + return prePreDataIndex; + } + prevDataIndex = prePreDataIndex; + nodeSum++; + } + return -1; +} + +int TaggedDoubleList::FindPrevNodeByValueAtLast(const JSTaggedValue &element) +{ + int prevDataIndex = GetElement(ELEMENTS_START_INDEX + PREV_PTR_OFFSET).GetInt(); + int nodeSum = 0; + int len = GetElement(NUMBER_OF_NODE_INDEX).GetInt(); + while (nodeSum <= len) { + int prePreDataIndex = GetElement(prevDataIndex + PREV_PTR_OFFSET).GetInt(); + JSTaggedValue data = GetElement(prevDataIndex); + if (JSTaggedValue::SameValue(data, element)) { + return prePreDataIndex; + } + prevDataIndex = prePreDataIndex; + nodeSum++; + } + return -1; +} +} // namespace panda::ecmascript diff --git a/ecmascript/tagged_list.h b/ecmascript/tagged_list.h new file mode 100644 index 0000000000..daa20117d1 --- /dev/null +++ b/ecmascript/tagged_list.h @@ -0,0 +1,190 @@ +/* + * 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. + */ + +#ifndef ECMASCRIPT_TAGGED_LIST_H +#define ECMASCRIPT_TAGGED_LIST_H + +#include "ecmascript/js_tagged_value.h" +#include "js_handle.h" +#include "js_symbol.h" +#include "js_tagged_number.h" +#include "tagged_array.h" + +namespace panda::ecmascript { +template +class TaggedList : public TaggedArray { +public: + static const int NUMBER_OF_NODE_INDEX = 0; + static const int NUMBER_OF_DELETED_NODES_INDEX = 1; + static const int HEAD_TABLE_INDEX = 2; + static const int TAIL_TABLE_INDEX = 3; + static const int ELEMENTS_START_INDEX = 4; + static const int DEFAULT_ARRAY_LENGHT = 10; + static const int NEXT_PTR_OFFSET = 1; + static const int PREV_PTR_OFFSET = 2; + + static JSHandle Create(const JSThread *thread, int numberOfNodes = DEFAULT_ARRAY_LENGHT); + static JSHandle GrowCapacity(const JSThread *thread, const JSHandle &taggedList); + static JSTaggedValue AddNode(const JSThread *thread, const JSHandle &taggedList, + const JSHandle &value, const int index, int prevDataIndex); + static JSTaggedValue TaggedListToArray(const JSThread *thread, const JSHandle &taggedList); + static JSHandle OwnKeys(JSThread *thread, const JSHandle &taggedList); + void CopyArray(const JSThread *thread, JSHandle &taggedList); + void Clear(const JSThread *thread); + JSTaggedValue FindElementByIndex(int index) const; + int FindIndexByElement(const JSTaggedValue &element); + int FindLastIndexByElement(const JSTaggedValue &element); + int FindDataIndexByNodeIndex(int index) const; + void RemoveNode(JSThread *thread, int prevDataIndex); + int FindPrevNodeByIndex(int index) const; + int FindPrevNodeByValue(const JSTaggedValue &element); + JSTaggedValue RemoveByIndex(JSThread *thread, const int &index); + inline int Length() + { + return NumberOfNodes(); + } + + inline JSTaggedValue GetFirst() + { + int firstDataIndex = GetElement(ELEMENTS_START_INDEX + NEXT_PTR_OFFSET).GetInt(); + return GetElement(firstDataIndex); + } + + inline JSTaggedValue GetLast() + { + int lastDataIndex = GetElement(TAIL_TABLE_INDEX).GetInt(); + return GetElement(lastDataIndex); + } + + inline int GetCapacityFromTaggedArray() + { + return static_cast(GetLength()); + } + + inline void SetElement(const JSThread *thread, int index, const JSTaggedValue &element) + { + ASSERT(index >= 0 && index < static_cast(GetLength())); + Set(thread, index, element); + } + + inline JSTaggedValue GetElement(int index) const + { + ASSERT(index >= 0 && index < static_cast(GetLength())); + return Get(index); + } + + inline int NumberOfNodes() const + { + return Get(NUMBER_OF_NODE_INDEX).GetInt(); + } + + inline int NumberOfDeletedNodes() const + { + return Get(NUMBER_OF_DELETED_NODES_INDEX).GetInt(); + } + + inline void SetNumberOfDeletedNodes(const JSThread *thread, int nod) + { + Set(thread, NUMBER_OF_DELETED_NODES_INDEX, JSTaggedValue(nod)); + } + + inline void SetNumberOfNodes(const JSThread *thread, int nof) + { + Set(thread, NUMBER_OF_NODE_INDEX, JSTaggedValue(nof)); + } +}; + +class TaggedSingleList : public TaggedList { +public: + static const int ENTRY_SIZE = 2; + static TaggedSingleList *Cast(ObjectHeader *obj) + { + return static_cast(obj); + } + + static JSTaggedValue Create(const JSThread *thread, int numberOfElements = TaggedSingleList::DEFAULT_ARRAY_LENGHT); + static JSTaggedValue Add(const JSThread *thread, const JSHandle &taggedList, + const JSHandle &value); + static JSTaggedValue Insert(JSThread *thread, const JSHandle &taggedList, + const JSHandle &value, const int index); + static JSTaggedValue Set(JSThread *thread, const JSHandle &taggedList, + const int index, const JSHandle &value); + static JSTaggedValue ReplaceAllElements(JSThread *thread, const JSHandle &thisHandle, + const JSHandle &callbackFn, + const JSHandle &thisArg, + const JSHandle &taggedList); + static JSTaggedValue Sort(JSThread *thread, const JSHandle &callbackFn, + const JSHandle &taggedList); + static JSTaggedValue ConvertToArray(const JSThread *thread, const JSHandle &taggedList); + static JSTaggedValue GetSubList(JSThread *thread, const JSHandle &taggedList, + const int fromIndex, const int toIndex, const JSHandle &subList); + static JSHandle OwnKeys(JSThread *thread, const JSHandle &taggedList); + void Clear(const JSThread *thread); + bool IsEmpty() const; + bool Has(const JSTaggedValue &value); + JSTaggedValue Get(const int index); + int GetIndexOf(const JSTaggedValue &value); + int GetLastIndexOf(const JSTaggedValue &value); + void InsertNode(const JSThread *thread, const JSHandle &value, const int prevDataIndex, + const int finalDataIndex); + JSTaggedValue RemoveByIndex(JSThread *thread, const int &index); + JSTaggedValue Remove(JSThread *thread, const JSTaggedValue &element); + JSTaggedValue Equal(const JSHandle &compareList); + DECL_DUMP() +}; + +class TaggedDoubleList : public TaggedList { +public: + static const int ENTRY_SIZE = 3; + static TaggedDoubleList *Cast(ObjectHeader *obj) + { + return static_cast(obj); + } + + static JSTaggedValue Create(const JSThread *thread, int numberOfElements = TaggedDoubleList::DEFAULT_ARRAY_LENGHT); + static JSTaggedValue Add(const JSThread *thread, const JSHandle &taggedList, + const JSHandle &value); + static JSTaggedValue AddFirst(const JSThread *thread, const JSHandle &taggedList, + const JSHandle &value); + static JSTaggedValue Insert(JSThread *thread, const JSHandle &taggedList, + const JSHandle &value, const int index); + static JSTaggedValue Set(JSThread *thread, const JSHandle &taggedList, const int index, + const JSHandle &value); + static JSTaggedValue ConvertToArray(const JSThread *thread, const JSHandle &taggedList); + static JSHandle OwnKeys(JSThread *thread, const JSHandle &taggedList); + static JSTaggedValue RemoveFirstFound(JSThread *thread, const JSHandle &taggedList, + const JSTaggedValue &element); + static JSTaggedValue RemoveLastFound(JSThread *thread, const JSHandle &taggedList, + const JSTaggedValue &element); + void Clear(const JSThread *thread); + JSTaggedValue Get(const int index); + bool Has(const JSTaggedValue &value); + void InsertNode(const JSThread *thread, const JSHandle &value, const int prevDataIndex, + const int finalDataIndex); + JSTaggedValue RemoveFirst(JSThread *thread); + JSTaggedValue RemoveLast(JSThread *thread); + JSTaggedValue RemoveByIndex(JSThread *thread, const int &index); + JSTaggedValue Remove(JSThread *thread, const JSTaggedValue &element); + int GetIndexOf(const JSTaggedValue &value); + int GetLastIndexOf(const JSTaggedValue &value); + int FindPrevNodeByIndexAtLast(const int index) const; + int FindPrevNodeByValueAtLast(const JSTaggedValue &element); + DECL_DUMP() + +protected: + inline JSTaggedValue FindElementByIndexAtLast(int index) const; +}; +} // namespace panda::ecmascript +#endif // ECMASCRIPT_TAGGED_LIST_H diff --git a/ecmascript/tagged_tree.cpp b/ecmascript/tagged_tree.cpp index 6f59040582..975a8fef07 100644 --- a/ecmascript/tagged_tree.cpp +++ b/ecmascript/tagged_tree.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/tagged_tree.h b/ecmascript/tagged_tree.h index e86ffb003a..5c2722a1ec 100644 --- a/ecmascript/tagged_tree.h +++ b/ecmascript/tagged_tree.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/tests/BUILD.gn b/ecmascript/tests/BUILD.gn index 415a0fa85f..09327dd2b0 100644 --- a/ecmascript/tests/BUILD.gn +++ b/ecmascript/tests/BUILD.gn @@ -40,6 +40,8 @@ host_unittest_action("EcmaVmTest") { "js_api_arraylist_test.cpp", "js_api_deque_iterator_test.cpp", "js_api_deque_test.cpp", + "js_api_linked_list_test.cpp", + "js_api_list_test.cpp", "js_api_plain_array_test.cpp", "js_api_queue_test.cpp", "js_api_stack_iterator_test.cpp", diff --git a/ecmascript/tests/dump_test.cpp b/ecmascript/tests/dump_test.cpp index 83729a2ace..504a88b2c2 100644 --- a/ecmascript/tests/dump_test.cpp +++ b/ecmascript/tests/dump_test.cpp @@ -33,6 +33,10 @@ #include "ecmascript/js_api_arraylist_iterator.h" #include "ecmascript/js_api_deque.h" #include "ecmascript/js_api_deque_iterator.h" +#include "ecmascript/js_api_linked_list.h" +#include "ecmascript/js_api_linked_list_iterator.h" +#include "ecmascript/js_api_list.h" +#include "ecmascript/js_api_list_iterator.h" #include "ecmascript/js_api_plain_array.h" #include "ecmascript/js_api_plain_array_iterator.h" #include "ecmascript/js_api_queue.h" @@ -95,6 +99,7 @@ #include "ecmascript/object_factory.h" #include "ecmascript/tagged_array.h" #include "ecmascript/tagged_dictionary.h" +#include "ecmascript/tagged_list.h" #include "ecmascript/tagged_tree.h" #include "ecmascript/template_map.h" #include "ecmascript/tests/test_helper.h" @@ -208,6 +213,28 @@ static JSHandle NewJSAPIPlainArray(JSThread *thread, ObjectFact return jSAPIPlainArray; } +static JSHandle NewJSAPIList(JSThread *thread, ObjectFactory *factory) +{ + auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv(); + JSHandle proto = globalEnv->GetObjectFunctionPrototype(); + JSHandle listClass = factory->NewEcmaDynClass(JSAPIList::SIZE, JSType::JS_API_LIST, proto); + JSHandle jsAPIList = JSHandle::Cast(factory->NewJSObjectWithInit(listClass)); + JSHandle taggedSingleList(thread, TaggedSingleList::Create(thread)); + jsAPIList->SetSingleList(thread, taggedSingleList); + return jsAPIList; +} + +static JSHandle NewJSAPILinkedList(JSThread *thread, ObjectFactory *factory) +{ + auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv(); + JSHandle proto = globalEnv->GetObjectFunctionPrototype(); + JSHandle mapClass = factory->NewEcmaDynClass(JSAPILinkedList::SIZE, JSType::JS_API_LINKED_LIST, proto); + JSHandle jsAPILinkedList = JSHandle::Cast(factory->NewJSObjectWithInit(mapClass)); + JSHandle linkedlist(thread, TaggedDoubleList::Create(thread)); + jsAPILinkedList->SetDoubleList(thread, linkedlist); + return jsAPILinkedList; +} + static JSHandle NewJSObject(JSThread *thread, ObjectFactory *factory, JSHandle globalEnv) { JSFunction *jsFunc = globalEnv->GetObjectFunction().GetObject(); @@ -955,6 +982,37 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump) DUMP_FOR_HANDLE(jsVectorIter) break; } + case JSType::JS_API_LIST: { + // 1 : 1 dump fileds number + CHECK_DUMP_FIELDS(JSObject::SIZE, JSAPIList::SIZE, 1U) + JSHandle jsAPIList = NewJSAPIList(thread, factory); + DUMP_FOR_HANDLE(jsAPIList) + break; + } + case JSType::JS_API_LINKED_LIST: { + // 1 : 1 dump fileds number + CHECK_DUMP_FIELDS(JSObject::SIZE, JSAPILinkedList::SIZE, 1U) + JSHandle jsAPILinkedList = NewJSAPILinkedList(thread, factory); + DUMP_FOR_HANDLE(jsAPILinkedList) + break; + } + case JSType::JS_API_LIST_ITERATOR: { + // 2 : 2 dump fileds number + CHECK_DUMP_FIELDS(JSObject::SIZE, JSAPIListIterator::SIZE, 2U) + JSHandle jsAPIList = NewJSAPIList(thread, factory); + JSHandle jsAPIListIter = factory->NewJSAPIListIterator(jsAPIList); + DUMP_FOR_HANDLE(jsAPIListIter) + break; + } + case JSType::JS_API_LINKED_LIST_ITERATOR: { + // 2 : 2 dump fileds number + CHECK_DUMP_FIELDS(JSObject::SIZE, JSAPIListIterator::SIZE, 2U) + JSHandle jsAPILinkedList = NewJSAPILinkedList(thread, factory); + JSHandle jsAPILinkedListIter = + factory->NewJSAPILinkedListIterator(jsAPILinkedList); + DUMP_FOR_HANDLE(jsAPILinkedListIter) + break; + } case JSType::MODULE_RECORD: { CHECK_DUMP_FIELDS(Record::SIZE, ModuleRecord::SIZE, 0U); break; diff --git a/ecmascript/tests/js_api_arraylist_test.cpp b/ecmascript/tests/js_api_arraylist_test.cpp index 709d9c453d..4a7216f76f 100644 --- a/ecmascript/tests/js_api_arraylist_test.cpp +++ b/ecmascript/tests/js_api_arraylist_test.cpp @@ -535,10 +535,9 @@ HWTEST_F_L0(JSAPIArrayListTest, GetOwnProperty) JSHandle value(thread, JSTaggedValue(i)); JSAPIArrayList::Add(thread, arrayList, value); } - PropertyDescriptor descRes(thread); for (uint32_t i = 0; i < elementsNums; i++) { JSHandle key(thread, JSTaggedValue(i)); - bool getOwnPropertyRes = JSAPIArrayList::GetOwnProperty(thread, arrayList, key, descRes); + bool getOwnPropertyRes = JSAPIArrayList::GetOwnProperty(thread, arrayList, key); EXPECT_EQ(getOwnPropertyRes, true); } } diff --git a/ecmascript/tests/js_api_deque_test.cpp b/ecmascript/tests/js_api_deque_test.cpp index 23fb5523dc..c7feb59bc5 100644 --- a/ecmascript/tests/js_api_deque_test.cpp +++ b/ecmascript/tests/js_api_deque_test.cpp @@ -167,4 +167,27 @@ HWTEST_F_L0(JSAPIDequeTest, PopLast) toor->Dump(); } + +HWTEST_F_L0(JSAPIDequeTest, GetOwnProperty) +{ + constexpr uint32_t DEFAULT_LENGTH = 8; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + JSHandle toor(thread, CreateDeque()); + + std::string dequeValue("dequevalue"); + for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) { + std::string ivalue = dequeValue + std::to_string(i); + value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); + JSAPIDeque::InsertFront(thread, toor, value); + JSAPIDeque::InsertEnd(thread, toor, value); + } + // test GetOwnProperty + int testInt = 1; + JSHandle dequeKey1(thread, JSTaggedValue(testInt)); + EXPECT_TRUE(JSAPIDeque::GetOwnProperty(thread, toor, dequeKey1)); + testInt = 20; + JSHandle dequeKey2(thread, JSTaggedValue(testInt)); + EXPECT_FALSE(JSAPIDeque::GetOwnProperty(thread, toor, dequeKey2)); +} } // namespace panda::test diff --git a/ecmascript/tests/js_api_linked_list_test.cpp b/ecmascript/tests/js_api_linked_list_test.cpp new file mode 100644 index 0000000000..494689d800 --- /dev/null +++ b/ecmascript/tests/js_api_linked_list_test.cpp @@ -0,0 +1,338 @@ +/* + * 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. + */ + +#include "ecmascript/containers/containers_private.h" +#include "ecmascript/ecma_string.h" +#include "ecmascript/ecma_vm.h" +#include "ecmascript/global_env.h" +#include "ecmascript/js_api_linked_list.h" +#include "ecmascript/js_api_linked_list_iterator.h" +#include "ecmascript/js_function.h" +#include "ecmascript/js_handle.h" +#include "ecmascript/js_iterator.h" +#include "ecmascript/js_object-inl.h" +#include "ecmascript/js_tagged_value.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/tagged_list.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda; + +using namespace panda::ecmascript; + +using namespace panda::ecmascript::containers; + +namespace panda::test { +class JSAPILinkedListTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(instance, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + + EcmaVM *instance {nullptr}; + ecmascript::EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; + +protected: + JSAPILinkedList *CreateLinkedList() + { + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + + JSHandle globalObject = env->GetJSGlobalObject(); + JSHandle key(factory->NewFromASCII("ArkPrivate")); + JSHandle value = + JSObject::GetProperty(thread, JSHandle(globalObject), key).GetValue(); + + auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + objCallInfo->SetFunction(JSTaggedValue::Undefined()); + objCallInfo->SetThis(value.GetTaggedValue()); + // 6 : 6 value is 6. + objCallInfo->SetCallArg(0, JSTaggedValue(6)); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo.get()); + JSHandle contianer = + JSHandle(thread, ContainersPrivate::Load(objCallInfo.get())); + JSHandle linkedList = + JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(contianer), + contianer)); + JSTaggedValue doubleList = TaggedDoubleList::Create(thread); + linkedList->SetDoubleList(thread, doubleList); + return *linkedList; + } +}; + +HWTEST_F_L0(JSAPILinkedListTest, LinkedListCreate) +{ + JSAPILinkedList *linkedlist = CreateLinkedList(); + EXPECT_TRUE(linkedlist != nullptr); +} + +HWTEST_F_L0(JSAPILinkedListTest, AddAndHas) +{ + constexpr int NODE_NUMBERS = 9; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + + JSHandle toor(thread, CreateLinkedList()); + + std::string myValue("myvalue"); + for (int i = 0; i < NODE_NUMBERS; i++) { + std::string ivalue = myValue + std::to_string(i); + value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); + JSAPILinkedList::Add(thread, toor, value); + } + EXPECT_EQ(toor->Length(), NODE_NUMBERS); + + for (int i = 0; i < NODE_NUMBERS; i++) { + std::string ivalue = myValue + std::to_string(i); + value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); + + JSTaggedValue gValue = toor->Get(i); + EXPECT_EQ(gValue, value.GetTaggedValue()); + } + JSTaggedValue gValue = toor->Get(10); + EXPECT_EQ(gValue, JSTaggedValue::Undefined()); + + std::string ivalue = myValue + std::to_string(1); + value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); + EXPECT_TRUE(toor->Has(value.GetTaggedValue())); +} + +HWTEST_F_L0(JSAPILinkedListTest, AddFirstAndGetFirst) +{ + JSHandle value(thread, JSTaggedValue(1)); + JSHandle list(thread, CreateLinkedList()); + list->Add(thread, list, value); + EXPECT_EQ(list->Length(), 1); + EXPECT_EQ(list->Get(0).GetInt(), 1); + + JSHandle value1(thread, JSTaggedValue(2)); + list->AddFirst(thread, list, value1); + EXPECT_EQ(list->Length(), 2); + EXPECT_EQ(list->GetFirst().GetInt(), 2); +} + +HWTEST_F_L0(JSAPILinkedListTest, InsertAndGetLast) +{ // create jsMap + constexpr uint32_t NODE_NUMBERS = 9; + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + + JSHandle toor(thread, CreateLinkedList()); + EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined()); + EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined()); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i + 1)); + JSAPILinkedList::Add(thread, toor, value); + } + EXPECT_EQ(toor->GetLast().GetInt(), 9); + EXPECT_EQ(toor->GetFirst().GetInt(), 1); + + value.Update(JSTaggedValue(99)); + int len = toor->Length(); + toor->Insert(thread, toor, value, len); + EXPECT_EQ(toor->GetLast().GetInt(), 99); + EXPECT_EQ(toor->Length(), 10); + + value.Update(JSTaggedValue(100)); + toor->Insert(thread, toor, value, 0); + EXPECT_EQ(toor->GetFirst().GetInt(), 100); + EXPECT_EQ(toor->Length(), 11); + + toor->Dump(); + + value.Update(JSTaggedValue(101)); + toor->Insert(thread, toor, value, 5); + EXPECT_EQ(toor->Length(), 12); + toor->Dump(); + EXPECT_EQ(toor->Get(5).GetInt(), 101); +} + +HWTEST_F_L0(JSAPILinkedListTest, GetIndexOfAndGetLastIndexOf) +{ // create jsMap + constexpr uint32_t NODE_NUMBERS = 9; + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + + JSHandle toor(thread, CreateLinkedList()); + EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined()); + EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined()); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i + 1)); + JSAPILinkedList::Add(thread, toor, value); + } + EXPECT_EQ(toor->GetLast().GetInt(), 9); + EXPECT_EQ(toor->GetFirst().GetInt(), 1); + + value.Update(JSTaggedValue(99)); + int len = toor->Length(); + toor->Insert(thread, toor, value, len); + EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), 9); + EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), 9); + EXPECT_EQ(toor->Length(), 10); + + value.Update(JSTaggedValue(100)); + toor->Insert(thread, toor, value, 0); + EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), 0); + EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), 0); + EXPECT_EQ(toor->Length(), 11); + + value.Update(JSTaggedValue(101)); + toor->Insert(thread, toor, value, 5); + EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), 5); + EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), 5); + EXPECT_EQ(toor->Length(), 12); + + toor->Dump(); +} + +HWTEST_F_L0(JSAPILinkedListTest, Remove) +{ // create jsMap + constexpr uint32_t NODE_NUMBERS = 20; + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + + JSHandle toor(thread, CreateLinkedList()); + EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined()); + EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined()); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i)); + JSAPILinkedList::Add(thread, toor, value); + } + EXPECT_EQ(toor->Length(), 20); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i)); + JSTaggedValue gValue = toor->Get(i); + EXPECT_EQ(gValue, value.GetTaggedValue()); + } + + EXPECT_EQ(JSAPILinkedList::RemoveFirst(thread, toor), JSTaggedValue(0)); + value.Update(JSTaggedValue(0)); + EXPECT_EQ(toor->Has(value.GetTaggedValue()), false); + EXPECT_EQ(toor->Length(), 19); + + EXPECT_EQ(JSAPILinkedList::RemoveLast(thread, toor), JSTaggedValue(19)); + value.Update(JSTaggedValue(19)); + EXPECT_EQ(toor->Has(value.GetTaggedValue()), false); + EXPECT_EQ(toor->Length(), 18); + + value.Update(JSTaggedValue(5)); + EXPECT_EQ(JSAPILinkedList::RemoveByIndex(thread, toor, 4), value.GetTaggedValue()); + EXPECT_EQ(toor->Has(value.GetTaggedValue()), false); + EXPECT_EQ(toor->Length(), 17); + + value.Update(JSTaggedValue(8)); + EXPECT_EQ(toor->Remove(thread, value.GetTaggedValue()), JSTaggedValue::True()); + EXPECT_EQ(toor->Has(value.GetTaggedValue()), false); + EXPECT_EQ(toor->Length(), 16); + + value.Update(JSTaggedValue(11)); + EXPECT_EQ(JSAPILinkedList::RemoveFirstFound(thread, toor, value.GetTaggedValue()), JSTaggedValue::True()); + EXPECT_EQ(toor->Has(value.GetTaggedValue()), false); + EXPECT_EQ(toor->Length(), 15); + + value.Update(JSTaggedValue(14)); + EXPECT_EQ(JSAPILinkedList::RemoveLastFound(thread, toor, value.GetTaggedValue()), JSTaggedValue::True()); + EXPECT_EQ(toor->Has(value.GetTaggedValue()), false); + EXPECT_EQ(toor->Length(), 14); + + toor->Dump(); +} + +HWTEST_F_L0(JSAPILinkedListTest, Clear) +{ + JSAPILinkedList *linkedlist = CreateLinkedList(); + + JSHandle value(thread, JSTaggedValue(1)); + JSHandle list(thread, linkedlist); + linkedlist->Add(thread, list, value); + + JSHandle value1(thread, JSTaggedValue(2)); + linkedlist->Insert(thread, list, value1, 0); + + linkedlist->Clear(thread); + + EXPECT_EQ(linkedlist->Length(), 0); + EXPECT_TRUE(linkedlist->GetFirst() == JSTaggedValue::Undefined()); +} + +HWTEST_F_L0(JSAPILinkedListTest, Set) +{ + constexpr uint32_t NODE_NUMBERS = 20; + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + + JSHandle toor(thread, CreateLinkedList()); + EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined()); + EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined()); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i)); + JSAPILinkedList::Add(thread, toor, value); + } + EXPECT_EQ(toor->Length(), 20); + + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i)); + JSTaggedValue gValue = toor->Get(i); + EXPECT_EQ(gValue, value.GetTaggedValue()); + } + + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i + 1)); + JSAPILinkedList::Set(thread, toor, i, value); + } + + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i + 1)); + JSTaggedValue gValue = toor->Get(i); + EXPECT_EQ(gValue, value.GetTaggedValue()); + } +} + +HWTEST_F_L0(JSAPILinkedListTest, GetOwnProperty) +{ + constexpr uint32_t DEFAULT_LENGTH = 8; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + JSHandle toor(thread, CreateLinkedList()); + + std::string linkedListvalue("linkedListvalue"); + for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) { + std::string ivalue = linkedListvalue + std::to_string(i); + value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); + JSAPILinkedList::Add(thread, toor, value); + } + // test GetOwnProperty + int testInt = 1; + JSHandle linkedListKey1(thread, JSTaggedValue(testInt)); + EXPECT_TRUE(JSAPILinkedList::GetOwnProperty(thread, toor, linkedListKey1)); + testInt = 20; + JSHandle linkedListKey2(thread, JSTaggedValue(testInt)); + EXPECT_FALSE(JSAPILinkedList::GetOwnProperty(thread, toor, linkedListKey2)); +} +} // namespace panda::test diff --git a/ecmascript/tests/js_api_list_test.cpp b/ecmascript/tests/js_api_list_test.cpp new file mode 100644 index 0000000000..b1ba952399 --- /dev/null +++ b/ecmascript/tests/js_api_list_test.cpp @@ -0,0 +1,303 @@ +/* + * 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. + */ + +#include "ecmascript/containers/containers_private.h" +#include "ecmascript/ecma_string.h" +#include "ecmascript/ecma_vm.h" +#include "ecmascript/global_env.h" +#include "ecmascript/js_api_list.h" +#include "ecmascript/js_api_list_iterator.h" +#include "ecmascript/js_function.h" +#include "ecmascript/js_handle.h" +#include "ecmascript/js_iterator.h" +#include "ecmascript/js_object-inl.h" +#include "ecmascript/js_tagged_value.h" +#include "ecmascript/object_factory.h" +#include "ecmascript/tagged_list.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda; + +using namespace panda::ecmascript; + +using namespace panda::ecmascript::containers; + +namespace panda::test { +class JSAPIListTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(instance, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + + EcmaVM *instance {nullptr}; + ecmascript::EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; + +protected: + JSAPIList *CreateList() + { + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + + JSHandle globalObject = env->GetJSGlobalObject(); + JSHandle key(factory->NewFromASCII("ArkPrivate")); + JSHandle value = + JSObject::GetProperty(thread, JSHandle(globalObject), key).GetValue(); + + auto objCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + objCallInfo->SetFunction(JSTaggedValue::Undefined()); + objCallInfo->SetThis(value.GetTaggedValue()); + objCallInfo->SetCallArg(0, JSTaggedValue(static_cast(containers::ContainerTag::List))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, objCallInfo.get()); + JSTaggedValue result = containers::ContainersPrivate::Load(objCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + + JSHandle constructor(thread, result); + JSHandle list(factory->NewJSObjectByConstructor(JSHandle(constructor), constructor)); + JSTaggedValue singleList = TaggedSingleList::Create(thread); + list->SetSingleList(thread, singleList); + return *list; + } +}; + +HWTEST_F_L0(JSAPIListTest, listCreate) +{ + JSAPIList *list = CreateList(); + EXPECT_TRUE(list != nullptr); +} + +HWTEST_F_L0(JSAPIListTest, AddAndHas) +{ + constexpr int NODE_NUMBERS = 9; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + + JSHandle toor(thread, CreateList()); + + std::string myValue("myvalue"); + for (int i = 0; i < NODE_NUMBERS; i++) { + std::string ivalue = myValue + std::to_string(i); + value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); + JSAPIList::Add(thread, toor, value); + } + EXPECT_EQ(toor->Length(), NODE_NUMBERS); + + for (int i = 0; i < NODE_NUMBERS; i++) { + std::string ivalue = myValue + std::to_string(i); + value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); + + JSTaggedValue gValue = toor->Get(i); + EXPECT_EQ(gValue, value.GetTaggedValue()); + } + JSTaggedValue gValue = toor->Get(10); + EXPECT_EQ(gValue, JSTaggedValue::Undefined()); + + std::string ivalue = myValue + std::to_string(1); + value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); + EXPECT_TRUE(toor->Has(value.GetTaggedValue())); + + toor->Dump(); +} + +HWTEST_F_L0(JSAPIListTest, InsertAndGetLastAndGetFirst) +{ // create jsMap + constexpr uint32_t NODE_NUMBERS = 9; + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + + JSHandle toor(thread, CreateList()); + EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined()); + EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined()); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i + 1)); + JSAPIList::Add(thread, toor, value); + } + EXPECT_EQ(toor->GetLast().GetInt(), 9); + EXPECT_EQ(toor->GetFirst().GetInt(), 1); + + value.Update(JSTaggedValue(99)); + int len = toor->Length(); + toor->Insert(thread, toor, value, len); + EXPECT_EQ(toor->GetLast().GetInt(), 99); + EXPECT_EQ(toor->Length(), 10); + + value.Update(JSTaggedValue(100)); + toor->Insert(thread, toor, value, 0); + EXPECT_EQ(toor->GetFirst().GetInt(), 100); + EXPECT_EQ(toor->Length(), 11); + + toor->Dump(); + + value.Update(JSTaggedValue(101)); + toor->Insert(thread, toor, value, 5); + EXPECT_EQ(toor->Length(), 12); + toor->Dump(); + EXPECT_EQ(toor->Get(5).GetInt(), 101); +} + +HWTEST_F_L0(JSAPIListTest, GetIndexOfAndGetLastIndexOf) +{ // create jsMap + constexpr uint32_t NODE_NUMBERS = 9; + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + + JSHandle toor(thread, CreateList()); + EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined()); + EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined()); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i + 1)); + JSAPIList::Add(thread, toor, value); + } + EXPECT_EQ(toor->GetLast().GetInt(), 9); + EXPECT_EQ(toor->GetFirst().GetInt(), 1); + + value.Update(JSTaggedValue(99)); + int len = toor->Length(); + toor->Insert(thread, toor, value, len); + EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), 9); + EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), 9); + EXPECT_EQ(toor->Length(), 10); + + value.Update(JSTaggedValue(100)); + toor->Insert(thread, toor, value, 0); + EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), 0); + EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), 0); + EXPECT_EQ(toor->Length(), 11); + + value.Update(JSTaggedValue(101)); + toor->Insert(thread, toor, value, 5); + EXPECT_EQ(toor->GetIndexOf(value.GetTaggedValue()).GetInt(), 5); + EXPECT_EQ(toor->GetLastIndexOf(value.GetTaggedValue()).GetInt(), 5); + EXPECT_EQ(toor->Length(), 12); + + toor->Dump(); +} + +HWTEST_F_L0(JSAPIListTest, Remove) +{ // create jsMap + constexpr uint32_t NODE_NUMBERS = 20; + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + + JSHandle toor(thread, CreateList()); + EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined()); + EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined()); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i)); + JSAPIList::Add(thread, toor, value); + } + EXPECT_EQ(toor->Length(), 20); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i)); + JSTaggedValue gValue = toor->Get(i); + EXPECT_EQ(gValue, value.GetTaggedValue()); + } + + value.Update(JSTaggedValue(4)); + EXPECT_EQ(JSAPIList::RemoveByIndex(thread, toor, 4), value.GetTaggedValue()); + EXPECT_EQ(toor->Has(value.GetTaggedValue()), false); + EXPECT_EQ(toor->Length(), 19); + + value.Update(JSTaggedValue(8)); + EXPECT_EQ(toor->Remove(thread, value.GetTaggedValue()), JSTaggedValue::True()); + EXPECT_EQ(toor->Has(value.GetTaggedValue()), false); + EXPECT_EQ(toor->Length(), 18); + + toor->Dump(); +} + +HWTEST_F_L0(JSAPIListTest, Clear) +{ + JSHandle value(thread, JSTaggedValue(1)); + JSHandle list(thread, CreateList()); + list->Add(thread, list, value); + + JSHandle value1(thread, JSTaggedValue(2)); + list->Insert(thread, list, value1, 0); + + list->Clear(thread); + + EXPECT_EQ(list->Length(), 0); + EXPECT_TRUE(list->GetFirst() == JSTaggedValue::Undefined()); +} + +HWTEST_F_L0(JSAPIListTest, Set) +{ + constexpr uint32_t NODE_NUMBERS = 20; + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + + JSHandle toor(thread, CreateList()); + EXPECT_EQ(toor->GetLast(), JSTaggedValue::Undefined()); + EXPECT_EQ(toor->GetFirst(), JSTaggedValue::Undefined()); + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i)); + JSAPIList::Add(thread, toor, value); + } + EXPECT_EQ(toor->Length(), 20); + + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i)); + JSTaggedValue gValue = toor->Get(i); + EXPECT_EQ(gValue, value.GetTaggedValue()); + } + + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i + 1)); + JSAPIList::Set(thread, toor, i, value); + } + + for (uint32_t i = 0; i < NODE_NUMBERS; i++) { + value.Update(JSTaggedValue(i + 1)); + JSTaggedValue gValue = toor->Get(i); + EXPECT_EQ(gValue, value.GetTaggedValue()); + } +} + +HWTEST_F_L0(JSAPIListTest, GetOwnProperty) +{ + constexpr uint32_t DEFAULT_LENGTH = 8; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + JSHandle toor(thread, CreateList()); + + std::string listvalue("listvalue"); + for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) { + std::string ivalue = listvalue + std::to_string(i); + value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); + JSAPIList::Add(thread, toor, value); + } + // test GetOwnProperty + int testInt = 1; + JSHandle listKey1(thread, JSTaggedValue(testInt)); + EXPECT_TRUE(JSAPIList::GetOwnProperty(thread, toor, listKey1)); + testInt = 20; + JSHandle listKey2(thread, JSTaggedValue(testInt)); + EXPECT_FALSE(JSAPIList::GetOwnProperty(thread, toor, listKey2)); +} +} // namespace panda::test diff --git a/ecmascript/tests/js_api_plain_array_test.cpp b/ecmascript/tests/js_api_plain_array_test.cpp index e8b7b73b39..430ad64b66 100644 --- a/ecmascript/tests/js_api_plain_array_test.cpp +++ b/ecmascript/tests/js_api_plain_array_test.cpp @@ -250,4 +250,29 @@ HWTEST_F_L0(JSAPIPlainArrayTest, PA_RemvoeAnrRemvoeAtAndSetValueAtAndGetValueAt) taggedValue = array->GetValueAt(lvalue); EXPECT_TRUE(JSTaggedValue::Equal(thread, value, JSHandle(thread, taggedValue))); } + +HWTEST_F_L0(JSAPIPlainArrayTest, GetOwnProperty) +{ + constexpr uint32_t DEFAULT_LENGTH = 8; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle toor(thread, CreatePlainArray()); + JSMutableHandle key(thread, JSTaggedValue::Undefined()); + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + + std::string plainArrayvalue("plainArrayvalue"); + for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) { + uint32_t ikey = 100 + i; + std::string ivalue = plainArrayvalue + std::to_string(i); + key.Update(JSTaggedValue(ikey)); + value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); + JSAPIPlainArray::Add(thread, toor, key, value); + } + // test GetOwnProperty + int testInt = 100 + 1; + JSHandle plainArrayKey1(thread, JSTaggedValue(testInt)); + EXPECT_TRUE(JSAPIPlainArray::GetOwnProperty(thread, toor, plainArrayKey1)); + testInt = 100 + 20; + JSHandle plainArrayKey2(thread, JSTaggedValue(testInt)); + EXPECT_FALSE(JSAPIPlainArray::GetOwnProperty(thread, toor, plainArrayKey2)); +} } // namespace panda::test diff --git a/ecmascript/tests/js_api_queue_test.cpp b/ecmascript/tests/js_api_queue_test.cpp index ebb4a228a3..bd4ed93b5a 100644 --- a/ecmascript/tests/js_api_queue_test.cpp +++ b/ecmascript/tests/js_api_queue_test.cpp @@ -188,7 +188,6 @@ HWTEST_F_L0(JSAPIQueueTest, GetOwnProperty) ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSMutableHandle value(thread, JSTaggedValue::Undefined()); JSHandle jsQueue = CreateQueue(); - PropertyDescriptor queueDesc(thread); std::string queueValue("queuevalue"); for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) { @@ -199,9 +198,9 @@ HWTEST_F_L0(JSAPIQueueTest, GetOwnProperty) // test GetOwnProperty int testInt = 1; JSHandle queueKey1(thread, JSTaggedValue(testInt)); - EXPECT_TRUE(JSAPIQueue::GetOwnProperty(thread, jsQueue, queueKey1, queueDesc)); + EXPECT_TRUE(JSAPIQueue::GetOwnProperty(thread, jsQueue, queueKey1)); testInt = 9; JSHandle queueKey2(thread, JSTaggedValue(testInt)); - EXPECT_FALSE(JSAPIQueue::GetOwnProperty(thread, jsQueue, queueKey2, queueDesc)); + EXPECT_FALSE(JSAPIQueue::GetOwnProperty(thread, jsQueue, queueKey2)); } } // namespace panda::test \ No newline at end of file diff --git a/ecmascript/tests/js_api_stack_test.cpp b/ecmascript/tests/js_api_stack_test.cpp index e4ab3371f9..b3adb6f441 100644 --- a/ecmascript/tests/js_api_stack_test.cpp +++ b/ecmascript/tests/js_api_stack_test.cpp @@ -191,4 +191,26 @@ HWTEST_F_L0(JSAPIStackTest, Search) toor->Dump(); } + +HWTEST_F_L0(JSAPIStackTest, GetOwnProperty) +{ + constexpr uint32_t DEFAULT_LENGTH = 8; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + JSHandle toor(thread, CreateStack()); + + std::string stackvalue("stackvalue"); + for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) { + std::string ivalue = stackvalue + std::to_string(i); + value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); + JSAPIStack::Push(thread, toor, value); + } + // test GetOwnProperty + int testInt = 1; + JSHandle stackKey1(thread, JSTaggedValue(testInt)); + EXPECT_TRUE(JSAPIStack::GetOwnProperty(thread, toor, stackKey1)); + testInt = 20; + JSHandle stackKey2(thread, JSTaggedValue(testInt)); + EXPECT_FALSE(JSAPIStack::GetOwnProperty(thread, toor, stackKey2)); +} } // namespace panda::test diff --git a/ecmascript/tests/js_api_tree_map_test.cpp b/ecmascript/tests/js_api_tree_map_test.cpp index d829b2eab7..7e869d3271 100644 --- a/ecmascript/tests/js_api_tree_map_test.cpp +++ b/ecmascript/tests/js_api_tree_map_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/tests/js_api_tree_set_test.cpp b/ecmascript/tests/js_api_tree_set_test.cpp index 5daaf572f9..843ee9d5d8 100644 --- a/ecmascript/tests/js_api_tree_set_test.cpp +++ b/ecmascript/tests/js_api_tree_set_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/ecmascript/tests/js_api_vector_test.cpp b/ecmascript/tests/js_api_vector_test.cpp index 544cb8068e..08499bcc5b 100644 --- a/ecmascript/tests/js_api_vector_test.cpp +++ b/ecmascript/tests/js_api_vector_test.cpp @@ -184,4 +184,26 @@ HWTEST_F_L0(JSAPIVectorTest, GetIndexOf) toor->Dump(); } + +HWTEST_F_L0(JSAPIVectorTest, GetOwnProperty) +{ + constexpr uint32_t DEFAULT_LENGTH = 8; + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSMutableHandle value(thread, JSTaggedValue::Undefined()); + JSHandle toor(thread, CreateVector()); + + std::string vectorvalue("vectorvalue"); + for (uint32_t i = 0; i < DEFAULT_LENGTH; i++) { + std::string ivalue = vectorvalue + std::to_string(i); + value.Update(factory->NewFromStdString(ivalue).GetTaggedValue()); + JSAPIVector::Add(thread, toor, value); + } + // test GetOwnProperty + int testInt = 1; + JSHandle vectorKey1(thread, JSTaggedValue(testInt)); + EXPECT_TRUE(JSAPIVector::GetOwnProperty(thread, toor, vectorKey1)); + testInt = 20; + JSHandle vectorKey2(thread, JSTaggedValue(testInt)); + EXPECT_FALSE(JSAPIVector::GetOwnProperty(thread, toor, vectorKey2)); +} } // namespace panda::test diff --git a/ecmascript/tests/tagged_tree_test.cpp b/ecmascript/tests/tagged_tree_test.cpp index e07bf9343a..ae5f7ac065 100644 --- a/ecmascript/tests/tagged_tree_test.cpp +++ b/ecmascript/tests/tagged_tree_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/test/moduletest/container/BUILD.gn b/test/moduletest/container/BUILD.gn index 37f457bdf5..28f40f2ef8 100644 --- a/test/moduletest/container/BUILD.gn +++ b/test/moduletest/container/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# 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 @@ -29,15 +29,27 @@ host_moduletest_action("container_vector") { deps = [] } +host_moduletest_action("container_list") { + deps = [] +} + +host_moduletest_action("container_linked_list") { + deps = [] +} + host_moduletest_action("container") { extra_modules = [ "container_arraylist", + "container_linked_list", + "container_list", "container_treemap", "container_treeset", "container_vector", ] deps = [ ":gen_container_arraylist_abc", + ":gen_container_linked_list_abc", + ":gen_container_list_abc", ":gen_container_treemap_abc", ":gen_container_treeset_abc", ":gen_container_vector_abc", diff --git a/test/moduletest/container/container.js b/test/moduletest/container/container.js index 0de6186f87..219bc97458 100644 --- a/test/moduletest/container/container.js +++ b/test/moduletest/container/container.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/test/moduletest/container/container_arraylist.js b/test/moduletest/container/container_arraylist.js index 76e4197081..a9a18c7ec4 100644 --- a/test/moduletest/container/container_arraylist.js +++ b/test/moduletest/container/container_arraylist.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/test/moduletest/container/container_linked_list.js b/test/moduletest/container/container_linked_list.js new file mode 100644 index 0000000000..21945d0d1a --- /dev/null +++ b/test/moduletest/container/container_linked_list.js @@ -0,0 +1,130 @@ +/* + * 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. + */ + +var LinkedList = undefined; +if (globalThis["ArkPrivate"] != undefined) { + LinkedList = ArkPrivate.Load(ArkPrivate.LinkedList); + let list = new LinkedList(); + let testArray = [] + for(let i = 0; i<10; i++) { + list.add(i) + testArray.push(i) + } + print("test linkedlist has:", list.has(8)) + print("test linkedlist not has:", list.has(2)) + print("test linkedlist getLastIndexOf:", list.getLastIndexOf(1) === 1) + print("test linkedlist getIndexOf:", list.getIndexOf(5) === 5) + + list.removeByIndex(9) + + testArray.splice(9, 1) + let res = true + for(let i = 0; i < testArray.length; i++) { + if (list[i] !== testArray[i]) { + res = false + } + } + print("test linkedlist removeByIndex:", res) + + const removeRes = list.remove(8) + testArray.splice(8, 1) + res = true + for(let i = 0; i < testArray.length; i++) { + if (list[i] !== testArray[i]) { + res = false + } + } + print("test linkedlist remove:", res) + print("test linkedlist remove1:", removeRes) + print("test linkedlist getFirst:", list.getFirst() === 0) + print("test linkedlist getLast:", list.getLast() === 7) + + list.insert(3, 999) + testArray.splice(3, 0, 999) + res = true + for(let i = 0; i < testArray.length; i++) { + if (list[i] !== testArray[i]) { + res = false + } + } + print("test linkedlist insert:", res) + + list.set(5, 888) + testArray[5] = 888 + res = true + for(let i = 0; i < testArray.length; i++) { + if (list[i] !== testArray[i]) { + res = false + } + } + print("test linkedlist set:", res) + + print("test linkedlist clone:", res) + + list.addFirst(1111) + print("test linkedlist addfirst:", list.getFirst() === 1111) + + const removefirstres = list.removeFirst() + print("test linkedlist removeFirst:", removefirstres === 1111) + + res = true + let i = 0 + for (const data of list) { + if (data !== testArray[i]) { + res = false + } + i++; + } + print("test linkedlist intertor:", res) + + let list1 = new LinkedList(); + let testArray1 = [] + for (let i = 0; i < 10; i++) { + list1.add(i) + testArray1.push(i) + } + + res = true + list1.forEach((i, d) => { + if (d !== testArray1[i]) { + res = false + } + }) + + print("test linkedlist forEach:", res) + list1.clear() + print("test linkedlist clear:", list1.length === 0) + print("test linkedlist get:", list.get(1232) === undefined) + print("test linkedlist getLastIndexOf:", list.getLastIndexOf('abc') === -1) + try { + list.removeByIndex(99) + } catch (error) { + print("test linkedlist removeByIndex:", 'There is no such element to delete') + } + + testArray.splice(5, 1) + const resRemove = list.remove(888) + print("test linkedlist remove:", resRemove) + + res = true + const arr = list.convertToArray() + for (let i = 1; i < arr.length; i++) { + if (arr[i] !== testArray[i]) { + res = false + } + } + print("test linkedlist convertToArray:", res) +} + diff --git a/test/moduletest/container/container_list.js b/test/moduletest/container/container_list.js new file mode 100644 index 0000000000..4e678c076c --- /dev/null +++ b/test/moduletest/container/container_list.js @@ -0,0 +1,160 @@ +/* + * 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. + */ + +var List = undefined; +if (globalThis["ArkPrivate"] != undefined) { + List = ArkPrivate.Load(ArkPrivate.List); + let list = new List(); + const testArray = [] + for(let i = 0; i < 10; i++) { + list.add(i) + testArray.push(i) + } + + print("test list get 1:", list.get(1) === 1) + print("test list has:", list.has(8)) + print("test list not has:", list.has(123) === false) + + let list1 = new List(); + const testArray2 = [] + for(let i = 0; i < 10; i++) { + list1.add(i) + testArray2.push(i) + } + + print("test list equal:", list.equal(list1)) + list.add(10) + testArray.push(10) + print("test list equal:", list.equal(list1) === false) + print("test list getLastIndexOf:", list.getLastIndexOf(1) === 1) + print("test list getIndexOf:", list.getIndexOf(5) === 5) + + list.removeByIndex(10) + testArray.splice(10, 1) + let res = true + for(let i = 0; i < testArray.length; i++) { + if (list[i] !== testArray[i]) { + res = false + } + } + print("test list removeByIndex:", res) + + list.remove(9) + testArray.splice(9, 1) + res = true + for(let i = 0; i < testArray.length; i++) { + if (list[i] !== testArray[i]) { + res = false + } + testArray[i] = testArray[i] * 2 + } + print("test list remove:", res) + + list.replaceAllElements((item, index) => { + return item * 2 + }) + res = true + for(let i = 0; i < testArray.length; i++) { + if (list[i] !== testArray[i]) { + res = false + } + } + print("test list replaceAllElements:", res) + print("test list getFirst:", list.getFirst() === 0) + print("test list getLast:", list.getLast() === 16) + list.insert(999, 3) + testArray.splice(3, 0, 999) + res = true + for(let i = 0; i < testArray.length; i++) { + if (list[i] !== testArray[i]) { + res = false + } + } + print("test list insert:", res) + + list.set(5, 888) + testArray[5] = 888 + res = true + for(let i = 0; i < testArray.length; i++) { + if (list[i] !== testArray[i]) { + res = false + } + } + print("test list set:", res) + + let list2 = new List(); + list2.add(4); + list2.add(3); + list2.add(1); + list2.add(2); + list2.add(0); + list2.sort((a,b) => a-b); + res = true + for (let i = 0; i < 5; i++) { + if (list2[i] !== i) { + res = false + } + } + print("test list sort:", res) + + res = true + let subList = list.getSubList(1, 3) + const newtestArray = testArray.slice(1, 3) + for(let i = 0; i < subList.length; i++) { + if (newtestArray[i] !== subList[i]) { + res = false + } + } + print("test list getSubList:", res) + + res = true + const arr = list.convertToArray() + for (let i = 0; i < arr.length; i++) { + if (arr[i] !== testArray[i]) { + res = false + } + } + print("test list convertToArray:", res) + + res = true + let i = 0 + for (const data of list) { + if (data !== testArray[i]) { + res = false + } + i++; + } + print("test list itertor:", res) + + res = true + list1.forEach((i, d) => { + if (d !== testArray2[i]) { + res = false + } + }) + print("test list forEach:", res) + list2.clear() + print("test list clear:", list2.length === 0) + print("test list get:", list1.get(200) === undefined) + print("test list getLastIndexOf:", list1.getLastIndexOf('abc') === -1) + try { + list1.removeByIndex(99) + } catch (error) { + print("test list removeByIndex:", 'There is no such element to delete') + } + res = list1.remove(888) + print("test list remove:", res) +} + diff --git a/test/moduletest/container/container_treemap.js b/test/moduletest/container/container_treemap.js index 77d2e94f23..2e64b2e86c 100644 --- a/test/moduletest/container/container_treemap.js +++ b/test/moduletest/container/container_treemap.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/test/moduletest/container/container_treeset.js b/test/moduletest/container/container_treeset.js index 4dfdd1d380..94123d08b9 100644 --- a/test/moduletest/container/container_treeset.js +++ b/test/moduletest/container/container_treeset.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 diff --git a/test/moduletest/container/expect_output.txt b/test/moduletest/container/expect_output.txt index 16e92e5b10..a7a47b12f3 100644 --- a/test/moduletest/container/expect_output.txt +++ b/test/moduletest/container/expect_output.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2021 Huawei Device Co., Ltd. +# 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 @@ -14,6 +14,52 @@ container test start 1 TypeError: Cannot set property on Container +test linkedlist has: true +test linkedlist not has: true +test linkedlist getLastIndexOf: true +test linkedlist getIndexOf: true +test linkedlist removeByIndex: true +test linkedlist remove: true +test linkedlist remove1: true +test linkedlist getFirst: true +test linkedlist getLast: true +test linkedlist insert: true +test linkedlist set: true +test linkedlist clone: true +test linkedlist addfirst: true +test linkedlist removeFirst: true +test linkedlist intertor: true +test linkedlist forEach: true +test linkedlist clear: true +test linkedlist get: true +test linkedlist getLastIndexOf: true +test linkedlist removeByIndex: There is no such element to delete +test linkedlist remove: true +test linkedlist convertToArray: true +test list get 1: true +test list has: true +test list not has: true +test list equal: true +test list equal: true +test list getLastIndexOf: true +test list getIndexOf: true +test list removeByIndex: true +test list remove: true +test list replaceAllElements: true +test list getFirst: true +test list getLast: true +test list insert: true +test list set: true +test list sort: true +test list getSubList: true +test list convertToArray: true +test list itertor: true +test list forEach: true +test list clear: true +test list get: true +test list getLastIndexOf: true +test list removeByIndex: There is no such element to delete +test list remove: false ### test TreeMap start ### test get, out: true test hasKey and hasValue, out: true From 188bad5338624a3d81debb136d7aad7c9c10a9fc Mon Sep 17 00:00:00 2001 From: hjzhangcm Date: Thu, 2 Jun 2022 15:01:33 +0800 Subject: [PATCH 06/35] Modify compilation script Signed-off-by: hjzhangcm --- test/run_test262.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/run_test262.sh b/test/run_test262.sh index bceb2d350f..cd9c63e099 100644 --- a/test/run_test262.sh +++ b/test/run_test262.sh @@ -23,8 +23,18 @@ pushd ark/ts2abc mkdir report fi - python3 test262/run_test262.py --es2015 all --threads=16 --libs-dir ../../out/hi3516dv300/clang_x64/ark/ark:../../out/hi3516dv300/clang_x64/ark/ark_js_runtime:../../out/hi3516dv300/clang_x64/thirdparty/icu:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib --ark-tool=../../out/hi3516dv300/clang_x64/ark/ark_js_runtime/ark_js_vm --ark-frontend-tool=../../out/hi3516dv300/clang_x64/ark/ark/build/src/index.js - + pushd ../../ + if [ -d out/rk3568 ];then + pushd ark/ts2abc + python3 test262/run_test262.py --es2015 all --threads=16 --libs-dir ../../out/rk3568/clang_x64/ark/ark:../../out/rk3568/clang_x64/ark/ark_js_runtime:../../out/rk3568/clang_x64/thirdparty/icu:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib --ark-tool=../../out/rk/clang_x64/ark/ark_js_runtime/ark_js_vm --ark-frontend-tool=../../out/rk3568/clang_x64/ark/ark/build/src/index.js + popd + fi + if [ -d out/hispark_taurus ];then + pushd ark/ts2abc + python3 test262/run_test262.py --es2015 all --threads=16 --libs-dir ../../out/hispark_taurus/clang_x64/ark/ark:../../out/hispark_taurus/clang_x64/ark/ark_js_runtime:../../out/hispark_taurus/clang_x64/thirdparty/icu:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib --ark-tool=../../out/rk/clang_x64/ark/ark_js_runtime/ark_js_vm --ark-frontend-tool=../../out/hispark_taurus/clang_x64/ark/ark/build/src/index.js + popd + fi + if [ $? -ne 0 ];then echo 'execute run_test262.py failed!' exit 1; From b13fb03d17562deaf3fb732aa2f15aea2cf809c5 Mon Sep 17 00:00:00 2001 From: jiangkai43 Date: Wed, 25 May 2022 22:03:38 +0800 Subject: [PATCH 07/35] Add atomics project and modify code errors Signed-off-by: jiangkai43 https://gitee.com/openharmony/ark_js_runtime/issues/I599WU --- BUILD.gn | 3 + ecmascript/base/atomic_helper.cpp | 140 ++++ ecmascript/base/atomic_helper.h | 104 +++ ecmascript/base/typed_array_helper-inl.h | 36 - ecmascript/base/typed_array_helper.cpp | 4 +- ecmascript/base/typed_array_helper.h | 1 - ecmascript/builtins.cpp | 31 + ecmascript/builtins.h | 2 + ecmascript/builtins/builtins_arraybuffer.cpp | 16 + ecmascript/builtins/builtins_arraybuffer.h | 2 + ecmascript/builtins/builtins_atomics.cpp | 587 ++++++++++++++++ ecmascript/builtins/builtins_atomics.h | 94 +++ ecmascript/builtins/builtins_typedarray.cpp | 8 +- ecmascript/builtins/tests/BUILD.gn | 1 + .../builtins/tests/builtins_atomics_test.cpp | 626 ++++++++++++++++++ ecmascript/dump.cpp | 3 + ecmascript/ecma_vm.h | 19 + ecmascript/global_env.h | 1 + ecmascript/global_env_constants.cpp | 3 + ecmascript/global_env_constants.h | 5 +- ecmascript/js_bigint.cpp | 17 +- ecmascript/js_bigint.h | 2 + ecmascript/js_typed_array.cpp | 36 + ecmascript/js_typed_array.h | 2 + ecmascript/mem/concurrent_marker.cpp | 1 + ecmascript/runtime_call_id.h | 12 + .../snapshot/mem/snapshot_processor.cpp | 13 + ecmascript/waiter_list.cpp | 71 ++ ecmascript/waiter_list.h | 108 +++ 29 files changed, 1903 insertions(+), 45 deletions(-) create mode 100644 ecmascript/base/atomic_helper.cpp create mode 100644 ecmascript/base/atomic_helper.h create mode 100644 ecmascript/builtins/builtins_atomics.cpp create mode 100644 ecmascript/builtins/builtins_atomics.h create mode 100644 ecmascript/builtins/tests/builtins_atomics_test.cpp create mode 100644 ecmascript/waiter_list.cpp create mode 100644 ecmascript/waiter_list.h diff --git a/BUILD.gn b/BUILD.gn index 1986d36df4..9b5c3804e6 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -301,6 +301,7 @@ config("icu_path_test_config") { ecma_source = [ "ecmascript/base/array_helper.cpp", + "ecmascript/base/atomic_helper.cpp", "ecmascript/base/builtins_base.cpp", "ecmascript/base/error_helper.cpp", "ecmascript/base/json_parser.cpp", @@ -314,6 +315,7 @@ ecma_source = [ "ecmascript/builtins/builtins_array.cpp", "ecmascript/builtins/builtins_arraybuffer.cpp", "ecmascript/builtins/builtins_async_function.cpp", + "ecmascript/builtins/builtins_atomics.cpp", "ecmascript/builtins/builtins_bigint.cpp", "ecmascript/builtins/builtins_boolean.cpp", "ecmascript/builtins/builtins_dataview.cpp", @@ -476,6 +478,7 @@ ecma_source = [ "ecmascript/tagged_dictionary.cpp", "ecmascript/tagged_tree.cpp", "ecmascript/template_string.cpp", + "ecmascript/waiter_list.cpp", "ecmascript/weak_vector.cpp", "ecmascript/compiler/llvm/llvm_stackmap_parser.cpp", "ecmascript/stubs/runtime_stubs.cpp", diff --git a/ecmascript/base/atomic_helper.cpp b/ecmascript/base/atomic_helper.cpp new file mode 100644 index 0000000000..d3d790e9f8 --- /dev/null +++ b/ecmascript/base/atomic_helper.cpp @@ -0,0 +1,140 @@ +/* + * 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. + */ + +#include "ecmascript/base/atomic_helper.h" +#include "ecmascript/base/typed_array_helper-inl.h" + +namespace panda::ecmascript::base { +using BuiltinsArrayBuffer = builtins::BuiltinsArrayBuffer; + +JSTaggedValue AtomicHelper::ValidateIntegerTypedArray(JSThread *thread, JSHandle typedArray, + bool waitable) +{ + // 1. If waitable is not present, set waitable to false. + // 2. Let buffer be ? ValidateTypedArray(typedArray). + JSTaggedValue buffer = TypedArrayHelper::ValidateTypedArray(thread, typedArray); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + JSHandle bufferHandle(thread, buffer); + + // 3. Let typeName be typedArray.[[TypedArrayName]]. + // 4. Let type be the Element Type value in Table 60 for typeName. + JSHandle typeName(thread, JSTypedArray::Cast(typedArray->GetTaggedObject())->GetTypedArrayName()); + DataViewType type = JSTypedArray::GetTypeFromName(thread, typeName); + + // 5. If waitable is true, then + // a. If typeName is not "Int32Array" or "BigInt64Array", throw a TypeError exception. + // 6. Else, + // a. If ! IsUnclampedIntegerElementType(type) is false and ! IsBigIntElementType(type) is false, + // throw a TypeError exception. + if (waitable) { + if (!(type == DataViewType::INT32 || type == DataViewType::BIGINT64)) { + THROW_TYPE_ERROR_AND_RETURN(thread, "The typeName is not Int32Array/BigInt64Array.", + JSTaggedValue::Exception()); + } + } else { + if (!(BuiltinsArrayBuffer::IsUnclampedIntegerElementType(type) || + BuiltinsArrayBuffer::IsBigIntElementType(type))) { + THROW_TYPE_ERROR_AND_RETURN(thread, "The typedArray type is not UnclampedInteger/BigInt.", + JSTaggedValue::Exception()); + } + } + // 7. Return buffer. + return bufferHandle.GetTaggedValue(); +} + +int32_t AtomicHelper::ValidateAtomicAccess(JSThread *thread, const JSHandle typedArray, + JSHandle requestIndex) +{ + // 1. Assert: typedArray is an Object that has a [[ViewedArrayBuffer]] internal slot. + ASSERT(typedArray->IsECMAObject() && typedArray->IsTypedArray()); + // 2. Let length be typedArray.[[ArrayLength]]. + JSHandle typedArrayObj(typedArray); + JSHandle srcObj(typedArray); + int32_t length = static_cast(srcObj->GetArrayLength()); + + // 3. Let accessIndex be ? ToIndex(requestIndex). + JSTaggedNumber accessIndex = JSTaggedValue::ToIndex(thread, requestIndex); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, 0); + int32_t index = base::NumberHelper::DoubleInRangeInt32(accessIndex.GetNumber()); + + // 4. Assert: accessIndex ≥ 0. + ASSERT(index >= 0); + + // 5. If accessIndex ≥ length, throw a RangeError exception. + if (index >= length) { + THROW_RANGE_ERROR_AND_RETURN(thread, "Index is overflow.", 0); + } + + // 6. Let arrayTypeName be typedArray.[[TypedArrayName]]. + // 7. Let elementSize be the Element Size value specified in Table 60 for arrayTypeName. + // 8. Let offset be typedArray.[[ByteOffset]]. + JSHandle arrayTypeName(thread, JSTypedArray::Cast(*typedArrayObj)->GetTypedArrayName()); + int32_t elementSize = TypedArrayHelper::GetSizeFromName(thread, arrayTypeName); + uint32_t offset = srcObj->GetByteOffset(); + // 9. Return (accessIndex × elementSize) + offset. + int32_t allOffset = index * elementSize + offset; + return allOffset; +} + +JSTaggedValue AtomicHelper::AtomicStore(JSThread *thread, const JSHandle &typedArray, + JSHandle index, JSHandle &value) +{ + JSTaggedValue bufferValue = ValidateIntegerTypedArray(thread, typedArray); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + JSHandle buffer(thread, bufferValue); + uint32_t indexedPosition = ValidateAtomicAccess(thread, typedArray, index); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + JSHandle arrayTypeName(thread, + JSTypedArray::Cast(typedArray->GetTaggedObject())->GetTypedArrayName()); + DataViewType type = JSTypedArray::GetTypeFromName(thread, arrayTypeName); + JSHandle bufferTag; + if (type == DataViewType::BIGUINT64 || type == DataViewType::BIGINT64) { + JSTaggedValue integerValue = JSTaggedValue::ToBigInt(thread, value); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + bufferTag = JSHandle(thread, integerValue); + } else { + JSTaggedNumber integerValue = JSTaggedValue::ToInteger(thread, value); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + bufferTag = JSHandle(thread, integerValue); + } + if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer.GetTaggedValue())) { + THROW_TYPE_ERROR_AND_RETURN(thread, "The ArrayBuffer of this value is detached buffer.", + JSTaggedValue::Exception()); + } + BuiltinsArrayBuffer::SetValueInBuffer(thread, buffer.GetTaggedValue(), indexedPosition, type, bufferTag, true); + return bufferTag.GetTaggedValue(); +} + +JSTaggedValue AtomicHelper::AtomicLoad(JSThread *thread, const JSHandle &typedArray, + JSHandle index) +{ + JSTaggedValue bufferValue = ValidateIntegerTypedArray(thread, typedArray); + JSHandle buffer(thread, bufferValue); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + int32_t indexedPosition = ValidateAtomicAccess(thread, typedArray, index); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer.GetTaggedValue())) { + THROW_TYPE_ERROR_AND_RETURN(thread, "The ArrayBuffer of this value is detached buffer.", + JSTaggedValue::Exception()); + } + JSHandle arrayTypeName(thread, + JSTypedArray::Cast(typedArray->GetTaggedObject())->GetTypedArrayName()); + DataViewType elementType = JSTypedArray::GetTypeFromName(thread, arrayTypeName); + return BuiltinsArrayBuffer::GetValueFromBuffer(thread, buffer.GetTaggedValue(), + indexedPosition, elementType, true); +} +} // panda::ecmascript::base + diff --git a/ecmascript/base/atomic_helper.h b/ecmascript/base/atomic_helper.h new file mode 100644 index 0000000000..5b17c50b70 --- /dev/null +++ b/ecmascript/base/atomic_helper.h @@ -0,0 +1,104 @@ +/* + * 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. + */ + +#ifndef ECMASCRIPT_BASE_ATOMIC_HELPER_H +#define ECMASCRIPT_BASE_ATOMIC_HELPER_H + +#include "ecmascript/js_dataview.h" + +namespace panda::ecmascript::base { +enum class BytesSize : int32_t {ONEBYTES = 1, TWOBYTES = 2, FOURBYTES = 4, EIGHTBYTES = 8}; + +class AtomicHelper final { +public: + struct SubFun { + template + T operator()(T *ptr, const T *arg) const + { + std::atomic *atomicValue = reinterpret_cast *>(ptr); + return atomicValue->fetch_sub(arg[0], std::memory_order_seq_cst); + } + }; + + struct AddFun { + template + T operator()(T *ptr, const T *arg) const + { + std::atomic *atomicValue = reinterpret_cast *>(ptr); + return atomicValue->fetch_add(arg[0], std::memory_order_seq_cst); + } + }; + + struct AndFun { + template + T operator()(T *ptr, const T *arg) const + { + std::atomic *atomicValue = reinterpret_cast *>(ptr); + return atomicValue->fetch_and(arg[0], std::memory_order_seq_cst); + } + }; + + struct OrFun { + template + T operator()(T *ptr, const T *arg) const + { + std::atomic *atomicValue = reinterpret_cast *>(ptr); + return atomicValue->fetch_or(arg[0], std::memory_order_seq_cst); + } + }; + + struct XorFun { + template + T operator()(T *ptr, const T *arg) const + { + std::atomic *atomicValue = reinterpret_cast *>(ptr); + return atomicValue->fetch_xor(arg[0], std::memory_order_seq_cst); + } + }; + + struct CompareExchangeFun { + template + T operator()(T *ptr, const T *arg) const + { + T a = arg[0]; + std::atomic *atomicValue = reinterpret_cast *>(ptr); + atomicValue->compare_exchange_strong(a, arg[1], std::memory_order_seq_cst); + return a; + } + }; + + struct ExchangeFun { + template + T operator()(T *ptr, const T *arg) const + { + std::atomic *atomicValue = reinterpret_cast *>(ptr); + return atomicValue->exchange(arg[0], std::memory_order_seq_cst); + } + }; + + // 25.4.1.1 ValidateIntegerTypedArray ( typedArray [ , waitable ] ) + static JSTaggedValue ValidateIntegerTypedArray(JSThread *thread, JSHandle typedArray, + bool waitable = false); + // 25.4.2.2 ValidateAtomicAccess ( typedArray, requestIndex ) + static int32_t ValidateAtomicAccess(JSThread *thread, const JSHandle typedArray, + JSHandle requestIndex); + static JSTaggedValue AtomicStore(JSThread *thread, const JSHandle &typedArray, + JSHandle index, JSHandle &value); + static JSTaggedValue AtomicLoad(JSThread *thread, const JSHandle &typedArray, + JSHandle index); +}; +} // namespace panda::ecmascript::base + +#endif // ECMASCRIPT_BASE_ATOMIC_HELPER_H \ No newline at end of file diff --git a/ecmascript/base/typed_array_helper-inl.h b/ecmascript/base/typed_array_helper-inl.h index 388ebe2ecf..efb7a9d74f 100644 --- a/ecmascript/base/typed_array_helper-inl.h +++ b/ecmascript/base/typed_array_helper-inl.h @@ -92,42 +92,6 @@ uint32_t TypedArrayHelper::GetElementSize(JSType type) } } -DataViewType TypedArrayHelper::GetTypeFromName(JSThread *thread, const JSHandle &typeName) -{ - const GlobalEnvConstants *globalConst = thread->GlobalConstants(); - if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledInt8ArrayString())) { - return DataViewType::INT8; - } - if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint8ArrayString())) { - return DataViewType::UINT8; - } - if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint8ClampedArrayString())) { - return DataViewType::UINT8_CLAMPED; - } - if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledInt16ArrayString())) { - return DataViewType::INT16; - } - if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint16ArrayString())) { - return DataViewType::UINT16; - } - if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledInt32ArrayString())) { - return DataViewType::INT32; - } - if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint32ArrayString())) { - return DataViewType::UINT32; - } - if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledFloat32ArrayString())) { - return DataViewType::FLOAT32; - } - if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledFloat64ArrayString())) { - return DataViewType::FLOAT64; - } - if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledBigInt64ArrayString())) { - return DataViewType::BIGINT64; - } - return DataViewType::BIGUINT64; -} - JSHandle TypedArrayHelper::GetConstructor(JSThread *thread, const JSHandle &obj) { JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); diff --git a/ecmascript/base/typed_array_helper.cpp b/ecmascript/base/typed_array_helper.cpp index 9d2a5a8dd4..1745b80509 100644 --- a/ecmascript/base/typed_array_helper.cpp +++ b/ecmascript/base/typed_array_helper.cpp @@ -186,14 +186,14 @@ JSTaggedValue TypedArrayHelper::CreateFromTypedArray(EcmaRuntimeCallInfo *argv, THROW_TYPE_ERROR_AND_RETURN(thread, "The srcData is detached buffer.", JSTaggedValue::Exception()); } // 8. Let elementType be the Element Type value in Table 61 for constructorName. - DataViewType elementType = TypedArrayHelper::GetTypeFromName(thread, constructorName); + DataViewType elementType = JSTypedArray::GetTypeFromName(thread, constructorName); // 9. Let elementLength be srcArray.[[ArrayLength]]. // 10. Let srcName be the String value of srcArray.[[TypedArrayName]]. // 11. Let srcType be the Element Type value in Table 61 for srcName. // 12. Let srcElementSize be the Element Size value specified in Table 61 for srcName. uint32_t elementLength = srcObj->GetArrayLength(); JSHandle srcName(thread, srcObj->GetTypedArrayName()); - DataViewType srcType = TypedArrayHelper::GetTypeFromName(thread, srcName); + DataViewType srcType = JSTypedArray::GetTypeFromName(thread, srcName); uint32_t srcElementSize = TypedArrayHelper::GetSizeFromName(thread, srcName); // 13. Let srcByteOffset be srcArray.[[ByteOffset]]. // 14. Let elementSize be the Element Size value specified in Table 61 for constructorName. diff --git a/ecmascript/base/typed_array_helper.h b/ecmascript/base/typed_array_helper.h index 8f03205432..d4bb38e91f 100644 --- a/ecmascript/base/typed_array_helper.h +++ b/ecmascript/base/typed_array_helper.h @@ -43,7 +43,6 @@ public: inline static DataViewType GetType(JSType type); inline static uint32_t GetElementSize(const JSHandle &obj); inline static uint32_t GetElementSize(JSType type); - inline static DataViewType GetTypeFromName(JSThread *thread, const JSHandle &typeName); inline static JSHandle GetConstructor(JSThread *thread, const JSHandle &obj); inline static JSHandle GetConstructorFromName(JSThread *thread, const JSHandle &typeName); diff --git a/ecmascript/builtins.cpp b/ecmascript/builtins.cpp index 38a0c1dda3..d0a48e8189 100644 --- a/ecmascript/builtins.cpp +++ b/ecmascript/builtins.cpp @@ -30,6 +30,7 @@ #include "ecmascript/builtins/builtins_array.h" #include "ecmascript/builtins/builtins_arraybuffer.h" #include "ecmascript/builtins/builtins_async_function.h" +#include "ecmascript/builtins/builtins_atomics.h" #include "ecmascript/builtins/builtins_bigint.h" #include "ecmascript/builtins/builtins_boolean.h" #include "ecmascript/builtins/builtins_collator.h" @@ -134,6 +135,7 @@ using StringIterator = builtins::BuiltinsStringIterator; using RegExp = builtins::BuiltinsRegExp; using Function = builtins::BuiltinsFunction; using Math = builtins::BuiltinsMath; +using Atomics = builtins::BuiltinsAtomics; using ArrayBuffer = builtins::BuiltinsArrayBuffer; using Json = builtins::BuiltinsJson; using Proxy = builtins::BuiltinsProxy; @@ -314,6 +316,7 @@ void Builtins::Initialize(const JSHandle &env, JSThread *thread) InitializeGlobalObject(env, globalObject); InitializeMath(env, objFuncPrototypeVal); + InitializeAtomics(env, objFuncPrototypeVal); InitializeJson(env, objFuncPrototypeVal); InitializeIterator(env, objFuncDynclass); InitializeProxy(env); @@ -1357,6 +1360,34 @@ void Builtins::InitializeWeakSet(const JSHandle &env, const JSHandle< env->SetBuiltinsWeakSetFunction(thread_, weakSetFunction); } +void Builtins::InitializeAtomics(const JSHandle &env, + const JSHandle &objFuncPrototypeVal) const +{ + [[maybe_unused]] EcmaHandleScope scope(thread_); + JSHandle atomicsDynclass = factory_->NewEcmaDynClass(JSObject::SIZE, JSType::JS_OBJECT, + objFuncPrototypeVal); + JSHandle atomicsObject = factory_->NewJSObject(atomicsDynclass); + SetFunction(env, atomicsObject, "add", Atomics::Add, FunctionLength::THREE); + SetFunction(env, atomicsObject, "and", Atomics::And, FunctionLength::THREE); + SetFunction(env, atomicsObject, "sub", Atomics::Sub, FunctionLength::THREE); + SetFunction(env, atomicsObject, "or", Atomics::Or, FunctionLength::THREE); + SetFunction(env, atomicsObject, "xor", Atomics::Xor, FunctionLength::THREE); + SetFunction(env, atomicsObject, "compareExchange", Atomics::CompareExchange, FunctionLength::FOUR); + SetFunction(env, atomicsObject, "exchange", Atomics::Exchange, FunctionLength::THREE); + SetFunction(env, atomicsObject, "isLockFree", Atomics::IsLockFree, FunctionLength::ONE); + SetFunction(env, atomicsObject, "load", Atomics::Load, FunctionLength::TWO); + SetFunction(env, atomicsObject, "store", Atomics::Store, FunctionLength::THREE); + SetFunction(env, atomicsObject, "wait", Atomics::Wait, FunctionLength::FOUR); + SetFunction(env, atomicsObject, "notify", Atomics::Notify, FunctionLength::THREE); + JSHandle atomicsString(factory_->NewFromASCII("Atomics")); + JSHandle globalObject(thread_, env->GetGlobalObject()); + PropertyDescriptor atomicsDesc(thread_, JSHandle::Cast(atomicsObject), true, false, true); + JSObject::DefineOwnProperty(thread_, globalObject, atomicsString, atomicsDesc); + // @@ToStringTag + SetStringTagSymbol(env, atomicsObject, "Atomics"); + env->SetAtomicsFunction(thread_, atomicsObject); +} + void Builtins::InitializeMath(const JSHandle &env, const JSHandle &objFuncPrototypeVal) const { [[maybe_unused]] EcmaHandleScope scope(thread_); diff --git a/ecmascript/builtins.h b/ecmascript/builtins.h index ed0d5f1e2a..1d8ce4d213 100644 --- a/ecmascript/builtins.h +++ b/ecmascript/builtins.h @@ -141,6 +141,8 @@ private: void InitializeMath(const JSHandle &env, const JSHandle &objFuncPrototypeVal) const; + void InitializeAtomics(const JSHandle &env, const JSHandle &objFuncPrototypeVal) const; + void InitializeJson(const JSHandle &env, const JSHandle &objFuncPrototypeVal) const; void InitializeString(const JSHandle &env, const JSHandle &primRefObjDynclass) const; diff --git a/ecmascript/builtins/builtins_arraybuffer.cpp b/ecmascript/builtins/builtins_arraybuffer.cpp index a7933aaa4f..0519014d02 100644 --- a/ecmascript/builtins/builtins_arraybuffer.cpp +++ b/ecmascript/builtins/builtins_arraybuffer.cpp @@ -386,6 +386,22 @@ bool BuiltinsArrayBuffer::IsBigIntElementType(DataViewType type) return false; } +// es12 25.1.2.6 IsUnclampedIntegerElementType ( type ) +bool BuiltinsArrayBuffer::IsUnclampedIntegerElementType(DataViewType type) +{ + switch (type) { + case DataViewType::INT8: + case DataViewType::INT16: + case DataViewType::INT32: + case DataViewType::UINT8: + case DataViewType::UINT16: + case DataViewType::UINT32: + return true; + default: + return false; + } +} + template void BuiltinsArrayBuffer::SetTypeData(uint8_t *block, T value, uint32_t index) { diff --git a/ecmascript/builtins/builtins_arraybuffer.h b/ecmascript/builtins/builtins_arraybuffer.h index 63498eed36..1c2d2f9464 100644 --- a/ecmascript/builtins/builtins_arraybuffer.h +++ b/ecmascript/builtins/builtins_arraybuffer.h @@ -66,6 +66,8 @@ public: // 24.1.1.1 AllocateArrayBuffer(constructor, byteLength) static JSTaggedValue AllocateArrayBuffer(JSThread *thread, const JSHandle &newTarget, double byteLength); + // es12 25.1.2.6 IsUnclampedIntegerElementType ( type ) + static bool IsUnclampedIntegerElementType(DataViewType type); // es12 25.1.2.7 IsBigIntElementType ( type ) static bool IsBigIntElementType(DataViewType type); diff --git a/ecmascript/builtins/builtins_atomics.cpp b/ecmascript/builtins/builtins_atomics.cpp new file mode 100644 index 0000000000..43e086bca2 --- /dev/null +++ b/ecmascript/builtins/builtins_atomics.cpp @@ -0,0 +1,587 @@ +/* + * 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. + */ + +#include "ecmascript/builtins/builtins_atomics.h" + +#include "ecmascript/base/atomic_helper.h" +#include "ecmascript/base/typed_array_helper-inl.h" +#include "utils/time.h" + +namespace panda::ecmascript::builtins { +using NumberHelper = base::NumberHelper; +using AtomicHelper = base::AtomicHelper; +using BytesSize = base::BytesSize; +using BuiltinsArrayBuffer = builtins::BuiltinsArrayBuffer; + +WaiterList *g_waitLists = Singleton::GetInstance(); +Mutex *g_mutex = Singleton::GetInstance(); + +// 25.4.2 Atomics.add ( typedArray, index, value ) +JSTaggedValue BuiltinsAtomics::Sub(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, Atomics, Sub); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle typedArray = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::SubFun()); +} + +JSTaggedValue BuiltinsAtomics::Add(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, Atomics, Add); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle typedArray = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::AddFun()); +} + +JSTaggedValue BuiltinsAtomics::And(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, Atomics, And); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle typedArray = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::AndFun()); +} + +JSTaggedValue BuiltinsAtomics::Or(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, Atomics, Or); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle typedArray = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::OrFun()); +} + +JSTaggedValue BuiltinsAtomics::Xor(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, Atomics, Xor); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle typedArray = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::XorFun()); +} + +JSTaggedValue BuiltinsAtomics::CompareExchange(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, Atomics, CompareExchange); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle typedArray = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::CompareExchangeFun()); +} + +JSTaggedValue BuiltinsAtomics::Exchange(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, Atomics, Exchange); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle typedArray = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + return AtomicReadModifyWrite(thread, typedArray, index, argv, AtomicHelper::ExchangeFun()); +} + +JSTaggedValue BuiltinsAtomics::Store(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, Atomics, Store); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle typedArray = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + JSHandle value = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); + return AtomicHelper::AtomicStore(thread, typedArray, index, value); +} + +JSTaggedValue BuiltinsAtomics::Load(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, Atomics, Load); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle typedArray = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + return AtomicHelper::AtomicLoad(thread, typedArray, index); +} + +JSTaggedValue BuiltinsAtomics::IsLockFree(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, Atomics, IsLockFree); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + JSHandle sizeTag = GetCallArg(argv, 0); + BytesSize size = BytesSize(JSTaggedValue::ToInt32(thread, sizeTag)); + bool result; + switch (size) { + case BytesSize::ONEBYTES: + case BytesSize::TWOBYTES: + case BytesSize::FOURBYTES: + case BytesSize::EIGHTBYTES: + result = true; + break; + default: + result = false; + break; + } + return JSTaggedValue(result); +} + +// 25.4.11 Atomics.wait ( typedArray, index, value, timeout ) +JSTaggedValue BuiltinsAtomics::Wait(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, Atomic, Wait); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + JSHandle array = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + JSHandle value = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); + JSHandle timeout = GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); + + // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + JSHandle arrayBuffer(thread, AtomicHelper::ValidateIntegerTypedArray(thread, array, true)); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + // 2. If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception. + if (!arrayBuffer->IsSharedArrayBuffer()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "buffer is not sharedArrayBuffer.", + JSTaggedValue::Exception()); + } + + // 3. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index). + int32_t indexedPosition = AtomicHelper::ValidateAtomicAccess(thread, array, index); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + // 4. If typedArray.[[TypedArrayName]] is "BigInt64Array", let v be ? ToBigInt64(value). + // 5. Otherwise, let v be ? ToInt32(value). + int64_t v = 0; + if (array->IsJSBigInt64Array()) { + v = JSHandle::Cast(value)->ToInt64(); + } else { + v = static_cast(JSTaggedValue::ToInt32(thread, value)); + } + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + // 6. Let q be ? ToNumber(timeout). + // 7. If q is NaN or +∞𝔽, let t be +∞; else if q is -∞𝔽, let t be 0; else let t be max(ℝ(q), 0). + double t = 0; + if (timeout->IsUndefined()) { + t = base::POSITIVE_INFINITY; + } else { + JSTaggedNumber q = JSTaggedValue::ToNumber(thread, timeout); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + t = q.GetNumber(); + if (NumberHelper::IsNaN(q) || (!NumberHelper::IsFinite(q) && t > 0)) { + t = base::POSITIVE_INFINITY; + } else if (t < 0) { + t = 0; + } + } + + // 8. Let B be AgentCanSuspend(). + // 9. If B is false, throw a TypeError exception. + if (!thread->GetEcmaVM()->GetAllowAtomicWait()) { + THROW_TYPE_ERROR_AND_RETURN(thread, "vm does not allow wait to block.", + JSTaggedValue::Exception()); + } + WaitResult res = WaitResult::OK; + if (array->IsJSBigInt64Array()) { + // AtomicHelper::Wait(thread, arrayBuffer, indexedPosition, v, t); + res = DoWait(thread, arrayBuffer, indexedPosition, v, t); + } else { + // AtomicHelper::Wait(thread, arrayBuffer, indexedPosition, static_cast(v), t); + res = DoWait(thread, arrayBuffer, indexedPosition, static_cast(v), t); + } + const GlobalEnvConstants *globalConst = thread->GlobalConstants(); + if (res == WaitResult::OK) { + return globalConst->GetOkString(); + } else if (res == WaitResult::NOT_EQ) { + return globalConst->GetNotEqualString(); + } + return globalConst->GetTimeoutString(); +} + +// 25.4.12 Atomics.notify ( typedArray, index, count ) +JSTaggedValue BuiltinsAtomics::Notify(EcmaRuntimeCallInfo *argv) +{ + ASSERT(argv); + JSThread *thread = argv->GetThread(); + BUILTINS_API_TRACE(thread, Atomic, Notify); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + + JSHandle array = GetCallArg(argv, 0); + JSHandle index = GetCallArg(argv, 1); + JSHandle count = GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); + + // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray, true). + JSHandle arrayBuffer(thread, AtomicHelper::ValidateIntegerTypedArray(thread, array, true)); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + // 2. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index). + int32_t indexedPosition = AtomicHelper::ValidateAtomicAccess(thread, array, index); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + // 3. If count is undefined, let c be +∞. + // 4. Else, + // a. Let intCount be ? ToIntegerOrInfinity(count). + // b. Let c be max(intCount, 0). + double c = 0; + if (count->IsUndefined()) { + c = base::POSITIVE_INFINITY; + } else { + JSTaggedNumber countTemp = JSTaggedValue::ToNumber(thread, count); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + c = base::NumberHelper::TruncateDouble(countTemp.GetNumber()); + c = c < 0 ? 0 : c; + } + // 6. If IsSharedArrayBuffer(buffer) is false, return +0𝔽. + if (!arrayBuffer->IsSharedArrayBuffer()) { + return JSTaggedValue(0); + } + return JSTaggedValue(Signal(arrayBuffer, indexedPosition, c)); +} + +template +JSTaggedValue BuiltinsAtomics::AtomicReadModifyWrite(JSThread *thread, const JSHandle &typedArray, + JSHandle &index, EcmaRuntimeCallInfo *argv, + const callbackfun &op) +{ + if (!typedArray->IsTypedArray()) { + THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception()); + } + // 1. Let buffer be ? ValidateIntegerTypedArray(typedArray). + JSTaggedValue bufferValue = base::AtomicHelper::ValidateIntegerTypedArray(thread, typedArray); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + JSHandle buffer(thread, bufferValue); + // 2. Let indexedPosition be ? ValidateAtomicAccess(typedArray, index). + int32_t indexedPosition = base::AtomicHelper::ValidateAtomicAccess(thread, typedArray, index); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + // 3. Let arrayTypeName be typedArray.[[TypedArrayName]]. + JSHandle arrayTypeName(thread, + JSTypedArray::Cast(typedArray->GetTaggedObject())->GetTypedArrayName()); + if (BuiltinsArrayBuffer::IsDetachedBuffer(buffer.GetTaggedValue())) { + THROW_TYPE_ERROR_AND_RETURN(thread, "The ArrayBuffer of this value is detached buffer.", + JSTaggedValue::Exception()); + } + // 7. NOTE: The above check is not redundant with the check in ValidateIntegerTypedArray because the call to + // ToBigInt or ToIntegerOrInfinity on the preceding lines can have arbitrary side effects, which could cause the + // buffer to become detached. + // 8. Let elementType be the Element Type value in Table 60 for arrayTypeName. + DataViewType elementType = JSTypedArray::GetTypeFromName(thread, arrayTypeName); + // 9. Return GetModifySetValueInBuffer(buffer, indexedPosition, elementType, v, op). + return AtomicReadModifyWriteCase(thread, buffer.GetTaggedValue(), elementType, indexedPosition, argv, op); +} + +template +JSTaggedValue BuiltinsAtomics::AtomicReadModifyWriteCase(JSThread *thread, JSTaggedValue arrBuf, + DataViewType type, int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op) +{ + JSArrayBuffer *jsArrayBuffer = JSArrayBuffer::Cast(arrBuf.GetTaggedObject()); + JSTaggedValue data = jsArrayBuffer->GetArrayBufferData(); + void *pointer = JSNativePointer::Cast(data.GetTaggedObject())->GetExternalPointer(); + auto *block = reinterpret_cast(pointer); + uint32_t size = argv->GetArgsNumber(); + switch (type) { + case DataViewType::UINT8: + return HandleWithUint8(thread, size, block, indexedPosition, argv, op); + case DataViewType::INT8: + return HandleWithInt8(thread, size, block, indexedPosition, argv, op); + case DataViewType::UINT16: + return HandleWithUint16(thread, size, block, indexedPosition, argv, op); + case DataViewType::INT16: + return HandleWithInt16(thread, size, block, indexedPosition, argv, op); + case DataViewType::UINT32: + return HandleWithUint32(thread, size, block, indexedPosition, argv, op); + case DataViewType::INT32: + return HandleWithInt32(thread, size, block, indexedPosition, argv, op); + case DataViewType::BIGINT64: + return HandleWithBigInt64(thread, size, block, indexedPosition, argv, op); + case DataViewType::BIGUINT64: + return HandleWithBigUint64(thread, size, block, indexedPosition, argv, op); + default: + break; + } + UNREACHABLE(); +} + +template +JSTaggedValue BuiltinsAtomics::HandleWithUint8(JSThread *thread, uint32_t size, uint8_t *block, + int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op) +{ + JSHandle value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); + uint8_t tag = JSTaggedValue::ToUint8(thread, value); + if (size == 3) { // the number of parameters is 3 + auto result = op((block + indexedPosition), &tag); + return BuiltinsBase::GetTaggedInt(result); + } + JSHandle newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); + uint8_t newTag = JSTaggedValue::ToUint8(thread, newValue); + uint8_t arg[ARGS_NUMBER] = {0}; + arg[0] = tag; + arg[1] = newTag; + auto result = op((block + indexedPosition), arg); + return JSTaggedValue(result); +} + +template +JSTaggedValue BuiltinsAtomics::HandleWithInt8(JSThread *thread, uint32_t size, uint8_t *block, + int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op) +{ + JSHandle value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); + int8_t tag = JSTaggedValue::ToInt8(thread, value); + if (size == 3) { // the number of parameters is 3 + auto result = op(reinterpret_cast(block + indexedPosition), &tag); + return BuiltinsBase::GetTaggedInt(result); + } + JSHandle newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); + int8_t newTag = JSTaggedValue::ToInt8(thread, newValue); + int8_t arg[ARGS_NUMBER] = {0}; + arg[0] = tag; + arg[1] = newTag; + auto result = op(reinterpret_cast(block + indexedPosition), arg); + return JSTaggedValue(result); +} + +template +JSTaggedValue BuiltinsAtomics::HandleWithUint16(JSThread *thread, uint32_t size, uint8_t *block, + int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op) +{ + JSHandle value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); + uint16_t tag = JSTaggedValue::ToUint16(thread, value); + if (size == 3) { // the number of parameters is 3 + auto result = op(reinterpret_cast(block + indexedPosition), &tag); + return BuiltinsBase::GetTaggedInt(result); + } + JSHandle newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); + uint16_t newTag = JSTaggedValue::ToUint16(thread, newValue); + uint16_t arg[ARGS_NUMBER] = {0}; + arg[0] = tag; + arg[1] = newTag; + auto result = op(reinterpret_cast(block + indexedPosition), arg); + return JSTaggedValue(result); +} + +template +JSTaggedValue BuiltinsAtomics::HandleWithInt16(JSThread *thread, uint32_t size, uint8_t *block, + int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op) +{ + JSHandle value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); + int16_t tag = JSTaggedValue::ToInt16(thread, value); + if (size == 3) { // the number of parameters is 3 + auto result = op(reinterpret_cast(block + indexedPosition), &tag); + return BuiltinsBase::GetTaggedInt(result); + } + JSHandle newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); + int16_t newTag = JSTaggedValue::ToInt16(thread, newValue); + int16_t arg[ARGS_NUMBER] = {0}; + arg[0] = tag; + arg[1] = newTag; + auto result = op(reinterpret_cast(block + indexedPosition), arg); + return JSTaggedValue(result); +} + +template +JSTaggedValue BuiltinsAtomics::HandleWithUint32(JSThread *thread, uint32_t size, uint8_t *block, + int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op) +{ + JSHandle value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); + uint32_t tag = JSTaggedValue::ToUint32(thread, value); + if (size == 3) { // the number of parameters is 3 + auto result = op(reinterpret_cast(block + indexedPosition), &tag); + return JSTaggedValue(result); + } + JSHandle newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); + uint32_t newTag = JSTaggedValue::ToUint32(thread, newValue); + uint32_t arg[ARGS_NUMBER] = {0}; + arg[0] = tag; + arg[1] = newTag; + auto result = op(reinterpret_cast(block + indexedPosition), arg); + return JSTaggedValue(result); +} + +template +JSTaggedValue BuiltinsAtomics::HandleWithInt32(JSThread *thread, uint32_t size, uint8_t *block, + int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op) +{ + JSHandle value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); + int32_t tag = JSTaggedValue::ToInt32(thread, value); + if (size == 3) { // the number of parameters is 3 + auto result = op(reinterpret_cast(block + indexedPosition), &tag); + return BuiltinsBase::GetTaggedInt(result); + } + JSHandle newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); + int32_t newTag = JSTaggedValue::ToInt32(thread, newValue); + int32_t arg[ARGS_NUMBER] = {0}; + arg[0] = tag; + arg[1] = newTag; + auto result = op(reinterpret_cast(block + indexedPosition), arg); + return JSTaggedValue(result); +} + +template +JSTaggedValue BuiltinsAtomics::HandleWithBigInt64(JSThread *thread, uint32_t size, uint8_t *block, + int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op) +{ + JSHandle value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); + int64_t val = 0; + bool lossless = true; + BigInt::BigIntToInt64(thread, value, &val, &lossless); + if (size == 3) { // the number of parameters is 3 + auto result = op(reinterpret_cast(block + indexedPosition), &val); + return BigInt::Int64ToBigInt(thread, result).GetTaggedValue(); + } + JSHandle newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); + int64_t newVal = 0; + BigInt::BigIntToInt64(thread, newValue, &newVal, &lossless); + int64_t arg[ARGS_NUMBER] = {0}; + arg[0] = val; + arg[1] = newVal; + auto result = op(reinterpret_cast(block + indexedPosition), arg); + return BigInt::Int64ToBigInt(thread, result).GetTaggedValue(); +} + +template +JSTaggedValue BuiltinsAtomics::HandleWithBigUint64(JSThread *thread, uint32_t size, uint8_t *block, + int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op) +{ + JSHandle value = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::THIRD); + uint64_t val = 0; + bool lossless = true; + BigInt::BigIntToUint64(thread, value, &val, &lossless); + if (size == 3) { // the number of parameters is 3 + auto result = op(reinterpret_cast(block + indexedPosition), &val); + return BigInt::Uint64ToBigInt(thread, result).GetTaggedValue(); + } + JSHandle newValue = BuiltinsBase::GetCallArg(argv, BuiltinsBase::ArgsPosition::FOURTH); + uint64_t newVal = 0; + BigInt::BigIntToUint64(thread, newValue, &newVal, &lossless); + uint64_t arg[ARGS_NUMBER] = {0}; + arg[0] = val; + arg[1] = newVal; + auto result = op(reinterpret_cast(block + indexedPosition), arg); + return BigInt::Uint64ToBigInt(thread, result).GetTaggedValue(); +} + +template +WaitResult BuiltinsAtomics::DoWait(JSThread *thread, JSHandle &arrayBuffer, + size_t index, T execpt, double timeout) +{ + MutexGuard lock_guard(g_mutex); + JSHandle np(thread, JSHandle::Cast(arrayBuffer)->GetArrayBufferData()); + void *buffer = np->GetExternalPointer(); + ASSERT(buffer != nullptr); + WaiterListNode *node = thread->GetEcmaVM()->GetWaiterListNode(); + node->date_ = buffer; + node->index_ = index; + node->waitPointer_ = reinterpret_cast(buffer) + index; + node->waiting_ = true; + std::atomic *atomicValue = reinterpret_cast *>(node->waitPointer_); + T value = atomicValue->load(); + if (value != execpt) { + return WaitResult::NOT_EQ; + } + g_waitLists->AddNode(node); + uint64_t currentTime = 0; + uint64_t timeoutTime = 0; + bool hasTimeout = timeout != base::POSITIVE_INFINITY; + if (hasTimeout) { + currentTime = time::GetCurrentTimeInMillis(); + timeoutTime = currentTime + static_cast(timeout); + } + WaitResult res = WaitResult::OK; + while (true) { + if (!node->waiting_) { + res = WaitResult::OK; + break; + } + if (hasTimeout) { + currentTime = time::GetCurrentTimeInMillis(); + if (currentTime >= timeoutTime) { + res = WaitResult::TIME_OUT; + break; + } + uint64_t untilTime = timeoutTime - currentTime; + ASSERT(untilTime != 0); + + node->cond_.TimedWait(g_mutex, untilTime); + } else { + node->cond_.Wait(g_mutex); + } + } + g_waitLists->DeleteNode(node); + node->waiting_ = false; + return res; +} + +uint32_t BuiltinsAtomics::Signal(JSHandle &arrayBuffer, const size_t &index, double wakeCount) +{ + JSTaggedValue data = JSHandle::Cast(arrayBuffer)->GetArrayBufferData(); + void *buffer = JSNativePointer::Cast(data.GetTaggedObject())->GetExternalPointer(); + ASSERT(buffer != nullptr); + MutexGuard lock_guard(g_mutex); + auto &locationListMap = g_waitLists->locationListMap_; + auto iter = locationListMap.find(reinterpret_cast(buffer) + index); + if (iter == locationListMap.end()) { + return 0; + } + WaiterListNode *node = iter->second.pHead; + uint32_t wokenUpCount = 0; + while (node != nullptr && wakeCount > 0.0) { + if (!node->waiting_) { + node = node->next_; + continue; + } + if (buffer == node->date_) { + ASSERT(index == node->index_); + node->waiting_ = false; + + WaiterListNode *oldNode = node; + node = node->next_; + oldNode->cond_.Signal(); + if (wakeCount != base::POSITIVE_INFINITY) { + wakeCount--; + } + wokenUpCount++; + continue; + } + node = node->next_; + } + return wokenUpCount; +} +} // namespace panda::ecmascript::builtins diff --git a/ecmascript/builtins/builtins_atomics.h b/ecmascript/builtins/builtins_atomics.h new file mode 100644 index 0000000000..b10f64799c --- /dev/null +++ b/ecmascript/builtins/builtins_atomics.h @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#ifndef ECMASCRIPT_BUILTINS_BUILTINS_ATOMICS_H +#define ECMASCRIPT_BUILTINS_BUILTINS_ATOMICS_H + +#include "ecmascript/base/builtins_base.h" +#include "ecmascript/js_dataview.h" +#include "ecmascript/waiter_list.h" + +namespace panda::ecmascript::builtins { +enum class WaitResult: uint8_t {OK = 0, NOT_EQ, TIME_OUT}; + +class BuiltinsAtomics : public base::BuiltinsBase { +public: + // 25.4.2 Atomics.add ( typedArray, index, value ) + static JSTaggedValue Add(EcmaRuntimeCallInfo *argv); + // 25.4.3 Atomics.and ( typedArray, index, value ) + static JSTaggedValue And(EcmaRuntimeCallInfo *argv); + // 25.4.4 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue) + static JSTaggedValue CompareExchange(EcmaRuntimeCallInfo *argv); + // 25.4.5 Atomics.exchange ( typedArray, index, value ) + static JSTaggedValue Exchange(EcmaRuntimeCallInfo *argv); + // 25.4.6 Atomics.isLockFree ( size ) + static JSTaggedValue IsLockFree(EcmaRuntimeCallInfo *argv); + // 25.4.7 Atomics.load ( typedArray, index ) + static JSTaggedValue Load(EcmaRuntimeCallInfo *argv); + // 25.4.8 Atomics.or ( typedArray, index, value ) + static JSTaggedValue Or(EcmaRuntimeCallInfo *argv); + // 25.4.9 Atomics.store ( typedArray, index, value ) + static JSTaggedValue Store(EcmaRuntimeCallInfo *argv); + // 25.4.10 Atomics.sub ( typedArray, index, value ) + static JSTaggedValue Sub(EcmaRuntimeCallInfo *argv); + // 25.4.11 Atomics.wait ( typedArray, index, value, timeout) + static JSTaggedValue Wait(EcmaRuntimeCallInfo *argv); + // 25.4.12 Atomics.notify ( typedArray, index, count) + static JSTaggedValue Notify(EcmaRuntimeCallInfo *argv); + // 25.4.13 Atomics.xor ( typedArray, index, value ) + static JSTaggedValue Xor(EcmaRuntimeCallInfo *argv); + +private: + static uint32_t Signal(JSHandle &arrayBuffer, const size_t &index, double wakeCount); + template + static WaitResult DoWait(JSThread *thread, JSHandle &arrayBuffer, + size_t index, T execpt, double timeout); + template + static JSTaggedValue AtomicReadModifyWrite(JSThread *thread, const JSHandle &typedArray, + JSHandle &index, EcmaRuntimeCallInfo *argv, + const callbackfun &op); + template + static JSTaggedValue AtomicReadModifyWriteCase(JSThread *thread, JSTaggedValue buffer, DataViewType type, + int32_t indexedPosition, EcmaRuntimeCallInfo *argv, + const callbackfun &op); + template + static JSTaggedValue HandleWithUint8(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op); + template + static JSTaggedValue HandleWithInt8(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op); + template + static JSTaggedValue HandleWithUint16(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op); + template + static JSTaggedValue HandleWithInt16(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op); + template + static JSTaggedValue HandleWithUint32(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op); + template + static JSTaggedValue HandleWithInt32(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op); + template + static JSTaggedValue HandleWithBigInt64(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op); + template + static JSTaggedValue HandleWithBigUint64(JSThread *thread, uint32_t size, uint8_t *block, int32_t indexedPosition, + EcmaRuntimeCallInfo *argv, const callbackfun &op); + + static constexpr int ARGS_NUMBER = 2; +}; +} // namespace panda::ecmascript::builtins +#endif // ECMASCRIPT_BUILTINS_BUILTINS_MATH_H \ No newline at end of file diff --git a/ecmascript/builtins/builtins_typedarray.cpp b/ecmascript/builtins/builtins_typedarray.cpp index 8fa4021b80..3674011d45 100644 --- a/ecmascript/builtins/builtins_typedarray.cpp +++ b/ecmascript/builtins/builtins_typedarray.cpp @@ -992,7 +992,7 @@ JSTaggedValue BuiltinsTypedArray::Set(EcmaRuntimeCallInfo *argv) uint32_t targetLength = targetObj->GetArrayLength(); JSHandle targetName(thread, targetObj->GetTypedArrayName()); uint32_t targetElementSize = TypedArrayHelper::GetSizeFromName(thread, targetName); - DataViewType targetType = TypedArrayHelper::GetTypeFromName(thread, targetName); + DataViewType targetType = JSTypedArray::GetTypeFromName(thread, targetName); uint32_t targetByteOffset = targetObj->GetByteOffset(); JSHandle argArray = GetCallArg(argv, 0); @@ -1084,7 +1084,7 @@ JSTaggedValue BuiltinsTypedArray::Set(EcmaRuntimeCallInfo *argv) // 21. Let srcLength be the value of typedArray’s [[ArrayLength]] internal slot. // 22. Let srcByteOffset be the value of typedArray’s [[ByteOffset]] internal slot. JSHandle srcName(thread, typedArray->GetTypedArrayName()); - DataViewType srcType = TypedArrayHelper::GetTypeFromName(thread, srcName); + DataViewType srcType = JSTypedArray::GetTypeFromName(thread, srcName); uint32_t srcElementSize = TypedArrayHelper::GetSizeFromName(thread, srcName); uint32_t srcLength = typedArray->GetArrayLength(); uint32_t srcByteOffset = typedArray->GetByteOffset(); @@ -1214,11 +1214,11 @@ JSTaggedValue BuiltinsTypedArray::Slice(EcmaRuntimeCallInfo *argv) // 17. Let srcName be the String value of O’s [[TypedArrayName]] internal slot. // 18. Let srcType be the String value of the Element Type value in Table 49 for srcName. JSHandle srcName(thread, thisObj->GetTypedArrayName()); - DataViewType srcType = TypedArrayHelper::GetTypeFromName(thread, srcName); + DataViewType srcType = JSTypedArray::GetTypeFromName(thread, srcName); // 19. Let targetName be the String value of A’s [[TypedArrayName]] internal slot. // 20. Let targetType be the String value of the Element Type value in Table 49 for targetName. JSHandle targetName(thread, JSTypedArray::Cast(*newArrObj)->GetTypedArrayName()); - DataViewType targetType = TypedArrayHelper::GetTypeFromName(thread, targetName); + DataViewType targetType = JSTypedArray::GetTypeFromName(thread, targetName); // 21. If SameValue(srcType, targetType) is false, then // a. Let n be 0. // b. Repeat, while k < final diff --git a/ecmascript/builtins/tests/BUILD.gn b/ecmascript/builtins/tests/BUILD.gn index 68d4563706..da76a36fc4 100755 --- a/ecmascript/builtins/tests/BUILD.gn +++ b/ecmascript/builtins/tests/BUILD.gn @@ -52,6 +52,7 @@ host_unittest_action("BuiltinsNaturalTest") { # test file "builtins_array_test.cpp", "builtins_arraybuffer_test.cpp", + "builtins_atomics_test.cpp", "builtins_boolean_test.cpp", "builtins_dataview_test.cpp", "builtins_date_test.cpp", diff --git a/ecmascript/builtins/tests/builtins_atomics_test.cpp b/ecmascript/builtins/tests/builtins_atomics_test.cpp new file mode 100644 index 0000000000..b4f7a86784 --- /dev/null +++ b/ecmascript/builtins/tests/builtins_atomics_test.cpp @@ -0,0 +1,626 @@ +/* + * 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. + */ + +#include "ecmascript/builtins/builtins_array.h" +#include "ecmascript/builtins/builtins_atomics.h" +#include "ecmascript/builtins/builtins_typedarray.h" +#include "ecmascript/ecma_vm.h" +#include "ecmascript/global_env.h" +#include "ecmascript/js_array.h" +#include "ecmascript/js_handle.h" +#include "ecmascript/js_thread.h" +#include "ecmascript/js_typed_array.h" +#include "ecmascript/tests/test_helper.h" + +using namespace panda::ecmascript; +using namespace panda::ecmascript::builtins; + +namespace panda::test { +using TypedArray = ecmascript::builtins::BuiltinsTypedArray; +class BuiltinsAtomicsTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + TestHelper::CreateEcmaVMWithScope(instance, thread, scope); + } + + void TearDown() override + { + TestHelper::DestroyEcmaVMWithScope(instance, scope); + } + + EcmaVM *instance {nullptr}; + EcmaHandleScope *scope {nullptr}; + JSThread *thread {nullptr}; +}; + +JSTypedArray *CreateTypedArray(JSThread *thread, const JSHandle &array) +{ + auto ecmaVM = thread->GetEcmaVM(); + JSHandle env = ecmaVM->GetGlobalEnv(); + + JSHandle jsarray(JSArray::CreateArrayFromList(thread, array)); + JSHandle int8_array(env->GetInt8ArrayFunction()); + JSHandle globalObject(thread, env->GetGlobalObject()); + // 6 : test case + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*int8_array), 6); + ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue(*int8_array)); + ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject)); + ecmaRuntimeCallInfo1->SetCallArg(0, jsarray.GetTaggedValue()); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1.get()); + JSTaggedValue result = TypedArray::Int8ArrayConstructor(ecmaRuntimeCallInfo1.get()); + + EXPECT_TRUE(result.IsECMAObject()); + JSTypedArray *int8arr = JSTypedArray::Cast(reinterpret_cast(result.GetRawData())); + return int8arr; +} + +HWTEST_F_L0(BuiltinsAtomicsTest, Add_1) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + array->Set(thread, 0, JSTaggedValue(7)); + array->Set(thread, 1, JSTaggedValue(8)); + array->Set(thread, 2, JSTaggedValue(9)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(5))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Add(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 7); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, Add_2) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(10)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Add(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 0); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, Add_3) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Add(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 0); + + + auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast(0))); + + prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get()); + JSTaggedValue results = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(results.GetInt(), 2); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, And_1) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(10)); + array->Set(thread, 0, JSTaggedValue(7)); + array->Set(thread, 1, JSTaggedValue(0)); + array->Set(thread, 2, JSTaggedValue(0)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Add(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 7); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, And_2) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(10)); + array->Set(thread, 0, JSTaggedValue(7)); + array->Set(thread, 1, JSTaggedValue(0)); + array->Set(thread, 2, JSTaggedValue(0)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::And(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 7); + + + auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast(0))); + + prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get()); + result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 2); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, CompareExchange_1) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + array->Set(thread, 0, JSTaggedValue(5)); + array->Set(thread, 1, JSTaggedValue(0)); + array->Set(thread, 2, JSTaggedValue(0)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 12); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(5))); + ecmaRuntimeCallInfo->SetCallArg(3, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::CompareExchange(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 5); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, CompareExchange_2) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + array->Set(thread, 0, JSTaggedValue(5)); + array->Set(thread, 1, JSTaggedValue(0)); + array->Set(thread, 2, JSTaggedValue(0)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 12); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(5))); + ecmaRuntimeCallInfo->SetCallArg(3, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::CompareExchange(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 5); + + + auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast(0))); + + prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get()); + result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 2); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, Exchange_1) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + array->Set(thread, 0, JSTaggedValue(3)); + array->Set(thread, 1, JSTaggedValue(0)); + array->Set(thread, 2, JSTaggedValue(0)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(6))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Exchange(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 3); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, Exchange_2) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + array->Set(thread, 0, JSTaggedValue(3)); + array->Set(thread, 1, JSTaggedValue(0)); + array->Set(thread, 2, JSTaggedValue(0)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(6))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Exchange(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 3); + + + auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast(0))); + + prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get()); + result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 6); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, Or_1) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + array->Set(thread, 0, JSTaggedValue(5)); + array->Set(thread, 1, JSTaggedValue(0)); + array->Set(thread, 2, JSTaggedValue(0)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Or(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 5); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, Or_2) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + array->Set(thread, 0, JSTaggedValue(5)); + array->Set(thread, 1, JSTaggedValue(0)); + array->Set(thread, 2, JSTaggedValue(0)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 12); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Or(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 5); + + + auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast(0))); + + prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get()); + result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 7); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, Sub_1) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + array->Set(thread, 0, JSTaggedValue(5)); + array->Set(thread, 1, JSTaggedValue(0)); + array->Set(thread, 2, JSTaggedValue(0)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Sub(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 5); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, Sub_2) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + array->Set(thread, 0, JSTaggedValue(0)); + array->Set(thread, 1, JSTaggedValue(5)); + array->Set(thread, 2, JSTaggedValue(0)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(1))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Sub(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 5); + + auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast(1))); + + prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get()); + result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 3); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, Xor_1) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + array->Set(thread, 0, JSTaggedValue(5)); + array->Set(thread, 1, JSTaggedValue(7)); + array->Set(thread, 2, JSTaggedValue(0)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(1))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Xor(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 7); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, Xor_2) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + array->Set(thread, 0, JSTaggedValue(5)); + array->Set(thread, 1, JSTaggedValue(7)); + array->Set(thread, 2, JSTaggedValue(0)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(1))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Xor(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 7); + + auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast(1))); + + prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get()); + result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 5); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_1) +{ + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(1))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_TRUE(result.ToBoolean()); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_2) +{ + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_TRUE(result.ToBoolean()); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_3) +{ + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(4))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_TRUE(result.ToBoolean()); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_4) +{ + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(-3))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_FALSE(result.ToBoolean()); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, IsLockFree_5) +{ + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, JSTaggedValue(static_cast(8))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::IsLockFree(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_TRUE(result.ToBoolean()); +} + + +HWTEST_F_L0(BuiltinsAtomicsTest, Store_1) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + array->Set(thread, 0, JSTaggedValue(5)); + array->Set(thread, 1, JSTaggedValue(6)); + array->Set(thread, 2, JSTaggedValue(7)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Store(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetDouble(), 2); +} + +HWTEST_F_L0(BuiltinsAtomicsTest, Store_2) +{ + ASSERT_NE(thread, nullptr); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + [[maybe_unused]] JSHandle array(factory->NewTaggedArray(3)); + array->Set(thread, 0, JSTaggedValue(5)); + array->Set(thread, 1, JSTaggedValue(6)); + array->Set(thread, 2, JSTaggedValue(7)); + + JSHandle obj = JSHandle(thread, CreateTypedArray(thread, array)); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(static_cast(0))); + ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast(2))); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + JSTaggedValue result = BuiltinsAtomics::Store(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetDouble(), 2); + + auto ecmaRuntimeCallInfos = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); + ecmaRuntimeCallInfos->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetThis(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfos->SetCallArg(0, obj.GetTaggedValue()); + ecmaRuntimeCallInfos->SetCallArg(1, JSTaggedValue(static_cast(0))); + + prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfos.get()); + result = BuiltinsAtomics::Load(ecmaRuntimeCallInfos.get()); + TestHelper::TearDownFrame(thread, prev); + ASSERT_EQ(result.GetInt(), 2); +} +} \ No newline at end of file diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index 026e5f0206..757292dd13 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -1711,6 +1711,8 @@ void GlobalEnv::Dump(std::ostream &os) const GetBuiltinsWeakMapFunction().GetTaggedValue().Dump(os); os << " - MathFunction: "; GetMathFunction().GetTaggedValue().Dump(os); + os << " - AtomicsFunction: "; + GetAtomicsFunction().GetTaggedValue().Dump(os); os << " - JsonFunction: "; GetJsonFunction().GetTaggedValue().Dump(os); os << " - StringFunction: "; @@ -3589,6 +3591,7 @@ void GlobalEnv::DumpForSnapshot(std::vector> & vec.push_back(std::make_pair(CString("BuiltinsWeakSetFunction"), GetBuiltinsWeakSetFunction().GetTaggedValue())); vec.push_back(std::make_pair(CString("BuiltinsWeakMapFunction"), GetBuiltinsWeakMapFunction().GetTaggedValue())); vec.push_back(std::make_pair(CString("MathFunction"), GetMathFunction().GetTaggedValue())); + vec.push_back(std::make_pair(CString("AtomicsFunction"), GetAtomicsFunction().GetTaggedValue())); vec.push_back(std::make_pair(CString("JsonFunction"), GetJsonFunction().GetTaggedValue())); vec.push_back(std::make_pair(CString("StringFunction"), GetStringFunction().GetTaggedValue())); vec.push_back(std::make_pair(CString("ProxyFunction"), GetProxyFunction().GetTaggedValue())); diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index 4f9821eceb..5ff6d3d616 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -24,6 +24,7 @@ #include "ecmascript/mem/chunk_containers.h" #include "ecmascript/taskpool/taskpool.h" #include "ecmascript/js_thread.h" +#include "ecmascript/waiter_list.h" namespace panda { class JSNApi; @@ -273,6 +274,21 @@ public: hostPromiseRejectionTracker_ = cb; } + void SetAllowAtomicWait(bool wait) + { + AllowAtomicWait_ = wait; + } + + bool GetAllowAtomicWait() const + { + return AllowAtomicWait_; + } + + WaiterListNode *GetWaiterListNode() + { + return &waiterListNode_; + } + void PromiseRejectionTracker(const JSHandle &promise, const JSHandle &reason, PromiseRejectionEvent operation) { @@ -374,6 +390,9 @@ private: void* data_ {nullptr}; bool isProcessingPendingJob_ = false; + // atomics + bool AllowAtomicWait_ {true}; + WaiterListNode waiterListNode_; friend class Snapshot; friend class SnapshotProcessor; diff --git a/ecmascript/global_env.h b/ecmascript/global_env.h index ea92188cd0..43705f20d2 100644 --- a/ecmascript/global_env.h +++ b/ecmascript/global_env.h @@ -81,6 +81,7 @@ class JSThread; V(JSTaggedValue, BuiltinsWeakSetFunction, BUILTINS_WEAK_SET_FUNCTION_INDEX) \ V(JSTaggedValue, MapPrototype, MAP_PROTOTYPE_INDEX) \ V(JSTaggedValue, MathFunction, MATH_FUNCTION_INDEX) \ + V(JSTaggedValue, AtomicsFunction, ATOMICS_FUNCTION_INDEX) \ V(JSTaggedValue, JsonFunction, JSON_FUNCTION_INDEX) \ V(JSTaggedValue, StringFunction, STRING_FUNCTION_INDEX) \ V(JSTaggedValue, ProxyFunction, PROXY_FUNCTION_INDEX) \ diff --git a/ecmascript/global_env_constants.cpp b/ecmascript/global_env_constants.cpp index 4c6b087a4f..60aa589277 100644 --- a/ecmascript/global_env_constants.cpp +++ b/ecmascript/global_env_constants.cpp @@ -474,6 +474,9 @@ void GlobalEnvConstants::InitGlobalConstant(JSThread *thread) SetConstant(ConstantIndex::ELEMENT_INDEX, factory->NewFromASCII("element")); SetConstant(ConstantIndex::FLAGS_INDEX, factory->NewFromASCII("flags")); SetConstant(ConstantIndex::G_INDEX, factory->NewFromASCII("g")); + SetConstant(ConstantIndex::NOT_EQUAL_INDEX, factory->NewFromASCII("not-equal")); + SetConstant(ConstantIndex::OK_INDEX, factory->NewFromASCII("ok")); + SetConstant(ConstantIndex::TIMEOUT_INDEX, factory->NewFromASCII("timed-out")); auto accessor = factory->NewInternalAccessor(reinterpret_cast(JSFunction::PrototypeSetter), reinterpret_cast(JSFunction::PrototypeGetter)); diff --git a/ecmascript/global_env_constants.h b/ecmascript/global_env_constants.h index 862fdf065c..476061936a 100644 --- a/ecmascript/global_env_constants.h +++ b/ecmascript/global_env_constants.h @@ -342,7 +342,10 @@ class JSThread; V(JSTaggedValue, DisjunctionString, DISJUNCTION_INDEX, disjunction) \ V(JSTaggedValue, ElementString, ELEMENT_INDEX, element) \ V(JSTaggedValue, FlagsString, FLAGS_INDEX, flags) \ - V(JSTaggedValue, GString, G_INDEX, g) + V(JSTaggedValue, GString, G_INDEX, g) \ + V(JSTaggedValue, NotEqualString, NOT_EQUAL_INDEX, notEqual) \ + V(JSTaggedValue, OkString, OK_INDEX, ok) \ + V(JSTaggedValue, TimeoutString, TIMEOUT_INDEX, timedout) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define GLOBAL_ENV_CONSTANT_ACCESSOR(V) \ diff --git a/ecmascript/js_bigint.cpp b/ecmascript/js_bigint.cpp index a4d36bb669..6399688a98 100644 --- a/ecmascript/js_bigint.cpp +++ b/ecmascript/js_bigint.cpp @@ -954,7 +954,7 @@ std::string BigIntHelper::MultiplyImpl(std::string &a, std::string &b) str[i + j + 1] = static_cast(temp2 % 10 + 48); // 2 and 10 and 48 is number addflag = temp2 / 10; } - str[i] += static_cast(mulflag + addflag); + str[i] += static_cast(mulflag + addflag); } if (str[0] == '0') { str = str.substr(1, str.size()); @@ -1429,4 +1429,19 @@ ComparisonResult BigInt::CompareWithNumber(JSHandle bigint, JSHandle(&value); + for (int index = len - 1; index >= 0; --index) { + *(addr + index) = GetDigit(index); + } + if (GetSign()) { + value = ~(value - 1); + } + return static_cast(value); +} } // namespace diff --git a/ecmascript/js_bigint.h b/ecmascript/js_bigint.h index d40a301370..edcf8b26cb 100644 --- a/ecmascript/js_bigint.h +++ b/ecmascript/js_bigint.h @@ -89,6 +89,8 @@ public: static JSTaggedValue AsintN(JSThread *thread, JSTaggedNumber &bits, JSHandle bigint); static JSTaggedNumber BigIntToNumber(JSHandle bigint); static ComparisonResult CompareWithNumber(JSHandle bigint, JSHandle number); + + int64_t ToInt64(); inline bool IsZero() { return GetLength() == 1 && !GetDigit(0); diff --git a/ecmascript/js_typed_array.cpp b/ecmascript/js_typed_array.cpp index c73d6ce48e..714660cd0d 100644 --- a/ecmascript/js_typed_array.cpp +++ b/ecmascript/js_typed_array.cpp @@ -406,6 +406,42 @@ bool JSTypedArray::IsValidIntegerIndex(const JSHandle &typedArray return true; } +DataViewType JSTypedArray::GetTypeFromName(JSThread *thread, const JSHandle &typeName) +{ + const GlobalEnvConstants *globalConst = thread->GlobalConstants(); + if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledInt8ArrayString())) { + return DataViewType::INT8; + } + if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint8ArrayString())) { + return DataViewType::UINT8; + } + if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint8ClampedArrayString())) { + return DataViewType::UINT8_CLAMPED; + } + if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledInt16ArrayString())) { + return DataViewType::INT16; + } + if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint16ArrayString())) { + return DataViewType::UINT16; + } + if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledInt32ArrayString())) { + return DataViewType::INT32; + } + if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledUint32ArrayString())) { + return DataViewType::UINT32; + } + if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledFloat32ArrayString())) { + return DataViewType::FLOAT32; + } + if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledFloat64ArrayString())) { + return DataViewType::FLOAT64; + } + if (JSTaggedValue::SameValue(typeName, globalConst->GetHandledBigInt64ArrayString())) { + return DataViewType::BIGINT64; + } + return DataViewType::BIGUINT64; +} + // static bool JSTypedArray::FastCopyElementToArray(JSThread *thread, const JSHandle &typedArray, JSHandle &array) diff --git a/ecmascript/js_typed_array.h b/ecmascript/js_typed_array.h index e4c6319818..b422d096ef 100644 --- a/ecmascript/js_typed_array.h +++ b/ecmascript/js_typed_array.h @@ -17,6 +17,7 @@ #define ECMASCRIPT_JS_TYPED_ARRAY_H #include "ecmascript/tagged_array.h" +#include "ecmascript/js_dataview.h" #include "js_object.h" namespace panda::ecmascript { @@ -94,6 +95,7 @@ public: // only use in TypeArray fast set property static JSTaggedNumber NonEcmaObjectToNumber(JSThread *thread, const JSTaggedValue tagged); static constexpr size_t VIEWED_ARRAY_BUFFER_OFFSET = JSObject::SIZE; + static DataViewType GetTypeFromName(JSThread *thread, const JSHandle &typeName); ACCESSORS(ViewedArrayBuffer, VIEWED_ARRAY_BUFFER_OFFSET, TYPED_ARRAY_NAME_OFFSET) ACCESSORS(TypedArrayName, TYPED_ARRAY_NAME_OFFSET, BYTE_LENGTH_OFFSET) ACCESSORS_PRIMITIVE_FIELD(ByteLength, uint32_t, BYTE_LENGTH_OFFSET, BYTE_OFFSET_OFFSET) diff --git a/ecmascript/mem/concurrent_marker.cpp b/ecmascript/mem/concurrent_marker.cpp index dec51b3f86..6311d39702 100644 --- a/ecmascript/mem/concurrent_marker.cpp +++ b/ecmascript/mem/concurrent_marker.cpp @@ -104,6 +104,7 @@ void ConcurrentMarker::Reset(bool revertCSet) auto callback = [](Region *region) { region->ClearMarkGCBitset(); region->ClearCrossRegionRSet(); + region->ResetAliveObject(); }; if (heap_->IsFullMark()) { heap_->EnumerateRegions(callback); diff --git a/ecmascript/runtime_call_id.h b/ecmascript/runtime_call_id.h index 2c5ff96eb3..5cc29a54b1 100644 --- a/ecmascript/runtime_call_id.h +++ b/ecmascript/runtime_call_id.h @@ -371,6 +371,18 @@ namespace panda::ecmascript { V(Math, Tan) \ V(Math, Tanh) \ V(Math, Trunc) \ + V(Atomics, Add) \ + V(Atomics, And) \ + V(Atomics, Or) \ + V(Atomics, Xor) \ + V(Atomics, Sub) \ + V(Atomics, Exchange) \ + V(Atomics, CompareEchange) \ + V(Atomics, Store) \ + V(Atomics, Load) \ + V(Atomics, IsLockFree) \ + V(Atomics, Wait) \ + V(Atomics, Notify) \ V(Number, Constructor) \ V(Number, IsFinite) \ V(Number, IsInteger) \ diff --git a/ecmascript/snapshot/mem/snapshot_processor.cpp b/ecmascript/snapshot/mem/snapshot_processor.cpp index 72e7d0eecb..96d4d92032 100644 --- a/ecmascript/snapshot/mem/snapshot_processor.cpp +++ b/ecmascript/snapshot/mem/snapshot_processor.cpp @@ -19,6 +19,7 @@ #include "ecmascript/builtins/builtins_array.h" #include "ecmascript/builtins/builtins_arraybuffer.h" #include "ecmascript/builtins/builtins_async_function.h" +#include "ecmascript/builtins/builtins_atomics.h" #include "ecmascript/builtins/builtins_bigint.h" #include "ecmascript/builtins/builtins_boolean.h" #include "ecmascript/builtins/builtins_collator.h" @@ -116,6 +117,7 @@ using StringIterator = builtins::BuiltinsStringIterator; using RegExp = builtins::BuiltinsRegExp; using Function = builtins::BuiltinsFunction; using Math = builtins::BuiltinsMath; +using Atomics = builtins::BuiltinsAtomics; using ArrayBuffer = builtins::BuiltinsArrayBuffer; using Json = builtins::BuiltinsJson; using Proxy = builtins::BuiltinsProxy; @@ -504,6 +506,17 @@ static uintptr_t g_nativeTable[] = { reinterpret_cast(Math::Tan), reinterpret_cast(Math::Tanh), reinterpret_cast(Math::Trunc), + reinterpret_cast(Atomics::Wait), + reinterpret_cast(Atomics::Exchange), + reinterpret_cast(Atomics::CompareExchange), + reinterpret_cast(Atomics::Store), + reinterpret_cast(Atomics::Load), + reinterpret_cast(Atomics::Notify), + reinterpret_cast(Atomics::Xor), + reinterpret_cast(Atomics::Or), + reinterpret_cast(Atomics::Sub), + reinterpret_cast(Atomics::And), + reinterpret_cast(Atomics::Add), reinterpret_cast(Json::Parse), reinterpret_cast(Json::Stringify), reinterpret_cast(BuiltinsIterator::Next), diff --git a/ecmascript/waiter_list.cpp b/ecmascript/waiter_list.cpp new file mode 100644 index 0000000000..1dd110b01b --- /dev/null +++ b/ecmascript/waiter_list.cpp @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#include "ecmascript/waiter_list.h" +#include "ecmascript/base/number_helper.h" +#include "os/time.h" + +namespace panda::ecmascript { +// --------------------------WaiterList------------------------------ +void WaiterList::AddNode(WaiterListNode *node) +{ + ASSERT(node->prev_ == nullptr); + ASSERT(node->next_ == nullptr); + auto iter = locationListMap_.find(node->waitPointer_); + if (iter != locationListMap_.end()) { + iter->second.pTail->next_ = node; + node->prev_ = iter->second.pTail; + iter->second.pTail = node; + } else { + locationListMap_.insert(std::make_pair(node->waitPointer_, HeadAndTail {node, node})); + } +} + +void WaiterList::DeleteNode(WaiterListNode *node) +{ + auto iter = locationListMap_.find(node->waitPointer_); + ASSERT(iter != locationListMap_.end()); + WaiterListNode *temp = iter->second.pHead; + bool flag = false; + while (temp != nullptr) { + if (temp == node) { + flag = true; + break; + } + temp = temp->next_; + } + ASSERT(flag); + if (node == iter->second.pHead && node == iter->second.pTail) { + locationListMap_.erase(iter); + return; + } + + if (node == iter->second.pHead) { + iter->second.pHead = node->next_; + } else { + ASSERT(node->prev_); + node->prev_->next_ = node->next_; + } + + if (node == iter->second.pTail) { + iter->second.pTail = node->prev_; + } else { + ASSERT(node->next_); + node->next_->prev_ = node->prev_; + } + + node->prev_ = node->next_ = nullptr; +} +} // namespace \ No newline at end of file diff --git a/ecmascript/waiter_list.h b/ecmascript/waiter_list.h new file mode 100644 index 0000000000..9b0abbf0e7 --- /dev/null +++ b/ecmascript/waiter_list.h @@ -0,0 +1,108 @@ +/* + * 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. + */ + +#ifndef ECMASCRIPT_WAITER_LIST_H +#define ECMASCRIPT_WAITER_LIST_H + +#include "ecmascript/ecma_macros.h" +#include "ecmascript/mem/c_containers.h" +#include "os/mutex.h" + +namespace panda::ecmascript { +using Mutex = os::memory::Mutex; +using LockHolder = os::memory::LockHolder; + +class WaiterListNode { +public: + WaiterListNode() = default; + ~WaiterListNode() = default; + +public: + NO_COPY_SEMANTIC(WaiterListNode); + NO_MOVE_SEMANTIC(WaiterListNode); + + WaiterListNode *prev_ {nullptr}; + WaiterListNode *next_ {nullptr}; + // Used to call wait or Signal() to unlock wait and wake up + os::memory::ConditionVariable cond_; + + // Managed Arraybuffer or SharedArrayBuffer memory data + void *date_ {nullptr}; + + // the offset of the element in the typedArray + size_t index_ {0}; + + // the memory address data corresponding to the offset + int8_t *waitPointer_ {nullptr}; + + // used to determine whether to wait, start wait when waiting_ is true + bool waiting_ {false}; + +private: + friend class WaiterList; +}; + +// WaiterList to manage WaiterListNode +class WaiterList { +public: + WaiterList() = default; + void AddNode(WaiterListNode *node); + void DeleteNode(WaiterListNode *node); + struct HeadAndTail { + WaiterListNode *pHead {nullptr}; + WaiterListNode *pTail {nullptr}; + }; + + // locationListMap_ is used AddNode or DeleteNode + // When calling addnode If there is no corresponding memory data, add the node corresponding to the key + CMap locationListMap_; +}; + +// The Singleton pattern is used to creat a global metux and WaiterList +template +class Singleton { +public: + ~Singleton() {} + NO_COPY_SEMANTIC(Singleton); + NO_MOVE_SEMANTIC(Singleton); + static T *GetInstance() + { + static T instance; + return &instance; + } + +private: + Singleton() = default; +}; + +class SCOPED_CAPABILITY MutexGuard +{ +public: + explicit MutexGuard(Mutex *mutex) : mutex_(mutex), lockHolder_(*mutex) {} + void Unlock() RELEASE() + { + mutex_->Unlock(); + } + void Lock() ACQUIRE() + { + mutex_->Lock(); + } + +public: + Mutex *mutex_; + LockHolder lockHolder_; +}; +} // namespace +#endif // ECMASCRIPT_WAITER_LIST_H \ No newline at end of file From 3d0305c4a773260c278d20d0b4b901e65a301187 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Thu, 2 Jun 2022 14:35:14 +0800 Subject: [PATCH 08/35] Implement Prologue refactor and Add mulitple Optimized Frame In LLVM 12.0.1 1 refactor prologue reserve dynamic slots which is setted by LLVM IR 2 callsiteSp is calculated by current function's callee saved registers size 3 and Add mulitple Optimized Frame: OPTIMIZED_JS_FUNCTION_FRAME:argv[n-1],..., argv[0], argc, ...., returnaddr, Fp, type. this frame need to visit args and stackmap. OPTIMIZED_ASM_FRAME: jscall/jsentry construct frame which is implemented by assemble, this frame is only link to previou frame, it don't need to visit args and stackmap 4 stackmap support parse const pool and llvm patch add deopt interface LLVMBuildCall3 issue: https://gitee.com/openharmony/ark_js_runtime/issues/I5AJ9U Signed-off-by: songzhengchao Change-Id: Ie6a0067169805cc6043ea94936dd578489b56c7b --- ecmascript/compiler/BUILD.gn | 9 +- ecmascript/compiler/compile_llvm_lib.sh | 6 +- ecmascript/compiler/file_generators.cpp | 14 +- ecmascript/compiler/file_generators.h | 55 +- ecmascript/compiler/llvm/llvm_new.patch | 1037 ----------------- .../compiler/llvm/llvm_stackmap_parser.cpp | 92 +- .../compiler/llvm/llvm_stackmap_parser.h | 39 +- ecmascript/compiler/llvm_codegen.cpp | 22 +- ecmascript/compiler/llvm_codegen.h | 3 +- ecmascript/compiler/llvm_ir_builder.cpp | 63 +- ecmascript/compiler/llvm_ir_builder.h | 16 +- ecmascript/compiler/tests/BUILD.gn | 8 +- ecmascript/compiler/tests/stub_tests.cpp | 18 +- .../trampoline/aarch64/assembler_stubs.cpp | 61 +- .../trampoline/x64/assembler_stubs_x64.cpp | 10 +- ecmascript/file_loader.cpp | 23 + ecmascript/file_loader.h | 7 +- ecmascript/frames.h | 137 ++- ecmascript/interpreter/frame_handler.cpp | 107 +- ecmascript/interpreter/frame_handler.h | 20 +- .../interpreter/interpreter_assembly.cpp | 12 +- ecmascript/js_thread.h | 1 - ecmascript/stubs/runtime_stubs-inl.h | 1 + test/aottest/BUILD.gn | 3 +- 24 files changed, 490 insertions(+), 1274 deletions(-) delete mode 100644 ecmascript/compiler/llvm/llvm_new.patch diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index f6bc4c8b2f..b2fc7ce53b 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -28,8 +28,8 @@ if (defined(ark_independent_build)) { config("include_llvm") { if (compile_llvm_online) { include_dirs = [ - "//third_party/llvm-project/build/include", - "//third_party/llvm-project/llvm/include/", + "//third_party/third_party_llvm-project/build/include", + "//third_party/third_party_llvm-project/llvm/include/", ] } else { include_dirs = [ @@ -78,7 +78,7 @@ source_set("libark_jsoptimizer_set") { ] if (compile_llvm_online) { - lib_dirs = [ "//third_party/llvm-project/build/lib" ] + lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] } else { lib_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/build/lib" ] @@ -137,12 +137,13 @@ source_set("libark_jsoptimizer_set") { "LLVMAArch64Desc", "LLVMAArch64Disassembler", "LLVMAArch64AsmParser", - "LLVMX86Utils", "LLVMX86AsmParser", "LLVMX86CodeGen", "LLVMX86Desc", "LLVMX86Disassembler", "LLVMX86Info", + "LLVMFrontendOpenMP", + "LLVMBitWriter", ] deps = [ diff --git a/ecmascript/compiler/compile_llvm_lib.sh b/ecmascript/compiler/compile_llvm_lib.sh index 852ae9093c..78646dd6f4 100755 --- a/ecmascript/compiler/compile_llvm_lib.sh +++ b/ecmascript/compiler/compile_llvm_lib.sh @@ -28,14 +28,12 @@ echo ${BASE_HOME} if [ ! -d "${BASE_HOME}/third_party/llvm-project" ]; then cd ${BASE_HOME}/third_party dd if=/dev/zero of=/tmp/mem.swap bs=1M count=4096 - git clone https://gitee.com/surpassgoodchao/llvm-project.git + git clone git@gitee.com:openharmony-sig/third_party_llvm-project.git -b llvmorg-12.0.1-ark + git checkout 12.0.1-ark-1.0 fi cd ${BASE_HOME}/third_party/llvm-project if [ ! -d "build" ];then - git checkout -b local llvmorg-10.0.1 - cp ../../ark/js_runtime/ecmascript/compiler/llvm/llvm_new.patch . - git apply --reject llvm_new.patch mkdir build && cd build cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DBUILD_ARK_GC_SUPPORT=ON -DLLVM_ENABLE_TERMINFO=OFF DLLVM_STATIC_LINK_CXX_STDLIB=OFF -DLLVM_ENABLE_ZLIB=OFF ../llvm ninja diff --git a/ecmascript/compiler/file_generators.cpp b/ecmascript/compiler/file_generators.cpp index 71af836c95..f26e2129ec 100644 --- a/ecmascript/compiler/file_generators.cpp +++ b/ecmascript/compiler/file_generators.cpp @@ -23,14 +23,22 @@ void StubFileGenerator::CollectAsmStubCodeInfo(std::map { uintptr_t codeBegin = asmModule_.GetCodeBufferOffset(); auto asmCallSigns = asmModule_.GetCSigns(); + uint32_t funSize = 0; for (size_t i = 0; i < asmModule_.GetFunctionCount(); i++) { auto cs = asmCallSigns[i]; auto entryOffset = asmModule_.GetFunction(cs->GetID()); - stubInfo_.AddStubEntry(cs->GetTargetKind(), cs->GetID(), entryOffset + codeBegin, 0); + if (i < asmModule_.GetFunctionCount() - 1) { + auto nextcs = asmCallSigns[i + 1]; + funSize = asmModule_.GetFunction(nextcs->GetID()) - entryOffset; + } else { + funSize = asmModule_.GetBufferSize() - entryOffset; + } + stubInfo_.AddStubEntry(cs->GetTargetKind(), cs->GetID(), entryOffset + codeBegin, 0, 0, funSize); ASSERT(!cs->GetName().empty()); auto codeBuffer = modulePackage_[0].GetCodeBuffer(); uintptr_t entry = codeBuffer + entryOffset + codeBegin; addr2name[entry] = cs->GetName(); + DisassembleEachFunc(addr2name); } } @@ -38,7 +46,7 @@ void StubFileGenerator::CollectCodeInfo() { std::map addr2name; for (size_t i = 0; i < modulePackage_.size(); i++) { - modulePackage_[i].CollectFuncEntryInfo(addr2name, stubInfo_, i); + modulePackage_[i].CollectFuncEntryInfo(addr2name, stubInfo_, i, GetLog()); if (i == 0) { CollectAsmStubCodeInfo(addr2name); } @@ -52,7 +60,7 @@ void AOTFileGenerator::CollectCodeInfo() { std::map addr2name; for (size_t i = 0; i < modulePackage_.size(); i++) { - modulePackage_[i].CollectFuncEntryInfo(addr2name, aotInfo_, i); + modulePackage_[i].CollectFuncEntryInfo(addr2name, aotInfo_, i, GetLog()); auto des = modulePackage_[i].GetModuleSectionDes(); aotInfo_.AddModuleDes(des, aotfileHashs_[i]); } diff --git a/ecmascript/compiler/file_generators.h b/ecmascript/compiler/file_generators.h index 552000c720..55c8ecadc3 100644 --- a/ecmascript/compiler/file_generators.h +++ b/ecmascript/compiler/file_generators.h @@ -15,6 +15,7 @@ #ifndef ECMASCRIPT_COMPILER_FILE_GENERATORS_H #define ECMASCRIPT_COMPILER_FILE_GENERATORS_H +#include #include "ecmascript/compiler/assembler_module.h" #include "ecmascript/compiler/compiler_log.h" #include "ecmascript/compiler/llvm_codegen.h" @@ -32,35 +33,71 @@ public: } void CollectFuncEntryInfo(std::map &addr2name, StubModulePackInfo &stubInfo, - uint32_t moduleIndex) + uint32_t moduleIndex, const CompilerLog &log) { auto codeBuff = assembler_->GetCodeBuffer(); auto engine = assembler_->GetEngine(); auto callSigns = llvmModule_->GetCSigns(); + std::map addr2FpToPrevFrameSpDelta; + std::vector funSizeVec; + std::vector entrys; for (size_t j = 0; j < llvmModule_->GetFuncCount(); j++) { - auto cs = callSigns[j]; LLVMValueRef func = llvmModule_->GetFunction(j); ASSERT(func != nullptr); uintptr_t entry = reinterpret_cast(LLVMGetPointerToGlobal(engine, func)); - stubInfo.AddStubEntry(cs->GetTargetKind(), cs->GetID(), entry - codeBuff, moduleIndex); - ASSERT(!cs->GetName().empty()); - addr2name[entry] = cs->GetName(); + entrys.push_back(entry); } + const size_t funcCount = llvmModule_->GetFuncCount(); + for (size_t j = 0; j < funcCount; j++) { + auto cs = callSigns[j]; + LLVMValueRef func = llvmModule_->GetFunction(j); + ASSERT(func != nullptr); + int delta = assembler_->GetFpDeltaPrevFramSp(func, log); + ASSERT(delta >= 0 && (delta % sizeof(uintptr_t) == 0)); + uint32_t funcSize = 0; + if (j < funcCount - 1) { + funcSize = entrys[j + 1] - entrys[j]; + } else { + funcSize = codeBuff + assembler_->GetCodeSize() - entrys[j]; + } + stubInfo.AddStubEntry(cs->GetTargetKind(), cs->GetID(), entrys[j] - codeBuff, moduleIndex, delta, funcSize); + ASSERT(!cs->GetName().empty()); + addr2name[entrys[j]] = cs->GetName(); + } + // GetCodeSize } void CollectFuncEntryInfo(std::map &addr2name, AOTModulePackInfo &aotInfo, - uint32_t moduleIndex) + uint32_t moduleIndex, const CompilerLog &log) { auto codeBuff = assembler_->GetCodeBuffer(); auto engine = assembler_->GetEngine(); + std::vector> funcInfo; // entry、idx、delta llvmModule_->IteratefuncIndexMap([&](size_t idx, LLVMValueRef func) { uint64_t funcEntry = reinterpret_cast(LLVMGetPointerToGlobal(engine, func)); uint64_t length = 0; std::string funcName(LLVMGetValueName2(func, &length)); assert(length != 0); COMPILER_LOG(INFO) << "CollectCodeInfo for AOT func: " << funcName.c_str(); - aotInfo.AddStubEntry(CallSignature::TargetKind::JSFUNCTION, idx, funcEntry - codeBuff, moduleIndex); addr2name[funcEntry] = funcName; + int delta = assembler_->GetFpDeltaPrevFramSp(func, log); + ASSERT(delta >= 0 && (delta % sizeof(uintptr_t) == 0)); + funcInfo.emplace_back(std::tuple(funcEntry, idx, delta)); }); + const size_t funcCount = funcInfo.size(); + for (size_t i = 0; i < funcInfo.size(); i++) { + uint64_t funcEntry; + size_t idx; + int delta; + uint32_t funcSize; + std::tie(funcEntry, idx, delta) = funcInfo[i]; + if (i < funcCount - 1) { + funcSize = std::get<0>(funcInfo[i + 1]) - funcEntry; + } else { + funcSize = codeBuff + assembler_->GetCodeSize() - funcEntry; + } + aotInfo.AddStubEntry(CallSignature::TargetKind::JSFUNCTION, idx, + funcEntry - codeBuff, moduleIndex, delta, funcSize); + } } ModuleSectionDes GetModuleSectionDes() @@ -126,9 +163,9 @@ public: explicit FileGenerator(const CompilerLog *log) : log_(log) {}; virtual ~FileGenerator() = default; - const CompilerLog *GetLog() const + const CompilerLog GetLog() const { - return log_; + return *log_; } protected: std::vector modulePackage_ {}; diff --git a/ecmascript/compiler/llvm/llvm_new.patch b/ecmascript/compiler/llvm/llvm_new.patch deleted file mode 100644 index 3a419a1b06..0000000000 --- a/ecmascript/compiler/llvm/llvm_new.patch +++ /dev/null @@ -1,1037 +0,0 @@ -diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt -index 0e85afa82c7..43756892e40 100644 ---- a/llvm/CMakeLists.txt -+++ b/llvm/CMakeLists.txt -@@ -505,8 +505,15 @@ option(LLVM_BUILD_RUNTIME - "Build the LLVM runtime libraries." ON) - option(LLVM_BUILD_EXAMPLES - "Build the LLVM example programs. If OFF, just generate build targets." OFF) -+option(BUILD_ARK_GC_SUPPORT -+ "ARK support GC. If ON, support GC." OFF) -+if(BUILD_ARK_GC_SUPPORT) -+ add_definitions(-DARK_GC_SUPPORT) -+endif(BUILD_ARK_GC_SUPPORT) -+ - option(LLVM_INCLUDE_EXAMPLES "Generate build targets for the LLVM examples" ON) - -+ - if(LLVM_BUILD_EXAMPLES) - add_definitions(-DBUILD_EXAMPLES) - endif(LLVM_BUILD_EXAMPLES) -diff --git a/llvm/include/llvm-c/ExecutionEngine.h b/llvm/include/llvm-c/ExecutionEngine.h -index f31b97ad762..ceda6a19496 100644 ---- a/llvm/include/llvm-c/ExecutionEngine.h -+++ b/llvm/include/llvm-c/ExecutionEngine.h -@@ -42,6 +42,7 @@ typedef struct LLVMOpaqueMCJITMemoryManager *LLVMMCJITMemoryManagerRef; - - struct LLVMMCJITCompilerOptions { - unsigned OptLevel; -+ LLVMRelocMode RelMode; - LLVMCodeModel CodeModel; - LLVMBool NoFramePointerElim; - LLVMBool EnableFastISel; -diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h b/llvm/include/llvm/CodeGen/TargetFrameLowering.h -index c7d4c4d7e5d..1df40696dd0 100644 ---- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h -+++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h -@@ -15,6 +15,9 @@ - - #include "llvm/CodeGen/MachineBasicBlock.h" - #include "llvm/ADT/StringSwitch.h" -+#ifdef ARK_GC_SUPPORT -+#include "llvm/ADT/Triple.h" -+#endif - #include - #include - -@@ -177,7 +180,12 @@ public: - MachineBasicBlock &MBB) const = 0; - virtual void emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const = 0; -- -+#ifdef ARK_GC_SUPPORT -+ virtual Triple::ArchType GetArkSupportTarget() const -+ { -+ return Triple::UnknownArch; -+ } -+#endif - /// Replace a StackProbe stub (if any) with the actual probe code inline - virtual void inlineStackProbe(MachineFunction &MF, - MachineBasicBlock &PrologueMBB) const {} -diff --git a/llvm/include/llvm/Target/CodeGenCWrappers.h b/llvm/include/llvm/Target/CodeGenCWrappers.h -index a9954635705..a0a533a7153 100644 ---- a/llvm/include/llvm/Target/CodeGenCWrappers.h -+++ b/llvm/include/llvm/Target/CodeGenCWrappers.h -@@ -59,6 +59,36 @@ inline LLVMCodeModel wrap(CodeModel::Model Model) { - } - llvm_unreachable("Bad CodeModel!"); - } -+ -+inline Reloc::Model unwrap(LLVMRelocMode Model) { -+ switch (Model) { -+ case LLVMRelocDefault: -+ case LLVMRelocStatic: -+ return Reloc::Static; -+ case LLVMRelocPIC: -+ return Reloc::PIC_; -+ case LLVMRelocDynamicNoPic: -+ return Reloc::DynamicNoPIC; -+ } -+ llvm_unreachable("Invalid LLVMRelocMode!"); -+} -+ -+inline LLVMRelocMode unwrap(Reloc::Model Model) { -+ switch (Model) { -+ case Reloc::Static: -+ return LLVMRelocStatic; -+ case Reloc::PIC_: -+ return LLVMRelocPIC; -+ case Reloc::DynamicNoPIC: -+ return LLVMRelocDynamicNoPic; -+ case Reloc::ROPI: -+ case Reloc::RWPI: -+ case Reloc::ROPI_RWPI: -+ break; -+ } -+ llvm_unreachable("Invalid Reloc::Model!"); -+} -+ - } // namespace llvm - - #endif -diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/llvm/lib/CodeGen/PrologEpilogInserter.cpp -index 3909b571728..b9a835d0b39 100644 ---- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp -+++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp -@@ -79,6 +79,9 @@ using MBBVector = SmallVector; - STATISTIC(NumLeafFuncWithSpills, "Number of leaf functions with CSRs"); - STATISTIC(NumFuncSeen, "Number of functions seen in PEI"); - -+#define JS_ENTRY_FRAME_MARK 1 -+#define JS_FRAME_MARK 0 -+ - - namespace { - -@@ -878,6 +881,32 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &MF) { - int64_t FixedCSEnd = Offset; - unsigned MaxAlign = MFI.getMaxAlignment(); - -+ #ifdef ARK_GC_SUPPORT -+ unsigned CalleeSavedFrameSize = 0; -+ Triple::ArchType archType = TFI.GetArkSupportTarget(); -+ if (archType != Triple::UnknownArch) { -+ int slotSize = sizeof(uint32_t); -+ if (archType == Triple::aarch64 || archType == Triple::x86_64) { -+ slotSize = sizeof(uint64_t); -+ } -+ if (MF.getFunction().hasFnAttribute("js-stub-call")) { -+ int64_t marker = 0x0; -+ MF.getFunction() -+ .getFnAttribute("js-stub-call") -+ .getValueAsString() -+ .getAsInteger(10, marker);//marker 1 break frame -+ if (marker == JS_ENTRY_FRAME_MARK) { -+ CalleeSavedFrameSize = 3 * slotSize; // 3 * slotSize;/* frameType + currentSP + threadSP*/ -+ } else if (marker == JS_FRAME_MARK){ -+ CalleeSavedFrameSize = 2 * slotSize; /* 2: frameType + currentSP */ -+ } else { -+ assert("js-stub-call is illeagl ! "); -+ } -+ Offset += CalleeSavedFrameSize; -+ } -+ } -+ #endif -+ - // Make sure the special register scavenging spill slot is closest to the - // incoming stack pointer if a frame pointer is required and is closer - // to the incoming rather than the final stack pointer. -diff --git a/llvm/lib/CodeGen/StackMaps.cpp b/llvm/lib/CodeGen/StackMaps.cpp -index e16587c44a5..bd3e99c6600 100644 ---- a/llvm/lib/CodeGen/StackMaps.cpp -+++ b/llvm/lib/CodeGen/StackMaps.cpp -@@ -29,6 +29,9 @@ - #include "llvm/Support/ErrorHandling.h" - #include "llvm/Support/MathExtras.h" - #include "llvm/Support/raw_ostream.h" -+#ifdef ARK_GC_SUPPORT -+#include "llvm/Target/TargetMachine.h" -+#endif - #include - #include - #include -@@ -442,7 +445,11 @@ void StackMaps::emitFunctionFrameRecords(MCStreamer &OS) { - LLVM_DEBUG(dbgs() << WSMP << "function addr: " << FR.first - << " frame size: " << FR.second.StackSize - << " callsite count: " << FR.second.RecordCount << '\n'); -+#ifdef ARK_GC_SUPPORT -+ OS.EmitSymbolValue(FR.first, AP.TM.getProgramPointerSize()); -+#else - OS.EmitSymbolValue(FR.first, 8); -+#endif - OS.EmitIntValue(FR.second.StackSize, 8); - OS.EmitIntValue(FR.second.RecordCount, 8); - } -diff --git a/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp -index ff1e8050c7e..a18df38ab53 100644 ---- a/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp -+++ b/llvm/lib/ExecutionEngine/ExecutionEngineBindings.cpp -@@ -198,6 +198,7 @@ LLVMBool LLVMCreateMCJITCompilerForModule( - builder.setEngineKind(EngineKind::JIT) - .setErrorStr(&Error) - .setOptLevel((CodeGenOpt::Level)options.OptLevel) -+ .setRelocationModel(unwrap(options.RelMode)) - .setTargetOptions(targetOptions); - bool JIT; - if (Optional CM = unwrap(options.CodeModel, JIT)) -diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp -index 6da089d1859..271b4e157d9 100644 ---- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp -+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp -@@ -95,6 +95,10 @@ public: - const MachineInstr &MI); - void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM, - const MachineInstr &MI); -+#ifdef ARK_GC_SUPPORT -+ void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, -+ const MachineInstr &MI); -+#endif - - void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI); - void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI); -@@ -936,6 +940,49 @@ void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM, - EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0)); - } - -+#ifdef ARK_GC_SUPPORT -+void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, -+ const MachineInstr &MI) { -+ StatepointOpers SOpers(&MI); -+ if (unsigned PatchBytes = SOpers.getNumPatchBytes()) { -+ assert(PatchBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); -+ for (unsigned i = 0; i < PatchBytes; i += 4) -+ EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0)); -+ } else { -+ // Lower call target and choose correct opcode -+ const MachineOperand &CallTarget = SOpers.getCallTarget(); -+ MCOperand CallTargetMCOp; -+ unsigned CallOpcode; -+ switch (CallTarget.getType()) { -+ case MachineOperand::MO_GlobalAddress: -+ case MachineOperand::MO_ExternalSymbol: -+ MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp); -+ CallOpcode = AArch64::BL; -+ break; -+ case MachineOperand::MO_Immediate: -+ CallTargetMCOp = MCOperand::createImm(CallTarget.getImm()); -+ CallOpcode = AArch64::BL; -+ break; -+ case MachineOperand::MO_Register: -+ CallTargetMCOp = MCOperand::createReg(CallTarget.getReg()); -+ CallOpcode = AArch64::BLR; -+ break; -+ default: -+ llvm_unreachable("Unsupported operand type in statepoint call target"); -+ break; -+ } -+ -+ EmitToStreamer(OutStreamer, -+ MCInstBuilder(CallOpcode).addOperand(CallTargetMCOp)); -+ } -+ -+ auto &Ctx = OutStreamer.getContext(); -+ MCSymbol *MILabel = Ctx.createTempSymbol(); -+ OutStreamer.EmitLabel(MILabel); -+ SM.recordStatepoint(*MILabel, MI); -+} -+#endif -+ - void AArch64AsmPrinter::EmitFMov0(const MachineInstr &MI) { - Register DestReg = MI.getOperand(0).getReg(); - if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround()) { -@@ -1198,6 +1245,11 @@ void AArch64AsmPrinter::EmitInstruction(const MachineInstr *MI) { - case TargetOpcode::PATCHPOINT: - return LowerPATCHPOINT(*OutStreamer, SM, *MI); - -+#ifdef ARK_GC_SUPPORT -+ case TargetOpcode::STATEPOINT: -+ return LowerSTATEPOINT(*OutStreamer, SM, *MI); -+#endif -+ - case TargetOpcode::PATCHABLE_FUNCTION_ENTER: - LowerPATCHABLE_FUNCTION_ENTER(*MI); - return; -diff --git a/llvm/lib/Target/AArch64/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/AArch64CallLowering.cpp -index 76ff238234d..f52d4c5c877 100644 ---- a/llvm/lib/Target/AArch64/AArch64CallLowering.cpp -+++ b/llvm/lib/Target/AArch64/AArch64CallLowering.cpp -@@ -213,7 +213,11 @@ struct OutgoingArgHandler : public CallLowering::ValueHandler { - } // namespace - - static bool doesCalleeRestoreStack(CallingConv::ID CallConv, bool TailCallOpt) { -- return CallConv == CallingConv::Fast && TailCallOpt; -+ #ifdef ARK_GC_SUPPORT -+ return (CallConv == CallingConv::GHC || (CallConv == CallingConv::Fast)) && TailCallOpt; -+ #else -+ return CallConv == CallingConv::Fast && TailCallOpt; -+ #endif - } - - void AArch64CallLowering::splitToValueTypes( -@@ -496,7 +500,11 @@ bool AArch64CallLowering::lowerFormalArguments( - - /// Return true if the calling convention is one that we can guarantee TCO for. - static bool canGuaranteeTCO(CallingConv::ID CC) { -- return CC == CallingConv::Fast; -+ #ifdef ARK_GC_SUPPORT -+ return (CC == CallingConv::GHC) || (CC == CallingConv::Fast); -+ #else -+ return CC == CallingConv::Fast; -+ #endif - } - - /// Return true if we might ever do TCO for calls with this calling convention. -diff --git a/llvm/lib/Target/AArch64/AArch64CallingConvention.td b/llvm/lib/Target/AArch64/AArch64CallingConvention.td -index a0b2d7712b6..511cd3a3a36 100644 ---- a/llvm/lib/Target/AArch64/AArch64CallingConvention.td -+++ b/llvm/lib/Target/AArch64/AArch64CallingConvention.td -@@ -355,7 +355,7 @@ def CC_AArch64_GHC : CallingConv<[ - CCIfType<[i8, i16, i32], CCPromoteToType>, - - // Pass in STG registers: Base, Sp, Hp, R1, R2, R3, R4, R5, R6, SpLim -- CCIfType<[i64], CCAssignToReg<[X19, X20, X21, X22, X23, X24, X25, X26, X27, X28]>> -+ CCIfType<[i64], CCAssignToReg<[X19, FP, X20, X21, X22, X23, X24, X25, X26, X27, X28]>> - ]>; - - // The order of the callee-saves in this file is important, because the -@@ -373,9 +373,10 @@ def CC_AArch64_GHC : CallingConv<[ - // vreg on entry, use it in RET & tail call generation; make that vreg def if we - // end up saving LR as part of a call frame). Watch this space... - def CSR_AArch64_AAPCS : CalleeSavedRegs<(add X19, X20, X21, X22, X23, X24, -- X25, X26, X27, X28, LR, FP, -+ X25, X26, X27, X28, - D8, D9, D10, D11, -- D12, D13, D14, D15)>; -+ D12, D13, D14, D15, -+ LR, FP)>; - - // Darwin puts the frame-record at the top of the callee-save area. - def CSR_Darwin_AArch64_AAPCS : CalleeSavedRegs<(add LR, FP, X19, X20, X21, X22, -diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp -index 651ad9ad4c8..729d7122cd0 100644 ---- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp -+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp -@@ -385,6 +385,7 @@ void AArch64FrameLowering::emitCalleeSavedFrameMoves( - unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); - unsigned CFIIndex = MF.addFrameInst( - MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset)); -+ - BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) - .addCFIIndex(CFIIndex) - .setMIFlags(MachineInstr::FrameSetup); -@@ -535,10 +536,11 @@ static MachineBasicBlock::iterator InsertSEH(MachineBasicBlock::iterator MBBI, - case AArch64::STPXpre: { - Register Reg0 = MBBI->getOperand(1).getReg(); - Register Reg1 = MBBI->getOperand(2).getReg(); -- if (Reg0 == AArch64::FP && Reg1 == AArch64::LR) -+ if (Reg0 == AArch64::FP && Reg1 == AArch64::LR) { - MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveFPLR_X)) - .addImm(Imm * 8) - .setMIFlag(Flag); -+ } - else - MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveRegP_X)) - .addImm(RegInfo->getSEHRegNum(Reg0)) -@@ -584,10 +586,11 @@ static MachineBasicBlock::iterator InsertSEH(MachineBasicBlock::iterator MBBI, - case AArch64::LDPXi: { - Register Reg0 = MBBI->getOperand(0).getReg(); - Register Reg1 = MBBI->getOperand(1).getReg(); -- if (Reg0 == AArch64::FP && Reg1 == AArch64::LR) -+ if (Reg0 == AArch64::FP && Reg1 == AArch64::LR) { - MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveFPLR)) - .addImm(Imm * 8) - .setMIFlag(Flag); -+ } - else - MIB = BuildMI(MF, DL, TII.get(AArch64::SEH_SaveRegP)) - .addImm(RegInfo->getSEHRegNum(Reg0)) -@@ -872,6 +875,13 @@ static bool IsSVECalleeSave(MachineBasicBlock::iterator I) { - } - } - -+#ifdef ARK_GC_SUPPORT -+Triple::ArchType AArch64FrameLowering::GetArkSupportTarget() const -+{ -+ return Triple::aarch64; -+} -+#endif -+ - void AArch64FrameLowering::emitPrologue(MachineFunction &MF, - MachineBasicBlock &MBB) const { - MachineBasicBlock::iterator MBBI = MBB.begin(); -@@ -920,8 +930,11 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, - - // All calls are tail calls in GHC calling conv, and functions have no - // prologue/epilogue. -+ #ifndef ARK_GC_SUPPORT - if (MF.getFunction().getCallingConv() == CallingConv::GHC) - return; -+ #endif -+ // asm-int GHC call webkit function, we need push regs to stack. - - // Set tagged base pointer to the bottom of the stack frame. - // Ideally it should match SP value after prologue. -@@ -980,6 +993,7 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, - unsigned FixedObject = getFixedObjectSize(MF, AFI, IsWin64, IsFunclet); - - auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject; -+ - // All of the remaining stack allocations are for locals. - AFI->setLocalStackSize(NumBytes - PrologueSaveSize); - bool CombineSPBump = shouldCombineCSRLocalStackBump(MF, NumBytes); -@@ -1020,11 +1034,13 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, - // mov fp,sp when FPOffset is zero. - // Note: All stores of callee-saved registers are marked as "FrameSetup". - // This code marks the instruction(s) that set the FP also. -+ - emitFrameOffset(MBB, MBBI, DL, AArch64::FP, AArch64::SP, - {FPOffset, MVT::i8}, TII, MachineInstr::FrameSetup, false, - NeedsWinCFI, &HasWinCFI); - } - -+ - if (windowsRequiresStackProbe(MF, NumBytes)) { - uint64_t NumWords = NumBytes >> 4; - if (NeedsWinCFI) { -@@ -1405,8 +1421,11 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, - - // All calls are tail calls in GHC calling conv, and functions have no - // prologue/epilogue. -+ #ifndef ARK_GC_SUPPORT - if (MF.getFunction().getCallingConv() == CallingConv::GHC) - return; -+ #endif -+ // asm-int GHC call webkit function, we need push regs to stack. - - // Initial and residual are named for consistency with the prologue. Note that - // in the epilogue, the residual adjustment is executed first. -@@ -1514,6 +1533,8 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, - - const StackOffset &SVEStackSize = getSVEStackSize(MF); - -+ -+ - // If there is a single SP update, insert it before the ret and we're done. - if (CombineSPBump) { - assert(!SVEStackSize && "Cannot combine SP bump with SVE"); -@@ -1552,6 +1573,8 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, - DeallocateAfter = SVEStackSize - DeallocateBefore; - } - -+ -+ - // Deallocate the SVE area. - if (SVEStackSize) { - if (AFI->isStackRealigned()) { -@@ -1632,6 +1655,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF, - // This must be placed after the callee-save restore code because that code - // assumes the SP is at the same location as it was after the callee-save save - // code in the prologue. -+ - if (AfterCSRPopSize) { - // Find an insertion point for the first ldp so that it goes before the - // shadow call stack epilog instruction. This ensures that the restore of -@@ -2079,6 +2103,7 @@ static void computeCalleeSaveRegisterPairs( - RegPairs.push_back(RPI); - if (RPI.isPaired()) - ++i; -+ - } - } - -@@ -2234,6 +2259,8 @@ bool AArch64FrameLowering::restoreCalleeSavedRegisters( - SmallVector RegPairs; - bool NeedsWinCFI = needsWinCFI(MF); - -+ -+ - if (MI != MBB.end()) - DL = MI->getDebugLoc(); - -@@ -2348,8 +2375,11 @@ void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF, - RegScavenger *RS) const { - // All calls are tail calls in GHC calling conv, and functions have no - // prologue/epilogue. -+ #ifndef ARK_GC_SUPPORT - if (MF.getFunction().getCallingConv() == CallingConv::GHC) - return; -+ #endif -+ // asm-int GHC call webkit function, we need push regs to stack. - - TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); - const AArch64RegisterInfo *RegInfo = static_cast( -@@ -2416,6 +2446,7 @@ void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF, - CSStackSize += RegSize; - } - -+ - // Save number of saved regs, so we can easily update CSStackSize later. - unsigned NumSavedRegs = SavedRegs.count(); - -diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.h b/llvm/lib/Target/AArch64/AArch64FrameLowering.h -index b5719feb6b1..b09aa05176d 100644 ---- a/llvm/lib/Target/AArch64/AArch64FrameLowering.h -+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.h -@@ -15,6 +15,11 @@ - - #include "AArch64StackOffset.h" - #include "llvm/CodeGen/TargetFrameLowering.h" -+#ifdef ARK_GC_SUPPORT -+#include "llvm/ADT/Triple.h" -+#endif -+ -+#define JS_ENTRY_FRAME_MARK 1 - - namespace llvm { - -@@ -35,6 +40,9 @@ public: - /// the function. - void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; -+#ifdef ARK_GC_SUPPORT -+ Triple::ArchType GetArkSupportTarget() const override; -+#endif - - bool canUseAsPrologue(const MachineBasicBlock &MBB) const override; - -diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp -index 23f05eaad94..cbf1347c4d6 100644 ---- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp -+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp -@@ -1498,6 +1498,10 @@ MachineBasicBlock *AArch64TargetLowering::EmitInstrWithCustomInserter( - - case TargetOpcode::STACKMAP: - case TargetOpcode::PATCHPOINT: -+#ifdef ARK_GC_SUPPORT -+ case TargetOpcode::STATEPOINT: -+ MI.addOperand(*BB->getParent(), MachineOperand::CreateReg(AArch64::LR, true, true)); -+#endif - return emitPatchPoint(MI, BB); - - case AArch64::CATCHRET: -@@ -3736,7 +3740,11 @@ SDValue AArch64TargetLowering::LowerCallResult( - - /// Return true if the calling convention is one that we can guarantee TCO for. - static bool canGuaranteeTCO(CallingConv::ID CC) { -- return CC == CallingConv::Fast; -+ #ifdef ARK_GC_SUPPORT -+ return (CC == CallingConv::GHC) || (CC == CallingConv::Fast); -+ #else -+ return CC == CallingConv::Fast; -+ #endif - } - - /// Return true if we might ever do TCO for calls with this calling convention. -@@ -3903,7 +3911,11 @@ SDValue AArch64TargetLowering::addTokenForArgument(SDValue Chain, - - bool AArch64TargetLowering::DoesCalleeRestoreStack(CallingConv::ID CallCC, - bool TailCallOpt) const { -+#ifdef ARK_GC_SUPPORT -+ return (CallCC == CallingConv::GHC || (CallCC == CallingConv::Fast)) && TailCallOpt; -+#else - return CallCC == CallingConv::Fast && TailCallOpt; -+#endif - } - - /// LowerCall - Lower a call to a callseq_start + CALL + callseq_end chain, -diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp -index 54f3f7c1013..c57374c9c78 100644 ---- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp -+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp -@@ -107,6 +107,15 @@ unsigned AArch64InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { - NumBytes = PatchPointOpers(&MI).getNumPatchBytes(); - assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); - break; -+#ifdef ARK_GC_SUPPORT -+ case TargetOpcode::STATEPOINT: -+ NumBytes = StatepointOpers(&MI).getNumPatchBytes(); -+ assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); -+ // No patch bytes means a normal call inst is emitted -+ if (NumBytes == 0) -+ NumBytes = 4; -+ break; -+#endif - case AArch64::TLSDESC_CALLSEQ: - // This gets lowered to an instruction sequence which takes 16 bytes - NumBytes = 16; -diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp -index 14f839cd4f8..a312944f17a 100644 ---- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp -+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp -@@ -205,6 +205,13 @@ AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const { - if (TFI->hasFP(MF) || TT.isOSDarwin()) - markSuperRegs(Reserved, AArch64::W29); - -+#ifdef ARK_GC_SUPPORT -+ if (MF.getFunction().getCallingConv() == CallingConv::GHC) { -+ markSuperRegs(Reserved, AArch64::W29); -+ markSuperRegs(Reserved, AArch64::W30); -+ } -+#endif -+ - for (size_t i = 0; i < AArch64::GPR32commonRegClass.getNumRegs(); ++i) { - if (MF.getSubtarget().isXRegisterReserved(i)) - markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i)); -@@ -464,8 +471,14 @@ void AArch64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - unsigned FrameReg; - - // Special handling of dbg_value, stackmap and patchpoint instructions. -+#ifdef ARK_GC_SUPPORT -+ if (MI.isDebugValue() || MI.getOpcode() == TargetOpcode::STACKMAP || -+ MI.getOpcode() == TargetOpcode::PATCHPOINT || -+ MI.getOpcode() == TargetOpcode::STATEPOINT) { -+#else - if (MI.isDebugValue() || MI.getOpcode() == TargetOpcode::STACKMAP || - MI.getOpcode() == TargetOpcode::PATCHPOINT) { -+#endif - StackOffset Offset = - TFI->resolveFrameIndexReference(MF, FrameIndex, FrameReg, - /*PreferFP=*/true, -diff --git a/llvm/lib/Target/AArch64/AArch64StackOffset.h b/llvm/lib/Target/AArch64/AArch64StackOffset.h -index f95b5dc5246..99f5905565a 100644 ---- a/llvm/lib/Target/AArch64/AArch64StackOffset.h -+++ b/llvm/lib/Target/AArch64/AArch64StackOffset.h -@@ -37,7 +37,7 @@ namespace llvm { - class StackOffset { - int64_t Bytes; - int64_t ScalableBytes; -- -+public: - explicit operator int() const; - - public: -diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp -index 4724d6b8dae..2155ad923f9 100644 ---- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp -+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp -@@ -189,6 +189,12 @@ int AArch64TTIImpl::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, - if ((Idx < 4) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) - return TTI::TCC_Free; - break; -+#ifdef ARK_GC_SUPPORT -+ case Intrinsic::experimental_gc_statepoint: -+ if ((Idx < 5) || (Imm.getBitWidth() <= 64 && isInt<64>(Imm.getSExtValue()))) -+ return TTI::TCC_Free; -+ break; -+#endif - } - return AArch64TTIImpl::getIntImmCost(Imm, Ty); - } -diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp -index 6f26ca127f9..20b2a76518f 100644 ---- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp -+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp -@@ -55,7 +55,11 @@ using namespace llvm; - ARMAsmPrinter::ARMAsmPrinter(TargetMachine &TM, - std::unique_ptr Streamer) - : AsmPrinter(TM, std::move(Streamer)), Subtarget(nullptr), AFI(nullptr), -+#ifdef ARK_GC_SUPPORT -+ MCP(nullptr), InConstantPool(false), OptimizationGoals(-1), SM(*this) {} -+#else - MCP(nullptr), InConstantPool(false), OptimizationGoals(-1) {} -+#endif - - void ARMAsmPrinter::EmitFunctionBodyEnd() { - // Make sure to terminate any constant pools that were at the end -@@ -567,6 +571,10 @@ void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { - OptimizationGoals = -1; - - ATS.finishAttributeSection(); -+ -+#ifdef ARK_GC_SUPPORT -+ SM.serializeToStackMapSection(); -+#endif - } - - //===----------------------------------------------------------------------===// -@@ -2135,6 +2143,14 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { - case ARM::PATCHABLE_TAIL_CALL: - LowerPATCHABLE_TAIL_CALL(*MI); - return; -+#ifdef ARK_GC_SUPPORT -+ case TargetOpcode::STACKMAP: -+ return LowerSTACKMAP(*OutStreamer, SM, *MI); -+ case TargetOpcode::PATCHPOINT: -+ return LowerPATCHPOINT(*OutStreamer, SM, *MI); -+ case TargetOpcode::STATEPOINT: -+ return LowerSTATEPOINT(*OutStreamer, SM, *MI); -+#endif - } - - MCInst TmpInst; -@@ -2143,6 +2159,76 @@ void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { - EmitToStreamer(*OutStreamer, TmpInst); - } - -+#ifdef ARK_GC_SUPPORT -+static unsigned roundUpTo4ByteAligned(unsigned n) { -+ unsigned mask = 3; -+ unsigned rev = ~3; -+ n = (n & rev) + (((n & mask) + mask) & rev); -+ return n; -+} -+ -+void ARMAsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM, -+ const MachineInstr &MI) { -+ llvm_unreachable("Stackmap lowering is not implemented"); -+} -+ -+void ARMAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM, -+ const MachineInstr &MI) { -+ llvm_unreachable("Patchpoint lowering is not implemented"); -+} -+ -+void ARMAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, -+ const MachineInstr &MI) { -+ assert(!AFI->isThumbFunction()); -+ -+ StatepointOpers SOpers(&MI); -+ MCInst Noop; -+ Subtarget->getInstrInfo()->getNoop(Noop); -+ if (unsigned PatchBytes = SOpers.getNumPatchBytes()) { -+ unsigned NumBytes = roundUpTo4ByteAligned(PatchBytes); -+ unsigned EncodedBytes = 0; -+ assert(NumBytes >= EncodedBytes && -+ "Statepoint can't request size less than the length of a call."); -+ assert((NumBytes - EncodedBytes) % 4 == 0 && -+ "Invalid number of NOP bytes requested!"); -+ MCInst Noop; -+ Subtarget->getInstrInfo()->getNoop(Noop); -+ for (unsigned i = EncodedBytes; i < NumBytes; i += 4) -+ EmitToStreamer(OutStreamer, Noop); -+ } else { -+ const MachineOperand &CallTarget = SOpers.getCallTarget(); -+ MCOperand CallTargetMCOp; -+ unsigned CallOpcode; -+ switch (CallTarget.getType()) { -+ case MachineOperand::MO_GlobalAddress: -+ case MachineOperand::MO_ExternalSymbol: -+ ARMAsmPrinter::lowerOperand(CallTarget, CallTargetMCOp); -+ CallOpcode = ARM::BL; -+ break; -+ case MachineOperand::MO_Immediate: -+ CallTargetMCOp = MCOperand::createImm(CallTarget.getImm()); -+ CallOpcode = ARM::BL; -+ break; -+ case MachineOperand::MO_Register: -+ CallTargetMCOp = MCOperand::createReg(CallTarget.getReg()); -+ CallOpcode = ARM::BLX; -+ break; -+ default: -+ llvm_unreachable("Unsupported operand type in statepoint call target"); -+ break; -+ } -+ -+ EmitToStreamer(OutStreamer, -+ MCInstBuilder(CallOpcode).addOperand(CallTargetMCOp)); -+ } -+ -+ auto &Ctx = OutStreamer.getContext(); -+ MCSymbol *MILabel = Ctx.createTempSymbol(); -+ OutStreamer.EmitLabel(MILabel); -+ SM.recordStatepoint(*MILabel, MI); -+} -+#endif -+ - //===----------------------------------------------------------------------===// - // Target Registry Stuff - //===----------------------------------------------------------------------===// -diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.h b/llvm/lib/Target/ARM/ARMAsmPrinter.h -index a4b37fa2331..be62b1875f4 100644 ---- a/llvm/lib/Target/ARM/ARMAsmPrinter.h -+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.h -@@ -11,6 +11,9 @@ - - #include "ARMSubtarget.h" - #include "llvm/CodeGen/AsmPrinter.h" -+#ifdef ARK_GC_SUPPORT -+#include "llvm/CodeGen/StackMaps.h" -+#endif - #include "llvm/Target/TargetMachine.h" - - namespace llvm { -@@ -65,6 +68,10 @@ class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter { - /// debug info can link properly. - SmallPtrSet EmittedPromotedGlobalLabels; - -+#ifdef ARK_GC_SUPPORT -+ StackMaps SM; -+#endif -+ - public: - explicit ARMAsmPrinter(TargetMachine &TM, - std::unique_ptr Streamer); -@@ -129,6 +136,17 @@ private: - bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, - const MachineInstr *MI); - -+#ifdef ARK_GC_SUPPORT -+ void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM, -+ const MachineInstr &MI); -+ -+ void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM, -+ const MachineInstr &MI); -+ -+ void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM, -+ const MachineInstr &MI); -+#endif -+ - public: - unsigned getISAEncoding() override { - // ARM/Darwin adds ISA to the DWARF info for each function. -diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp -index 48f78151025..0970a6259ad 100644 ---- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp -+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp -@@ -712,6 +712,11 @@ unsigned ARMBaseInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { - return 0; - case TargetOpcode::BUNDLE: - return getInstBundleLength(MI); -+#ifdef ARK_GC_SUPPORT -+ case TargetOpcode::PATCHPOINT: -+ case TargetOpcode::STATEPOINT: -+ return MI.getOperand(1).getImm(); -+#endif - case ARM::MOVi16_ga_pcrel: - case ARM::MOVTi16_ga_pcrel: - case ARM::t2MOVi16_ga_pcrel: -diff --git a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp -index 52e6d05c315..034fa157e4a 100644 ---- a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp -+++ b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp -@@ -196,6 +196,12 @@ getReservedRegs(const MachineFunction &MF) const { - markSuperRegs(Reserved, ARM::APSR_NZCV); - if (TFI->hasFP(MF)) - markSuperRegs(Reserved, getFramePointerReg(STI)); -+#ifdef ARK_GC_SUPPORT -+ if (MF.getFunction().getCallingConv() == CallingConv::GHC) { -+ markSuperRegs(Reserved, ARM::R11); -+ markSuperRegs(Reserved, ARM::LR); -+ } -+#endif - if (hasBasePointer(MF)) - markSuperRegs(Reserved, BasePtr); - // Some targets reserve R9. -diff --git a/llvm/lib/Target/ARM/ARMCallingConv.td b/llvm/lib/Target/ARM/ARMCallingConv.td -index 5df5b56f5af..e4c3493ead6 100644 ---- a/llvm/lib/Target/ARM/ARMCallingConv.td -+++ b/llvm/lib/Target/ARM/ARMCallingConv.td -@@ -119,7 +119,7 @@ def CC_ARM_APCS_GHC : CallingConv<[ - CCIfType<[i8, i16], CCPromoteToType>, - - // Pass in STG registers: Base, Sp, Hp, R1, R2, R3, R4, SpLim -- CCIfType<[i32], CCAssignToReg<[R4, R5, R6, R7, R8, R9, R10, R11]>> -+ CCIfType<[i32], CCAssignToReg<[R4, R11, R5, R6, R7, R8, R9, R10]>> - ]>; - - //===----------------------------------------------------------------------===// -diff --git a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp -index 66ad120a111..59335c77394 100644 ---- a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp -+++ b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp -@@ -831,6 +831,11 @@ initializeFunctionInfo(const std::vector &CPEMIs) { - NegOk = true; - break; - } -+ // Decrease a bit here to workaround the out of range pc-relative -+ // fixup value error during the MCJIT compilation process -+ if (Bits > 0) { -+ Bits--; -+ } - - // Remember that this is a user of a CP entry. - unsigned CPI = I.getOperand(op).getIndex(); -diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp -index cb98b2b34ef..1806214932e 100644 ---- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp -+++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp -@@ -1573,6 +1573,7 @@ static unsigned estimateRSStackSizeLimit(MachineFunction &MF, - Limit = std::min(Limit, ((1U << 7) - 1) * 4); - break; - default: -+ break; - llvm_unreachable("Unhandled addressing mode in stack size limit calculation"); - } - break; // At most one FI per instruction -diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp -index 9f504b1eaa4..30a1baf5c85 100644 ---- a/llvm/lib/Target/ARM/ARMISelLowering.cpp -+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp -@@ -10551,6 +10551,14 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, - llvm_unreachable("Unexpected instr type to insert"); - } - -+#ifdef ARK_GC_SUPPORT -+ case TargetOpcode::STATEPOINT: -+ case TargetOpcode::STACKMAP: -+ case TargetOpcode::PATCHPOINT: -+ MI.addOperand(*BB->getParent(), MachineOperand::CreateReg(ARM::LR, true, true)); -+ return emitPatchPoint(MI, BB); -+#endif -+ - // Thumb1 post-indexed loads are really just single-register LDMs. - case ARM::tLDR_postidx: { - MachineOperand Def(MI.getOperand(1)); -diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp -index 1da20371caf..01f0d6a2801 100644 ---- a/llvm/lib/Target/X86/X86FrameLowering.cpp -+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp -@@ -968,6 +968,13 @@ bool X86FrameLowering::has128ByteRedZone(const MachineFunction& MF) const { - - for 32-bit code, substitute %e?? registers for %r?? - */ - -+#ifdef ARK_GC_SUPPORT -+Triple::ArchType X86FrameLowering::GetArkSupportTarget() const -+{ -+ return Is64Bit ? Triple::x86_64 : Triple::x86; -+} -+#endif -+ - void X86FrameLowering::emitPrologue(MachineFunction &MF, - MachineBasicBlock &MBB) const { - assert(&STI == &MF.getSubtarget() && -@@ -1168,6 +1175,30 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, - else - MFI.setOffsetAdjustment(-StackSize); - } -+#ifdef ARK_GC_SUPPORT -+ // push marker -+ if (MF.getFunction().hasFnAttribute("js-stub-call")) -+ { -+ int64_t marker = 0x0; -+ MF.getFunction() -+ .getFnAttribute("js-stub-call") -+ .getValueAsString() -+ .getAsInteger(10, marker);//marker 1 break frame -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64i32 : X86::PUSH32i8)) -+ .addImm(marker) -+ .setMIFlag(MachineInstr::FrameSetup); // type -+ -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64i32 : X86::PUSH32i8)) -+ .addImm(marker) -+ .setMIFlag(MachineInstr::FrameSetup); // current sp -+ -+ if (marker == JS_ENTRY_FRAME_MARK) { -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::PUSH64i32 : X86::PUSH32i8)) -+ .addImm(marker) -+ .setMIFlag(MachineInstr::FrameSetup); // thread sp -+ } -+ } -+#endif - - // For EH funclets, only allocate enough space for outgoing calls. Save the - // NumBytes value that we would've used for the parent frame. -@@ -1635,6 +1666,31 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, - uint64_t SEHStackAllocAmt = NumBytes; - - if (HasFP) { -+#ifdef ARK_GC_SUPPORT -+ if (MF.getFunction().hasFnAttribute("js-stub-call")) -+ { -+ int64_t marker = 0x0; -+ MF.getFunction() -+ .getFnAttribute("js-stub-call") -+ .getValueAsString() -+ .getAsInteger(10, marker);//marker 1 break frame -+ -+ // pop marker -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), -+ MachineFramePtr) -+ .setMIFlag(MachineInstr::FrameDestroy); -+ // pop currentSP -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), -+ MachineFramePtr) -+ .setMIFlag(MachineInstr::FrameDestroy); -+ if (marker == JS_ENTRY_FRAME_MARK) { -+ // pop thread.fp -+ BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), -+ MachineFramePtr) -+ .setMIFlag(MachineInstr::FrameDestroy); -+ } -+ } -+#endif - // Pop EBP. - BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), - MachineFramePtr) -@@ -1993,8 +2049,31 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( - - if (hasFP(MF)) { - // emitPrologue always spills frame register the first thing. -+#ifdef ARK_GC_SUPPORT -+ if (MF.getFunction().hasFnAttribute("js-stub-call")) { -+ int64_t marker = 0x0; -+ MF.getFunction() -+ .getFnAttribute("js-stub-call") -+ .getValueAsString() -+ .getAsInteger(10, marker);//marker 1 break frame -+ -+ if (marker == JS_ENTRY_FRAME_MARK) { -+ SpillSlotOffset -= 4 * SlotSize; // add type and thread.fp and currentsp and threadfp -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ CalleeSavedFrameSize += (3 * SlotSize); -+ } else { -+ SpillSlotOffset -= 3 * SlotSize; // add type and pre and currentsp -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); // prev -+ CalleeSavedFrameSize += 2 * SlotSize; -+ } -+ } else { -+ SpillSlotOffset -= SlotSize; // add type and thread.fp -+ MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+ } -+#else - SpillSlotOffset -= SlotSize; - MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); -+#endif - - // Since emitPrologue and emitEpilogue will handle spilling and restoring of - // the frame register, we can delete it from CSI list and not have to worry -diff --git a/llvm/lib/Target/X86/X86FrameLowering.h b/llvm/lib/Target/X86/X86FrameLowering.h -index 2103d6471ea..36edb40cb5e 100644 ---- a/llvm/lib/Target/X86/X86FrameLowering.h -+++ b/llvm/lib/Target/X86/X86FrameLowering.h -@@ -15,6 +15,8 @@ - - #include "llvm/CodeGen/TargetFrameLowering.h" - -+#define JS_ENTRY_FRAME_MARK 1 -+ - namespace llvm { - - class MachineInstrBuilder; -@@ -64,6 +66,9 @@ public: - - /// emitProlog/emitEpilog - These methods insert prolog and epilog code into - /// the function. -+#ifdef ARK_GC_SUPPORT -+ Triple::ArchType GetArkSupportTarget() const override; -+#endif - void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - -diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp -index f69626b2622..0a7684d4673 100644 ---- a/llvm/lib/Target/X86/X86RegisterInfo.cpp -+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp -@@ -545,6 +545,12 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { - for (const MCPhysReg &SubReg : subregs_inclusive(X86::RBP)) - Reserved.set(SubReg); - } -+#ifdef ARK_GC_SUPPORT -+ if (MF.getFunction().getCallingConv() == CallingConv::GHC) { -+ for (const MCPhysReg &SubReg : subregs_inclusive(X86::RBP)) -+ Reserved.set(SubReg); -+ } -+#endif - - // Set the base-pointer register and its aliases as reserved if needed. - if (hasBasePointer(MF)) { diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp index 955bc3de53..aae31468ab 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -93,7 +93,7 @@ void LLVMStackMapParser::PrintCallSiteInfo(const CallSiteInfo *infos, OptimizedL } } -void LLVMStackMapParser::PrintCallSiteInfo(const CallSiteInfo *infos, uintptr_t *fp) const +void LLVMStackMapParser::PrintCallSiteInfo(const CallSiteInfo *infos, uintptr_t *fp, uintptr_t callSiteAddr) const { if (!IsLogEnabled()) { return; @@ -105,7 +105,7 @@ void LLVMStackMapParser::PrintCallSiteInfo(const CallSiteInfo *infos, uintptr_t uintptr_t derived = 0; uintptr_t callsiteFp = *fp; - uintptr_t callSiteSp = FrameHandler::GetPrevFrameCallSiteSp(reinterpret_cast(fp)); + uintptr_t callSiteSp = FrameHandler::GetPrevFrameCallSiteSp(reinterpret_cast(fp), callSiteAddr); for (auto &info: *infos) { if (info.first == GCStackMapRegisters::SP) { @@ -144,18 +144,26 @@ bool LLVMStackMapParser::CollectStackMapSlots(uintptr_t callSiteAddr, uintptr_t if (infos == nullptr) { return false; } + uintptr_t *fp = reinterpret_cast(frameFp); + uintptr_t callsiteFp = *fp; + uintptr_t callSiteSp = 0x0; + auto type = FrameHandler::GetFrameType(reinterpret_cast(frameFp)); + if (type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME || type == FrameType::OPTIMIZED_FRAME) { + callSiteSp = FrameHandler::GetPrevFrameCallSiteSp(reinterpret_cast(frameFp), callSiteAddr); + } else { + callSiteSp = FrameHandler::GetPrevFrameCallSiteSp(reinterpret_cast(frameFp)); + } + uintptr_t address = 0; uintptr_t base = 0; uintptr_t derived = 0; int i = 0; if (IsLogEnabled()) { - PrintCallSiteInfo(infos, fp); + PrintCallSiteInfo(infos, fp, callSiteAddr); } - uintptr_t callsiteFp = *fp; - uintptr_t callSiteSp = FrameHandler::GetPrevFrameCallSiteSp(reinterpret_cast(frameFp)); for (auto &info: *infos) { if (info.first == GCStackMapRegisters::SP) { address = callSiteSp + info.second; @@ -189,7 +197,9 @@ bool LLVMStackMapParser::CollectStackMapSlots(uintptr_t callSiteAddr, uintptr_t void LLVMStackMapParser::CalcCallSite() { uint64_t recordNum = 0; - auto calStkMapRecordFunc = [this, &recordNum](uintptr_t address, int recordId) { + Pc2CallSiteInfo pc2CallSiteInfo; + Pc2ConstInfo pc2ConstInfo; + auto calStkMapRecordFunc = [this, &recordNum, &pc2CallSiteInfo, &pc2ConstInfo](uintptr_t address, int recordId) { struct StkMapRecordHeadTy recordHead = llvmStackMap_.StkMapRecord[recordNum + recordId].head; for (int j = 0; j < recordHead.NumLocations; j++) { struct LocationTy loc = llvmStackMap_.StkMapRecord[recordNum + recordId].Locations[j]; @@ -202,12 +212,16 @@ void LLVMStackMapParser::CalcCallSite() instructionOffset << " callsite:" << " patchPointID :" << std::hex << patchPointID << callsite; DwarfRegAndOffsetType info(loc.DwarfRegNum, loc.OffsetOrSmallConstant); - auto it = pc2CallSiteInfo_.find(callsite); - if (pc2CallSiteInfo_.find(callsite) == pc2CallSiteInfo_.end()) { - pc2CallSiteInfo_.insert(std::pair(callsite, {info})); + auto it = pc2CallSiteInfo.find(callsite); + if (pc2CallSiteInfo.find(callsite) == pc2CallSiteInfo.end()) { + pc2CallSiteInfo.insert(std::pair(callsite, {info})); } else { it->second.emplace_back(info); } + } else if (loc.location == LocationTy::Kind::CONSTANT) { + if (j >= LocationTy::CONSTANT_FIRST_ELEMENT_INDEX) { + pc2ConstInfo[callsite].push_back(loc.OffsetOrSmallConstant); + } } } }; @@ -219,16 +233,17 @@ void LLVMStackMapParser::CalcCallSite() } recordNum += recordCount; } + pc2CallSiteInfoVec_.emplace_back(pc2CallSiteInfo); + pc2ConstInfoVec_.emplace_back(pc2ConstInfo); } bool LLVMStackMapParser::CalculateStackMap(std::unique_ptr stackMapAddr) { - stackMapAddr_ = std::move(stackMapAddr); - if (!stackMapAddr_) { - COMPILER_LOG(ERROR) << "stackMapAddr_ nullptr error ! "; + if (!stackMapAddr) { + COMPILER_LOG(ERROR) << "stackMapAddr nullptr error ! "; return false; } - dataInfo_ = std::make_unique(std::move(stackMapAddr_)); + dataInfo_ = std::make_unique(std::move(stackMapAddr)); llvmStackMap_.head = dataInfo_->Read(); uint32_t numFunctions, numConstants, numRecords; numFunctions = dataInfo_->Read(); @@ -288,9 +303,56 @@ bool LLVMStackMapParser::CalculateStackMap(std::unique_ptr stackMapA COMPILER_OPTIONAL_LOG(DEBUG) << std::dec << i << "th function " << std::hex << hostAddr << " ---> " << deviceAddr; } - pc2CallSiteInfo_.clear(); CalcCallSite(); - pc2CallSiteInfoVec_.push_back(pc2CallSiteInfo_); return true; } + +void LLVMStackMapParser::CalculateFuncFpDelta(Func2FpDelta info) +{ + bool find = std::find(fun2FpDelta_.begin(), fun2FpDelta_.end(), info) == fun2FpDelta_.end(); + if (!info.empty() && find) { + fun2FpDelta_.emplace_back(info); + } + for (auto &it: info) { + funAddr_.insert(it.first); + } +} + +int LLVMStackMapParser::FindFpDelta(uintptr_t funcAddr, uintptr_t callsitePc) const +{ + int delta = 0; + // next optimization can be performed via sorted/map. + for (auto &info: fun2FpDelta_) { + if (info.find(funcAddr) != info.end()) { + delta = info.at(funcAddr).first; + int funcSize = info.at(funcAddr).second; + if (callsitePc <= funcAddr + funcSize && callsitePc >= funcAddr) { + return delta; + } + } + } + return delta; +} + +int LLVMStackMapParser::GetFuncFpDelta(uintptr_t callsitePc) const +{ + int delta = 0; + auto itupper = funAddr_.upper_bound(callsitePc); + if (itupper != funAddr_.end()) { // find first element >= callsitePc + --itupper; + // callsitePC may jscall or entry, thus not existed in funAddr_ + if ((itupper == funAddr_.end()) || (*itupper > callsitePc)) { + return delta; + } + delta = FindFpDelta(*itupper, callsitePc); + } else { + auto rit = funAddr_.crbegin(); // find last element + // callsitePC may jscall or entry, thus not existed in funAddr_ + if ((rit == funAddr_.crend()) || (*rit > callsitePc)) { + return delta; + } + delta = FindFpDelta(*rit, callsitePc); + } + return delta; +} } // namespace panda::ecmascript::kungfu diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.h b/ecmascript/compiler/llvm/llvm_stackmap_parser.h index 9bad3bf8e0..3e3b904613 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.h +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.h @@ -32,6 +32,10 @@ using DwarfRegAndOffsetType = std::pair; using CallSiteInfo = std::vector; using Fun2InfoType = std::pair; using Pc2CallSiteInfo = std::unordered_map; +using FpDelta = std::pair; +using Func2FpDelta = std::unordered_map; // value: fpDelta & funcSize +using ConstInfo = std::vector; +using Pc2ConstInfo = std::unordered_map; struct Header { uint8_t stackmapversion; // Stack Map Version (current version is 3) @@ -89,6 +93,7 @@ struct LocationTy { CONSTANT = 4, CONSTANTNDEX = 5, }; + static constexpr int CONSTANT_FIRST_ELEMENT_INDEX = 3; Kind location; uint8_t Reserved_0; uint16_t LocationSize; @@ -211,35 +216,51 @@ public: return enableLog_; } + void PUBLIC_API CalculateFuncFpDelta(Func2FpDelta info); + int PUBLIC_API GetFuncFpDelta(uintptr_t callsitePc) const; + ConstInfo GetConstInfo(uintptr_t callsite) + { + // next optimization can be performed via sorted/map to accelerate the search + for (auto &pc2ConstInfo : pc2ConstInfoVec_) { + auto it = pc2ConstInfo.find(callsite); + if (it != pc2ConstInfo.end()) { + return pc2ConstInfo[callsite]; + } + } + return {}; + } + private: explicit LLVMStackMapParser(bool enableLog) { - stackMapAddr_ = nullptr; - pc2CallSiteInfo_.clear(); pc2CallSiteInfoVec_.clear(); dataInfo_ = nullptr; enableLog_ = enableLog; + funAddr_.clear(); + fun2FpDelta_.clear(); + pc2ConstInfoVec_.clear(); } ~LLVMStackMapParser() { - if (stackMapAddr_) { - stackMapAddr_.release(); - } - pc2CallSiteInfo_.clear(); pc2CallSiteInfoVec_.clear(); dataInfo_ = nullptr; + funAddr_.clear(); + fun2FpDelta_.clear(); + pc2ConstInfoVec_.clear(); } void CalcCallSite(); bool IsDeriveredPointer(int callsitetime) const; void PrintCallSiteInfo(const CallSiteInfo *infos, OptimizedLeaveFrame *frame) const; - void PrintCallSiteInfo(const CallSiteInfo *infos, uintptr_t *fp) const; + void PrintCallSiteInfo(const CallSiteInfo *infos, uintptr_t *fp, uintptr_t callSiteAddr) const; + int FindFpDelta(uintptr_t funcAddr, uintptr_t callsitePc) const; - std::unique_ptr stackMapAddr_; struct LLVMStackMap llvmStackMap_; - Pc2CallSiteInfo pc2CallSiteInfo_; std::vector pc2CallSiteInfoVec_; [[maybe_unused]] std::unique_ptr dataInfo_; bool enableLog_ {false}; + std::set funAddr_; + std::vector fun2FpDelta_; + std::vector pc2ConstInfoVec_; }; } // namespace panda::ecmascript::kungfu #endif // ECMASCRIPT_COMPILER_LLVM_LLVMSTACKPARSE_H \ No newline at end of file diff --git a/ecmascript/compiler/llvm_codegen.cpp b/ecmascript/compiler/llvm_codegen.cpp index 1f18ce680f..8d33f378a2 100644 --- a/ecmascript/compiler/llvm_codegen.cpp +++ b/ecmascript/compiler/llvm_codegen.cpp @@ -87,6 +87,7 @@ void LLVMIRGeneratorImpl::GenerateCode(Circuit *circuit, const ControlFlowGraph const panda::ecmascript::JSMethod *method) { auto function = module_->AddFunc(method); + circuit->SetFrameType(FrameType::OPTIMIZED_JS_FUNCTION_FRAME); LLVMIRBuilder builder(&graph, circuit, module_, function, cfg, CallSignature::CallConv::WebKitJSCallConv, enableLog_); builder.Build(); @@ -248,7 +249,26 @@ static const char *SymbolLookupCallback([[maybe_unused]] void *disInfo, [[maybe_ return nullptr; } -void LLVMAssembler::Disassemble(const std::map &addr2name, const CompilerLog &log) const +int LLVMAssembler::GetFpDeltaPrevFramSp(LLVMValueRef fn, const CompilerLog &log) +{ + int fpToCallerSpDelta = 0; + const char attrKey[] = "fpToCallerSpDelta"; // this key must consistent with llvm backend. + LLVMAttributeRef attrirbuteRef = LLVMGetStringAttributeAtIndex(fn, + llvm::AttributeList::FunctionIndex, attrKey, strlen(attrKey)); + if (attrirbuteRef) { + llvm::Attribute attr = llvm::unwrap(attrirbuteRef); + auto value = attr.getValueAsString().data(); + fpToCallerSpDelta = atoi(value); + if (log.IsAlwaysEnabled()) { + size_t length; + COMPILER_LOG(INFO) << " funcName: " << LLVMGetValueName2(fn, &length) << " fpToCallerSpDelta:" + << fpToCallerSpDelta; + } + } + return fpToCallerSpDelta; +} + +void LLVMAssembler::Disassemble(const std::map &addr2name, const CompilerLog &log) const { LLVMDisasmContextRef dcr = LLVMCreateDisasm(LLVMGetTarget(module_), nullptr, 0, nullptr, SymbolLookupCallback); bool logFlag = false; diff --git a/ecmascript/compiler/llvm_codegen.h b/ecmascript/compiler/llvm_codegen.h index e2e3c71b94..52fb8ae988 100644 --- a/ecmascript/compiler/llvm_codegen.h +++ b/ecmascript/compiler/llvm_codegen.h @@ -194,7 +194,8 @@ public: { return engine_; } - void Disassemble(const std::map &addr2name, const CompilerLog &log) const; + void Disassemble(const std::map &addr2name, const CompilerLog &log) const; + static int GetFpDeltaPrevFramSp(LLVMValueRef fn, const CompilerLog &log); static void Disassemble(uint8_t *buf, size_t size); uintptr_t GetStackMapsSection() const { diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 25cbf8783b..8dd878d109 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -371,10 +371,14 @@ void LLVMIRBuilder::GenPrologue([[maybe_unused]] LLVMModuleRef &module, LLVMBuil LLVMValueRef addr = LLVMBuildIntToPtr(builder, frameTypeSlotAddr, LLVMPointerType(slotType_, 0), "frameType.Addr"); + int reservedSlotsSize = slotSize_ * static_cast(ReservedSlots::OPTIMIZED_RESERVED_SLOT); if (frameType == panda::ecmascript::FrameType::OPTIMIZED_FRAME) { - LLVMAddTargetDependentFunctionAttr(function_, "js-stub-call", "0"); - } else if (frameType == panda::ecmascript::FrameType::OPTIMIZED_ENTRY_FRAME) { - LLVMAddTargetDependentFunctionAttr(function_, "js-stub-call", "1"); + LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots", + std::to_string(reservedSlotsSize).c_str()); + } else if (frameType == panda::ecmascript::FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { + reservedSlotsSize = slotSize_ * static_cast(ReservedSlots::OPTIMIZED_JS_FUNCTION_RESERVED_SLOT); + LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots", + std::to_string(reservedSlotsSize).c_str()); } else { COMPILER_OPTIONAL_LOG(FATAL) << "frameType interpret type error !"; ASSERT_PRINT(static_cast(frameType), "is not support !"); @@ -629,56 +633,6 @@ LLVMValueRef LLVMIRBuilder::GetCurrentSP() return spValue; } -void LLVMIRBuilder::SaveCurrentSP() -{ - if (compCfg_->Is64Bit()) { - LLVMValueRef llvmFpAddr = CallingFp(module_, builder_, false); - LLVMValueRef frameAddr = LLVMBuildPtrToInt(builder_, llvmFpAddr, slotType_, "cast_int_t"); - auto callSiteSpOffset = IsInterpreted() ? - AsmInterpretedFrame::GetCallSiteFpToSpDelta(compCfg_->Is32Bit()) : - OptimizedFrame::GetCallSiteFpToSpDelta(compCfg_->Is32Bit()); - LLVMValueRef frameSpSlotAddr = LLVMBuildSub(builder_, frameAddr, LLVMConstInt(slotType_, - callSiteSpOffset, false), ""); - LLVMValueRef addr = LLVMBuildIntToPtr(builder_, frameSpSlotAddr, - LLVMPointerType(slotType_, 0), "frameCallSiteSP.Addr"); - LLVMMetadataRef meta; - if (compCfg_->IsAmd64()) { - meta = LLVMMDStringInContext2(context_, "rsp", 4); // 4 : 4 means len of "rsp" - } else { - meta = LLVMMDStringInContext2(context_, "sp", 3); // 3 : 3 means len of "sp" - } - LLVMMetadataRef metadataNode = LLVMMDNodeInContext2(context_, &meta, 1); - LLVMValueRef spValue = ReadRegister(module_, builder_, metadataNode); - LLVMBuildStore(builder_, spValue, addr); - } -} - -LLVMValueRef LLVMIRBuilder::GetCurrentSPFrameAddr() -{ - LLVMValueRef glue = LLVMGetParam(function_, 0); - LLVMTypeRef glueType = LLVMTypeOf(glue); - LLVMValueRef rtoffset = LLVMConstInt(glueType, - JSThread::GlueData::GetCurrentFrameOffset(compCfg_->Is32Bit()), - 0); - LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, ""); - return rtbaseoffset; -} - -LLVMValueRef LLVMIRBuilder::GetCurrentSPFrame() -{ - LLVMValueRef addr = GetCurrentSPFrameAddr(); - LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, addr, LLVMPointerType(slotType_, 0), ""); - LLVMValueRef currentSpFrame = LLVMBuildLoad(builder_, rtbaseAddr, ""); - return currentSpFrame; -} - -void LLVMIRBuilder::SetCurrentSPFrame(LLVMValueRef sp) -{ - LLVMValueRef addr = GetCurrentSPFrameAddr(); - LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, addr, LLVMPointerType(slotType_, 0), ""); - LLVMBuildStore(builder_, sp, rtbaseAddr); -} - LLVMValueRef LLVMIRBuilder::GetCurrentFrameType(LLVMValueRef currentSpFrameAddr) { LLVMValueRef tmp = LLVMBuildSub(builder_, currentSpFrameAddr, LLVMConstInt(slotType_, slotSize_, 1), ""); @@ -749,9 +703,6 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector &inList, GateRef gateTmp = inList[paraIdx]; params.push_back(gate2LValue_[gateTmp]); } - if (op == OpCode::CALL) { - SaveCurrentSP(); - } LLVMValueRef call = LLVMBuildCall(builder_, callee, params.data(), inList.size() - firstArg + extraParameterCnt, ""); SetCallConvAttr(calleeDescriptor, call); diff --git a/ecmascript/compiler/llvm_ir_builder.h b/ecmascript/compiler/llvm_ir_builder.h index e4a6b2ad1c..282a1f6ed9 100644 --- a/ecmascript/compiler/llvm_ir_builder.h +++ b/ecmascript/compiler/llvm_ir_builder.h @@ -124,12 +124,18 @@ public: void SetFunction(size_t index, LLVMValueRef func) { - funcIndexMap_[index] = func; + funcIndexMap_.emplace_back(std::make_pair(index, func)); } LLVMValueRef GetFunction(size_t index) { - return funcIndexMap_.at(index); + // next optimization can be performed + for (auto &it: funcIndexMap_) { + if (it.first == index) { + return it.second; + } + } + return nullptr; } size_t GetFuncCount() const @@ -166,7 +172,7 @@ private: // index: // stub scenario - sequence of function adding to llvmModule // aot scenario - method Id of function generated by panda files - std::map funcIndexMap_; + std::vector> funcIndexMap_; std::vector callSigns_; LLVMModuleRef module_; CompilationConfig cfg_; @@ -245,7 +251,6 @@ private: void LinkToLLVMCfg(int bbId, const OperandsVector &predecessors); BasicBlock *EnsureBB(int id); LLVMValueRef CallingFp(LLVMModuleRef &module, LLVMBuilderRef &builder, bool isCaller); - void SaveCurrentSP(); LLVMValueRef GetCurrentSP(); LLVMValueRef ReadRegister(LLVMModuleRef &module, LLVMBuilderRef &builder, LLVMMetadataRef meta); @@ -276,9 +281,6 @@ private: LLVMValueRef VectorAdd(LLVMValueRef e1Value, LLVMValueRef e2Value, LLVMTypeRef rep); LLVMValueRef CanonicalizeToInt(LLVMValueRef value); LLVMValueRef CanonicalizeToPtr(LLVMValueRef value); - LLVMValueRef GetCurrentSPFrame(); - LLVMValueRef GetCurrentSPFrameAddr(); - void SetCurrentSPFrame(LLVMValueRef sp); LLVMValueRef GetCurrentFrameType(LLVMValueRef currentSpFrameAddr); bool IsGCRelated(GateType typeCode) const; void SetFunctionCallConv(); diff --git a/ecmascript/compiler/tests/BUILD.gn b/ecmascript/compiler/tests/BUILD.gn index fe09acf0cf..42a8c571fc 100644 --- a/ecmascript/compiler/tests/BUILD.gn +++ b/ecmascript/compiler/tests/BUILD.gn @@ -18,8 +18,8 @@ import("//build/test.gni") config("include_llvm_config") { if (compile_llvm_online) { include_dirs = [ - "//third_party/llvm-project/build/include", - "//third_party/llvm-project/llvm/include/", + "//third_party/third_party_llvm-project/build/include", + "//third_party/third_party_llvm-project/llvm/include/", ] } else { include_dirs = [ @@ -46,7 +46,7 @@ host_unittest_action("StubTest") { ] if (compile_llvm_online) { - lib_dirs = [ "//third_party/llvm-project/build/lib" ] + lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] } else { lib_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/build/lib" ] @@ -135,7 +135,7 @@ host_unittest_action("AssemblerTest") { ] if (compile_llvm_online) { - lib_dirs = [ "//third_party/llvm-project/build/lib" ] + lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] } else { lib_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/build/lib" ] diff --git a/ecmascript/compiler/tests/stub_tests.cpp b/ecmascript/compiler/tests/stub_tests.cpp index 70a3db5f45..a0cc408fef 100644 --- a/ecmascript/compiler/tests/stub_tests.cpp +++ b/ecmascript/compiler/tests/stub_tests.cpp @@ -555,7 +555,8 @@ HWTEST_F_L0(StubTest, JSEntryTest) /* implement stub1 */ LLVMValueRef stub1 = LLVMAddFunction(module, "stub1", LLVMFunctionType(LLVMInt64Type(), paramTys0, 1, 0)); LLVMAddTargetDependentFunctionAttr(stub1, "frame-pointer", "all"); - LLVMAddTargetDependentFunctionAttr(stub1, "js-stub-call", "1"); + int reservedSlotsSize = sizeof(uint64_t) * static_cast(ReservedSlots::OPTIMIZED_ENTRY_RESERVED_SLOT); + LLVMAddTargetDependentFunctionAttr(stub1, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); LLVMBasicBlockRef entryBb = LLVMAppendBasicBlock(stub1, "entry"); LLVMPositionBuilderAtEnd(builder, entryBb); @@ -593,7 +594,8 @@ HWTEST_F_L0(StubTest, JSEntryTest) /* implement stub2 call stub3 */ LLVMValueRef stub2 = LLVMAddFunction(module, "stub2", LLVMFunctionType(LLVMInt64Type(), paramTys0, 1, 0)); LLVMAddTargetDependentFunctionAttr(stub2, "frame-pointer", "all"); - LLVMAddTargetDependentFunctionAttr(stub2, "js-stub-call", "1"); + int reservedSlotsSize = sizeof(uint64_t) * static_cast(ReservedSlots::OPTIMIZED_ENTRY_RESERVED_SLOT); + LLVMAddTargetDependentFunctionAttr(stub2, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); entryBb = LLVMAppendBasicBlock(stub2, "entry"); LLVMPositionBuilderAtEnd(builder, entryBb); @@ -623,7 +625,8 @@ HWTEST_F_L0(StubTest, JSEntryTest) /* implement stub3 call RuntimeFunc2 */ LLVMAddTargetDependentFunctionAttr(stub3, "frame-pointer", "all"); - LLVMAddTargetDependentFunctionAttr(stub3, "js-stub-call", "0"); + int reservedSlotsSize = sizeof(uint64_t) * static_cast(ReservedSlots::OPTIMIZED_RESERVED_SLOT); + LLVMAddTargetDependentFunctionAttr(stub3, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); entryBb = LLVMAppendBasicBlock(stub3, "entry"); LLVMPositionBuilderAtEnd(builder, entryBb); @@ -686,7 +689,8 @@ HWTEST_F_L0(StubTest, Prologue) /* implement main implement */ LLVMValueRef func = LLVMAddFunction(module, "main", LLVMFunctionType(LLVMInt64Type(), nullptr, 0, 0)); LLVMAddTargetDependentFunctionAttr(func, "frame-pointer", "all"); - LLVMAddTargetDependentFunctionAttr(func, "js-stub-call", "1"); + int reservedSlotsSize = sizeof(uint64_t) * static_cast(ReservedSlots::OPTIMIZED_ENTRY_RESERVED_SLOT); + LLVMAddTargetDependentFunctionAttr(func, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); LLVMBasicBlockRef entryBb = LLVMAppendBasicBlock(func, "entry"); LLVMPositionBuilderAtEnd(builder, entryBb); @@ -695,7 +699,8 @@ HWTEST_F_L0(StubTest, Prologue) LLVMBuilderRef builderBar = LLVMCreateBuilder(); LLVMValueRef bar = LLVMAddFunction(module, "bar", LLVMFunctionType(LLVMInt64Type(), paramTys0, 2, 0)); LLVMAddTargetDependentFunctionAttr(bar, "frame-pointer", "all"); - LLVMAddTargetDependentFunctionAttr(bar, "js-stub-call", "0"); + int reservedSlotsSize = sizeof(uint64_t) * static_cast(ReservedSlots::OPTIMIZED_RESERVED_SLOT); + LLVMAddTargetDependentFunctionAttr(bar, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); LLVMBasicBlockRef entryBbBar = LLVMAppendBasicBlock(bar, "entry"); LLVMPositionBuilderAtEnd(builderBar, entryBbBar); LLVMValueRef value0Bar = LLVMGetParam(bar, 0); @@ -744,7 +749,8 @@ HWTEST_F_L0(StubTest, CEntryFp) /* implement main call RuntimeFunc */ LLVMValueRef func = LLVMAddFunction(module, "main", LLVMFunctionType(LLVMInt64Type(), paramTys0, 1, 0)); LLVMAddTargetDependentFunctionAttr(func, "frame-pointer", "all"); - LLVMAddTargetDependentFunctionAttr(func, "js-stub-call", "1"); + int reservedSlotsSize = sizeof(uint64_t) * static_cast(ReservedSlots::OPTIMIZED_ENTRY_RESERVED_SLOT); + LLVMAddTargetDependentFunctionAttr(func, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); LLVMBasicBlockRef entryBb = LLVMAppendBasicBlock(func, "entry"); LLVMPositionBuilderAtEnd(builder, entryBb); diff --git a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp index b8a3bfc388..6947eb4d66 100644 --- a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp +++ b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp @@ -236,7 +236,7 @@ void AssemblerStubs::OptimizedCallOptimized(ExtendedAssembler *assembler) __ SaveFpAndLr(); // Construct frame Register frameType(X5); - __ Mov(frameType, Immediate(static_cast(FrameType::OPTIMIZED_FRAME))); + __ Mov(frameType, Immediate(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME))); __ Str(frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // callee save @@ -375,32 +375,33 @@ void AssemblerStubs::CallBuiltinTrampoline(ExtendedAssembler *assembler) // uint64_t JSCall(uintptr_t glue, uint32_t argc, JSTaggedType calltarget, JSTaggedType new, JSTaggedType this, ...) // webkit_jscc calling convention call js function() -// Input: %x0 - glue -// stack layout: sp + N*8 argvN -// ........ -// sp + 24: argc -// sp + 16: this -// sp + 8: new -// sp: jsfunc -// +--------------------------+ -// | argv[argc-1] | -// +--------------------------+ -// | .......... | -// +--------------------------+ -// | argv[1] | -// +--------------------------+ -// | argv[0] | -// +--------------------------+ --- -// | argc | ^ -// |--------------------------| Fixed -// | RuntimeId | OptimizedFrame -// |--------------------------| | -// | returnAddr | | -// |--------------------------| | -// | callsiteFp | | -// |--------------------------| | -// | frameType | v -// +--------------------------+ --- +// %x0 - glue +// stack layout +// sp + N*8 argvN +// ........ +// sp + 24: argc +// sp + 16: this +// sp + 8: new +// sp: jsfunc +// +--------------------------+ +// | ... | +// +--------------------------+ +// | arg0 | +// +--------------------------+ +// | this | +// +--------------------------+ +// | new | +// +--------------------------+ --- +// | jsfunction | ^ +// |--------------------------| Fixed +// | argc | OptimizedFrame +// |--------------------------| | +// | returnAddr | | +// |--------------------------| | +// | callsiteFp | | +// |--------------------------| | +// | frameType | v +// +--------------------------+ --- void AssemblerStubs::JSCall(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(JSCall)); @@ -499,7 +500,7 @@ void AssemblerStubs::JSCallBody(ExtendedAssembler *assembler, Register jsfunc) // construct frame Register frameType(X5); Register fp(X29); - __ Mov(frameType, Immediate(static_cast(FrameType::OPTIMIZED_FRAME))); + __ Mov(frameType, Immediate(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME))); __ Str(frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); Register argVEnd(X4); __ Add(argVEnd, fp, Immediate(GetStackArgOffSetToFp(0))); @@ -594,7 +595,7 @@ void AssemblerStubs::JSCallBody(ExtendedAssembler *assembler, Register jsfunc) Register frameType(X6); Register taggedMessageId(X5); __ SaveFpAndLr(); - __ Mov(frameType, Immediate(static_cast(FrameType::OPTIMIZED_FRAME))); + __ Mov(frameType, Immediate(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME))); __ Mov(taggedMessageId, Immediate(JSTaggedValue(GET_MESSAGE_STRING_ID(NonCallable)).GetRawData())); // 2 : 2 means pair @@ -1953,4 +1954,4 @@ void AssemblerStubs::PushArgsSlowPath(ExtendedAssembler *assembler, Register &gl PushArgsFastPath(assembler, glueRegister, argcRegister, argvRegister, callTargetRegister, methodRegister, prevSpRegister, fpRegister, callFieldRegister); } -} // panda::ecmascript::aarch64 \ No newline at end of file +} // panda::ecmascript::aarch64 diff --git a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp index a766e57e39..c9dbf76a76 100644 --- a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp +++ b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp @@ -193,7 +193,7 @@ void AssemblerStubsX64::OptimizedCallOptimized(ExtendedAssembler *assembler) Label lPopFrame1; __ Pushq(rbp); __ Movq(rsp, rbp); - __ Pushq(static_cast(FrameType::OPTIMIZED_FRAME)); + __ Pushq(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)); // callee save __ Pushq(r14); __ Pushq(rbx); @@ -402,7 +402,7 @@ void AssemblerStubsX64::JSCallWithArgV(ExtendedAssembler *assembler) { __ Pushq(rbp); __ Movq(rsp, rbp); // set frame pointer - __ Pushq(static_cast(FrameType::OPTIMIZED_FRAME)); // set frame type + __ Pushq(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)); // set frame type __ Movq(MessageString::Message_NonCallable, rax); __ Pushq(rax); // message id __ Pushq(1); // argc @@ -473,7 +473,7 @@ void AssemblerStubsX64::JSCallWithArgV(ExtendedAssembler *assembler) { __ Pushq(rbp); __ Movq(rsp, rbp); - __ Pushq(static_cast(FrameType::OPTIMIZED_FRAME)); + __ Pushq(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)); __ Pushq(r10); // callee save __ Movq(rsp, rdx); __ Addq(32, rdx); // 32: sp + 32 argv @@ -653,7 +653,7 @@ void AssemblerStubsX64::JSCall(ExtendedAssembler *assembler) { __ Pushq(rbp); __ Movq(rsp, rbp); // set frame pointer - __ Pushq(static_cast(FrameType::OPTIMIZED_FRAME)); // set frame type + __ Pushq(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)); // set frame type __ Movq(MessageString::Message_NonCallable, rax); __ Pushq(rax); // message id __ Pushq(1); // argc @@ -724,7 +724,7 @@ void AssemblerStubsX64::JSCall(ExtendedAssembler *assembler) { __ Pushq(rbp); __ Movq(rsp, rbp); - __ Pushq(static_cast(FrameType::OPTIMIZED_FRAME)); + __ Pushq(static_cast(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME)); __ Pushq(r10); // callee save __ Movq(rsp, rdx); __ Addq(32, rdx); // 32: sp + 32 argv diff --git a/ecmascript/file_loader.cpp b/ecmascript/file_loader.cpp index ef23df778f..29c047be15 100644 --- a/ecmascript/file_loader.cpp +++ b/ecmascript/file_loader.cpp @@ -105,6 +105,17 @@ bool StubModulePackInfo::Load(EcmaVM *vm, const std::string &filename) des_[i].GetHostCodeSecAddr(), startAddr); } } + for (auto &funcEntryDes : GetStubs()) { + auto codeAddr = funcEntryDes.codeAddr_; // offset + auto moduleIndex = funcEntryDes.moduleIndex_; + auto startAddr = des_[moduleIndex].GetDeviceCodeSecAddr(); + auto delta = funcEntryDes.fpDeltaPrevFramSp_; + uintptr_t funAddr = startAddr + codeAddr; + kungfu::Func2FpDelta fun2fpDelta; + auto funSize = funcEntryDes.funcSize_; + fun2fpDelta[funAddr] = std::make_pair(delta, funSize); + kungfu::LLVMStackMapParser::GetInstance().CalculateFuncFpDelta(fun2fpDelta); + } for (size_t i = 0; i < entries_.size(); i++) { auto des = des_[entries_[i].moduleIndex_]; entries_[i].codeAddr_ += des.GetDeviceCodeSecAddr(); @@ -184,6 +195,18 @@ bool AOTModulePackInfo::Load(EcmaVM *vm, const std::string &filename) des_[i].GetHostCodeSecAddr(), startAddr); } } + for (auto &funcEntryDes : GetStubs()) { + auto codeAddr = funcEntryDes.codeAddr_; // offset + auto moduleIndex = funcEntryDes.moduleIndex_; + auto delta = funcEntryDes.fpDeltaPrevFramSp_; + auto funSize = funcEntryDes.funcSize_; + auto startAddr = des_[moduleIndex].GetDeviceCodeSecAddr(); + uintptr_t funAddr = startAddr + codeAddr; + kungfu::Func2FpDelta fun2fpDelta; + fun2fpDelta[funAddr] = std::make_pair(delta, funSize); + kungfu::LLVMStackMapParser::GetInstance().CalculateFuncFpDelta(fun2fpDelta); + } + for (size_t i = 0; i < entries_.size(); i++) { auto des = des_[entries_[i].moduleIndex_]; entries_[i].codeAddr_ += des.GetDeviceCodeSecAddr(); diff --git a/ecmascript/file_loader.h b/ecmascript/file_loader.h index 3fa529ecfe..b9f5f3255e 100644 --- a/ecmascript/file_loader.h +++ b/ecmascript/file_loader.h @@ -95,6 +95,8 @@ public: CallSignature::TargetKind kind_; uint32_t indexInKind_; uint32_t moduleIndex_; + int fpDeltaPrevFramSp_; + uint32_t funcSize_; bool IsStub() const { return CallSignature::TargetKind::STUB_BEGIN <= kind_ && kind_ < CallSignature::TargetKind::STUB_END; @@ -154,13 +156,16 @@ public: entryNum_ = n; } - void AddStubEntry(CallSignature::TargetKind kind, int indexInKind, uint64_t offset, uint32_t moduleIndex) + void AddStubEntry(CallSignature::TargetKind kind, int indexInKind, uint64_t offset, + uint32_t moduleIndex, int delta, uint32_t size) { FuncEntryDes des; des.kind_ = kind; des.indexInKind_ = static_cast(indexInKind); des.codeAddr_ = offset; des.moduleIndex_ = moduleIndex; + des.fpDeltaPrevFramSp_ = delta; + des.funcSize_ = size; entries_.emplace_back(des); } diff --git a/ecmascript/frames.h b/ecmascript/frames.h index e51dba1ad3..e27d91ca54 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -237,17 +237,19 @@ namespace panda::ecmascript { enum class FrameType: uintptr_t { OPTIMIZED_FRAME = 0, OPTIMIZED_ENTRY_FRAME = 1, - LEAVE_FRAME = 2, - LEAVE_FRAME_WITH_ARGV = 3, - INTERPRETER_FRAME = 4, - ASM_INTERPRETER_FRAME = 5, - INTERPRETER_CONSTRUCTOR_FRAME = 6, - BUILTIN_FRAME = 7, - BUILTIN_FRAME_WITH_ARGV = 8, - BUILTIN_ENTRY_FRAME = 9, - INTERPRETER_FAST_NEW_FRAME = 10, - INTERPRETER_ENTRY_FRAME = 11, - ASM_INTERPRETER_ENTRY_FRAME = 12, + OPTIMIZED_JS_FUNCTION_FRAME = 2, + LEAVE_FRAME = 3, + LEAVE_FRAME_WITH_ARGV = 4, + INTERPRETER_FRAME = 5, + ASM_INTERPRETER_FRAME = 6, + INTERPRETER_CONSTRUCTOR_FRAME = 7, + BUILTIN_FRAME = 8, + BUILTIN_FRAME_WITH_ARGV = 9, + BUILTIN_ENTRY_FRAME = 10, + INTERPRETER_FAST_NEW_FRAME = 11, + INTERPRETER_ENTRY_FRAME = 12, + ASM_INTERPRETER_ENTRY_FRAME = 13, + OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME = 14, INTERPRETER_BEGIN = INTERPRETER_FRAME, INTERPRETER_END = INTERPRETER_FAST_NEW_FRAME, @@ -255,6 +257,12 @@ enum class FrameType: uintptr_t { BUILTIN_END = BUILTIN_ENTRY_FRAME, }; +enum class ReservedSlots: int { + OPTIMIZED_RESERVED_SLOT = 1, + OPTIMIZED_JS_FUNCTION_RESERVED_SLOT = 1, + OPTIMIZED_ENTRY_RESERVED_SLOT = 2, +}; + enum class JSCallMode : uintptr_t { CALL_ARG0 = 0, CALL_ARG1, @@ -273,13 +281,11 @@ enum class JSCallMode : uintptr_t { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) struct OptimizedFrame : public base::AlignedStruct { public: enum class Index : size_t { - CallSiteSpIndex = 0, - TypeIndex, + TypeIndex = 0, PrevFpIndex, NumOfMembers }; @@ -294,23 +300,84 @@ public: { return prevFp; } - inline uintptr_t GetCallSiteSp() const - { - return callSiteSp; - } - static int32_t GetCallSiteFpToSpDelta(bool isArch32) - { - auto prevFpOffset = GetOffset(Index::PrevFpIndex)>(isArch32); - auto callSiteSpOffset = GetOffset(Index::CallSiteSpIndex)>(isArch32); - return prevFpOffset - callSiteSpOffset; - } - - alignas(EAS) uintptr_t callSiteSp {0}; alignas(EAS) FrameType type {0}; alignas(EAS) JSTaggedType *prevFp {nullptr}; }; STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64); +// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) +struct OptimizedJSFunctionArgConfigFrame : public base::AlignedStruct { +public: + enum class Index : size_t { + TypeIndex = 0, + PrevFpIndex, + NumOfMembers + }; + static_assert(static_cast(Index::NumOfMembers) == NumOfTypes); + + static OptimizedJSFunctionArgConfigFrame* GetFrameFromSp(const JSTaggedType *sp) + { + return reinterpret_cast(reinterpret_cast(sp) + - MEMBER_OFFSET(OptimizedJSFunctionArgConfigFrame, prevFp)); + } + inline JSTaggedType* GetPrevFrameFp() + { + return prevFp; + } + alignas(EAS) FrameType type {0}; + alignas(EAS) JSTaggedType *prevFp {nullptr}; +}; +STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionArgConfigFrame), + OptimizedJSFunctionArgConfigFrame::SizeArch32, OptimizedJSFunctionArgConfigFrame::SizeArch64); + +// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) +struct OptimizedJSFunctionFrame : public base::AlignedStruct { +public: + enum class Index : size_t { + TypeIndex = 0, + PrevFpIndex, + ReturnAddrIndex, + NumOfMembers + }; + static_assert(static_cast(Index::NumOfMembers) == NumOfTypes); + + static OptimizedJSFunctionFrame* GetFrameFromSp(const JSTaggedType *sp) + { + return reinterpret_cast(reinterpret_cast(sp) + - MEMBER_OFFSET(OptimizedJSFunctionFrame, prevFp)); + } + inline JSTaggedType* GetPrevFrameFp() + { + return prevFp; + } + uintptr_t* ComputePrevFrameSp(const JSTaggedType *sp, int delta) + { + uintptr_t *preFrameSp = reinterpret_cast(const_cast(sp)) + + delta / sizeof(uintptr_t); + return preFrameSp; + } + JSTaggedType* GetArgv(uintptr_t *preFrameSp) + { + return reinterpret_cast(preFrameSp + sizeof(uint64_t) / sizeof(uintptr_t)); + } + // dynamic callee saveregisters for x86-64 + alignas(EAS) FrameType type {0}; + alignas(EAS) JSTaggedType *prevFp {nullptr}; + alignas(EAS) uintptr_t returnAddr {0}; + // dynamic callee saveregisters for arm64 + // argc + // argv[0] + // argv[1] + // ... argv[n - 1] +}; +STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedJSFunctionFrame), OptimizedJSFunctionFrame::SizeArch32, + OptimizedJSFunctionFrame::SizeArch64); + struct OptimizedEntryFrame { public: OptimizedEntryFrame() = default; @@ -427,7 +494,7 @@ struct AsmInterpretedFrame : public base::AlignedStruct(Index::CallSizeOrCallSiteSpIndex)>(isArch32); + return GetOffset(Index::CallSizeIndex)>(isArch32); } static size_t GetFunctionOffset(bool isArch32) @@ -491,18 +558,6 @@ struct AsmInterpretedFrame : public base::AlignedStruct(Index::CallSizeOrCallSiteSpIndex)>(isArch32); - return fpOffset - callSiteSpOffset; - } - static uint32_t NumOfMembers() { return sizeof(AsmInterpretedFrame) / JSTaggedValue::TaggedTypeSize(); @@ -511,7 +566,7 @@ struct AsmInterpretedFrame : public base::AlignedStructGetPrevFrameFp(); break; } + case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME: { + auto frame = OptimizedJSFunctionArgConfigFrame::GetFrameFromSp(sp_); + sp_ = frame->GetPrevFrameFp(); + break; + } + case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: { + auto frame = OptimizedJSFunctionFrame::GetFrameFromSp(sp_); + sp_ = frame->GetPrevFrameFp(); + break; + } case FrameType::OPTIMIZED_ENTRY_FRAME: { auto frame = OptimizedEntryFrame::GetFrameFromSp(sp_); sp_ = frame->GetPrevFrameFp(); @@ -95,7 +105,7 @@ void FrameHandler::PrevFrame() } } -uintptr_t FrameHandler::GetPrevFrameCallSiteSp(const JSTaggedType *sp) +uintptr_t FrameHandler::GetPrevFrameCallSiteSp(const JSTaggedType *sp, uintptr_t callSiteAddr) { if (sp == nullptr) { return 0U; @@ -119,11 +129,11 @@ uintptr_t FrameHandler::GetPrevFrameCallSiteSp(const JSTaggedType *sp) auto frame = BuiltinFrame::GetFrameFromSp(sp); return frame->GetCallSiteSp(); } - case FrameType::OPTIMIZED_FRAME: { - auto frame = OptimizedFrame::GetFrameFromSp(sp); - sp = frame->GetPrevFrameFp(); - type = GetFrameType(sp); - break; + case FrameType::OPTIMIZED_FRAME: + case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: { + auto callSiteSp = reinterpret_cast(sp) + + kungfu::LLVMStackMapParser::GetInstance().GetFuncFpDelta(callSiteAddr); + return callSiteSp; } case FrameType::BUILTIN_ENTRY_FRAME: case FrameType::ASM_INTERPRETER_FRAME: @@ -138,14 +148,6 @@ uintptr_t FrameHandler::GetPrevFrameCallSiteSp(const JSTaggedType *sp) UNREACHABLE(); } } - - if (type == FrameType::OPTIMIZED_FRAME) { - auto frame = OptimizedFrame::GetFrameFromSp(sp); - return frame->GetCallSiteSp(); - } - - auto frame = AsmInterpretedFrame::GetFrameFromSp(sp); - return frame->GetCallSiteSp(); } ARK_INLINE void FrameHandler::AdvanceToInterpretedFrame() @@ -487,10 +489,10 @@ ARK_INLINE void FrameHandler::InterpretedEntryFrameIterate(const JSTaggedType *s } ARK_INLINE void FrameHandler::OptimizedFrameIterate(const JSTaggedType *sp, - const RootVisitor &v0, - [[maybe_unused]] const RootRangeVisitor &v1, - ChunkMap *derivedPointers, - bool isVerifying) const + const RootVisitor &v0, + [[maybe_unused]] const RootRangeVisitor &v1, + ChunkMap *derivedPointers, + bool isVerifying) const { std::set slotAddrs; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) @@ -511,14 +513,53 @@ ARK_INLINE void FrameHandler::OptimizedFrameIterate(const JSTaggedType *sp, } } +ARK_INLINE void FrameHandler::OptimizedJSFunctionFrameIterate(const JSTaggedType *sp, + const RootVisitor &v0, + [[maybe_unused]] const RootRangeVisitor &v1, + ChunkMap *derivedPointers, + bool isVerifying) +{ + OptimizedJSFunctionFrame *frame = OptimizedJSFunctionFrame::GetFrameFromSp(sp); + auto currentPc = optimizedReturnAddr_; + optimizedReturnAddr_ = frame->returnAddr; + int delta = kungfu::LLVMStackMapParser::GetInstance().GetFuncFpDelta(currentPc); + uintptr_t *preFrameSp = frame->ComputePrevFrameSp(sp, delta); + + auto argc = *(reinterpret_cast(preFrameSp)); + JSTaggedType *argv = frame->GetArgv(preFrameSp); + if (argc > 0) { + uintptr_t start = ToUintPtr(argv); // argv + uintptr_t end = ToUintPtr(argv + argc); + v1(Root::ROOT_FRAME, ObjectSlot(start), ObjectSlot(end)); + } + std::set slotAddrs; + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + auto returnAddr = + reinterpret_cast(*(reinterpret_cast(const_cast(sp)) + 1)); + bool enableCompilerLog = thread_->GetEcmaVM()->GetJSOptions().WasSetlogCompiledMethods(); + bool ret = kungfu::LLVMStackMapParser::GetInstance(enableCompilerLog).CollectStackMapSlots( + returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying); + if (!ret) { +#ifndef NDEBUG + LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << returnAddr; +#endif + return; + } + + for (const auto &slot : slotAddrs) { + v0(Root::ROOT_FRAME, ObjectSlot(slot)); + } +} + ARK_INLINE void FrameHandler::OptimizedEntryFrameIterate(const JSTaggedType *sp, const RootVisitor &v0, [[maybe_unused]] const RootRangeVisitor &v1, ChunkMap *derivedPointers, - bool isVerifying) const + bool isVerifying) { std::set slotAddrs; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + optimizedReturnAddr_ = 0; auto returnAddr = reinterpret_cast(*(reinterpret_cast(const_cast(sp)) + 1)); bool enableCompilerLog = thread_->GetEcmaVM()->GetJSOptions().WasSetlogCompiledMethods(); bool ret = kungfu::LLVMStackMapParser::GetInstance(enableCompilerLog).CollectStackMapSlots( @@ -539,9 +580,10 @@ ARK_INLINE void FrameHandler::OptimizedLeaveFrameIterate(const JSTaggedType *sp, const RootVisitor &v0, [[maybe_unused]] const RootRangeVisitor &v1, ChunkMap *derivedPointers, - bool isVerifying) const + bool isVerifying) { OptimizedLeaveFrame *frame = OptimizedLeaveFrame::GetFrameFromSp(sp); + optimizedReturnAddr_ = frame->returnAddr; if (frame->argc > 0) { JSTaggedType *argv = reinterpret_cast(&frame->argc + 1); uintptr_t start = ToUintPtr(argv); // argv @@ -565,9 +607,10 @@ ARK_INLINE void FrameHandler::OptimizedWithArgvLeaveFrameIterate(const JSTaggedT const RootVisitor &v0, [[maybe_unused]] const RootRangeVisitor &v1, ChunkMap *derivedPointers, - bool isVerifying) const + bool isVerifying) { OptimizedLeaveFrame *frame = OptimizedLeaveFrame::GetFrameFromSp(sp); + optimizedReturnAddr_ = frame->returnAddr; if (frame->argc > 0) { uintptr_t* argvPtr = reinterpret_cast(&frame->argc + 1); JSTaggedType *argv = reinterpret_cast(*argvPtr); @@ -588,13 +631,13 @@ ARK_INLINE void FrameHandler::OptimizedWithArgvLeaveFrameIterate(const JSTaggedT } } -void FrameHandler::IterateRsp(const RootVisitor &v0, const RootRangeVisitor &v1) const +void FrameHandler::IterateRsp(const RootVisitor &v0, const RootRangeVisitor &v1) { JSTaggedType *current = const_cast(thread_->GetLastLeaveFrame()); IterateFrameChain(current, v0, v1); } -void FrameHandler::IterateSp(const RootVisitor &v0, const RootRangeVisitor &v1) const +void FrameHandler::IterateSp(const RootVisitor &v0, const RootRangeVisitor &v1) { JSTaggedType *current = const_cast(thread_->GetCurrentSPFrame()); while (current) { @@ -606,7 +649,7 @@ void FrameHandler::IterateSp(const RootVisitor &v0, const RootRangeVisitor &v1) } } -void FrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const +void FrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) { if (thread_->IsAsmInterpreter()) { IterateSp(v0, v1); @@ -624,7 +667,7 @@ void FrameHandler::Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) co IterateFrameChain(current, v0, v1); } -void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &v0, const RootRangeVisitor &v1) const +void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &v0, const RootRangeVisitor &v1) { ChunkMap *derivedPointers = thread_->GetEcmaVM()->GetHeap()->GetDerivedPointers(); bool isVerifying = false; @@ -638,10 +681,24 @@ void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &v0, switch (type) { case FrameType::OPTIMIZED_FRAME: { auto frame = OptimizedFrame::GetFrameFromSp(current); + auto prevFrame = frame->GetPrevFrameFp(); OptimizedFrameIterate(current, v0, v1, derivedPointers, isVerifying); + current = prevFrame; + break; + } + case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME: { + OptimizedJSFunctionFrame *frame = OptimizedJSFunctionFrame::GetFrameFromSp(current); + optimizedReturnAddr_ = frame->returnAddr; current = frame->GetPrevFrameFp(); break; } + case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: { + auto frame = OptimizedJSFunctionFrame::GetFrameFromSp(current); + auto prevFrame = frame->GetPrevFrameFp(); + OptimizedJSFunctionFrameIterate(current, v0, v1, derivedPointers, isVerifying); + current = prevFrame; + break; + } case FrameType::OPTIMIZED_ENTRY_FRAME: { auto frame = OptimizedEntryFrame::GetFrameFromSp(current); current = frame->GetPrevFrameFp(); diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index ff6dc64497..af50ccc82c 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -115,7 +115,7 @@ public: JSTaggedType *GetPrevInterpretedFrame(); // for llvm. - static uintptr_t GetPrevFrameCallSiteSp(const JSTaggedType *sp); + static uintptr_t GetPrevFrameCallSiteSp(const JSTaggedType *sp, uintptr_t callSiteAddr = 0); // for InterpretedFrame. JSTaggedValue GetVRegValue(size_t index) const; @@ -146,10 +146,10 @@ public: static JSTaggedType* GetInterpretedEntryFrameStart(const JSTaggedType *sp); // for Frame GC. - void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1) const; - void IterateFrameChain(JSTaggedType *start, const RootVisitor &v0, const RootRangeVisitor &v1) const; - void IterateRsp(const RootVisitor &v0, const RootRangeVisitor &v1) const; - void IterateSp(const RootVisitor &v0, const RootRangeVisitor &v1) const; + void Iterate(const RootVisitor &v0, const RootRangeVisitor &v1); + void IterateFrameChain(JSTaggedType *start, const RootVisitor &v0, const RootRangeVisitor &v1); + void IterateRsp(const RootVisitor &v0, const RootRangeVisitor &v1); + void IterateSp(const RootVisitor &v0, const RootRangeVisitor &v1); private: FrameType GetFrameType() const @@ -176,20 +176,24 @@ private: void OptimizedFrameIterate( const JSTaggedType *sp, const RootVisitor &v0, const RootRangeVisitor &v1, ChunkMap *derivedPointers, bool isVerifying) const; + void OptimizedJSFunctionFrameIterate( + const JSTaggedType *sp, const RootVisitor &v0, const RootRangeVisitor &v1, + ChunkMap *derivedPointers, bool isVerifying); void OptimizedEntryFrameIterate( const JSTaggedType *sp, const RootVisitor &v0, const RootRangeVisitor &v1, - ChunkMap *derivedPointers, bool isVerifying) const; + ChunkMap *derivedPointers, bool isVerifying); void OptimizedLeaveFrameIterate( const JSTaggedType *sp, const RootVisitor &v0, const RootRangeVisitor &v1, - ChunkMap *derivedPointers, bool isVerifying) const; + ChunkMap *derivedPointers, bool isVerifying); void OptimizedWithArgvLeaveFrameIterate( const JSTaggedType *sp, const RootVisitor &v0, const RootRangeVisitor &v1, - ChunkMap *derivedPointers, bool isVerifying) const; + ChunkMap *derivedPointers, bool isVerifying); private: JSTaggedType *sp_ {nullptr}; JSTaggedType *fp_ {nullptr}; const JSThread *thread_ {nullptr}; + uintptr_t optimizedReturnAddr_ {0}; }; class StackAssertScope { diff --git a/ecmascript/interpreter/interpreter_assembly.cpp b/ecmascript/interpreter/interpreter_assembly.cpp index 1aac89aa40..a70e67d3d8 100644 --- a/ecmascript/interpreter/interpreter_assembly.cpp +++ b/ecmascript/interpreter/interpreter_assembly.cpp @@ -98,8 +98,8 @@ using panda::ecmascript::kungfu::CommonStubCSigns; JSFunction* prevFunc = JSFunction::Cast(prevState->function.GetTaggedObject()); \ method = prevFunc->GetMethod(); \ hotnessCounter = static_cast(method->GetHotnessCounter()); \ - ASSERT(prevState->callSizeOrCallSiteSp == GetJumpSizeAfterCall(pc)); \ - DISPATCH_OFFSET(prevState->callSizeOrCallSiteSp); \ + ASSERT(prevState->callSize == GetJumpSizeAfterCall(pc)); \ + DISPATCH_OFFSET(prevState->callSize); \ } while (false) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) @@ -401,7 +401,7 @@ using panda::ecmascript::kungfu::CommonStubCSigns; INTERPRETER_GOTO_EXCEPTION_HANDLER(); \ } \ SAVE_PC(); \ - GET_ASM_FRAME(sp)->callSizeOrCallSiteSp = GetJumpSizeAfterCall(pc); \ + GET_ASM_FRAME(sp)->callSize = GetJumpSizeAfterCall(pc); \ AsmInterpretedFrame *state = GET_ASM_FRAME(newSp); \ state->base.prev = sp; \ state->base.type = FrameType::ASM_INTERPRETER_FRAME; \ @@ -2073,7 +2073,7 @@ void InterpreterAssembly::HandleNewObjDynRangePrefImm16V8( if (IsFastNewFrameEnter(ctorFunc, ctorMethod)) { SAVE_PC(); - GET_ASM_FRAME(sp)->callSizeOrCallSiteSp = GetJumpSizeAfterCall(pc); + GET_ASM_FRAME(sp)->callSize = GetJumpSizeAfterCall(pc); uint32_t numVregs = ctorMethod->GetNumVregsWithCallField(); uint32_t numDeclaredArgs = ctorFunc->IsBase() ? ctorMethod->GetNumArgsWithCallField() + 1 : // +1 for this @@ -2465,8 +2465,8 @@ void InterpreterAssembly::HandleSuspendGeneratorPrefV8V8( return; } - ASSERT(prevState->callSizeOrCallSiteSp == GetJumpSizeAfterCall(pc)); - DISPATCH_OFFSET(prevState->callSizeOrCallSiteSp); + ASSERT(prevState->callSize == GetJumpSizeAfterCall(pc)); + DISPATCH_OFFSET(prevState->callSize); } void InterpreterAssembly::HandleAsyncFunctionAwaitUncaughtPrefV8V8( diff --git a/ecmascript/js_thread.h b/ecmascript/js_thread.h index a618b41b3a..175b3fab55 100644 --- a/ecmascript/js_thread.h +++ b/ecmascript/js_thread.h @@ -609,7 +609,6 @@ private: bool gcState_ {false}; bool isAsmInterpreter_ {false}; VmThreadControl *vmThreadControl_ {nullptr}; - bool stableArrayElementsGuardians_ {true}; GlueData glueData_; diff --git a/ecmascript/stubs/runtime_stubs-inl.h b/ecmascript/stubs/runtime_stubs-inl.h index bb0685d34f..d07dccb713 100644 --- a/ecmascript/stubs/runtime_stubs-inl.h +++ b/ecmascript/stubs/runtime_stubs-inl.h @@ -18,6 +18,7 @@ #include "runtime_stubs.h" #include "ecmascript/builtins/builtins_regexp.h" +#include "ecmascript/compiler/llvm/llvm_stackmap_parser.h" #include "ecmascript/ecma_string_table.h" #include "ecmascript/global_dictionary-inl.h" #include "ecmascript/global_env.h" diff --git a/test/aottest/BUILD.gn b/test/aottest/BUILD.gn index 8c338265f3..f481ae6064 100644 --- a/test/aottest/BUILD.gn +++ b/test/aottest/BUILD.gn @@ -59,7 +59,8 @@ group("ark_aot_test") { "stownbyname:stownbynameAotAction", "stownbynamewithnameset:stownbynamewithnamesetAotAction", "stownbyvalue:stownbyvalueAotAction", - "stownbyvaluewithnameset:stownbyvaluewithnamesetAotAction", + + #"stownbyvaluewithnameset:stownbyvaluewithnamesetAotAction", "strictequal:strictequalAotAction", "strictnotequal:strictnotequalAotAction", "sub:subAotAction", From dea138439d81a738b23a329a9f175d2d1dfbb0dc Mon Sep 17 00:00:00 2001 From: Gongyuhang Date: Fri, 3 Jun 2022 19:39:28 +0800 Subject: [PATCH 09/35] Description: Delete the tests for checking EcmaString's behaivoir after SetCompressedStringsEnabled(true). Details: Delete the part where SetCompressedStringsEnabled(true) is called. Issue: https://gitee.com/openharmony/ark_js_runtime/issues/I5ANQA Signed-off-by: Gongyuhang --- ecmascript/tests/ecma_string_test.cpp | 102 ++------------------------ 1 file changed, 7 insertions(+), 95 deletions(-) diff --git a/ecmascript/tests/ecma_string_test.cpp b/ecmascript/tests/ecma_string_test.cpp index b6555eb729..0279447b2d 100644 --- a/ecmascript/tests/ecma_string_test.cpp +++ b/ecmascript/tests/ecma_string_test.cpp @@ -47,26 +47,9 @@ public: JSThread *thread {nullptr}; }; -/* - * @tc.name: SetCompressedStringsEnabled - * @tc.desc: Check whether the bool returned through calling GetCompressedStringsEnabled function is within - * expectations after calling SetCompressedStringsEnabled function. - * @tc.type: FUNC - * @tc.require: - */ -HWTEST_F_L0(EcmaStringTest, SetCompressedStringsEnabled) -{ - EXPECT_TRUE(EcmaString::GetCompressedStringsEnabled()); - EcmaString::SetCompressedStringsEnabled(false); - EXPECT_FALSE(EcmaString::GetCompressedStringsEnabled()); - EcmaString::SetCompressedStringsEnabled(true); - EXPECT_TRUE(EcmaString::GetCompressedStringsEnabled()); -} - /* * @tc.name: CanBeCompressed - * @tc.desc: Check whether the bool returned through calling CanBeCompressed function is within expectations before and - * after calling SetCompressedStringsEnabled function with false. + * @tc.desc: Check whether the bool returned through calling CanBeCompressed function is within expectations. * @tc.type: FUNC * @tc.require: */ @@ -78,19 +61,11 @@ HWTEST_F_L0(EcmaStringTest, CanBeCompressed) EXPECT_TRUE(EcmaString::CanBeCompressed(arrayU8, sizeof(arrayU8) / sizeof(arrayU8[0]))); EXPECT_TRUE(EcmaString::CanBeCompressed(arrayU16Comp, sizeof(arrayU16Comp) / sizeof(arrayU16Comp[0]))); EXPECT_FALSE(EcmaString::CanBeCompressed(arrayU16NotComp, sizeof(arrayU16Comp) / sizeof(arrayU16Comp[0]))); - - EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EXPECT_FALSE(EcmaString::CanBeCompressed(arrayU16NotComp, sizeof(arrayU16Comp) / sizeof(arrayU16Comp[0]))); - /* Set compressedStringsEnabled default, because it is a static boolean that some other functions rely on.The foll- - * owing HWTEST_F_L0 will come to an unexpected result if we do not set it default in the end of this HWTEST_F_L0. - */ - EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } /* * @tc.name: CreateEmptyString - * @tc.desc: Check whether the EcmaString created through calling CreateEmptyString function is within expectations - * before and after calling SetCompressedStringsEnabled function with false. + * @tc.desc: Check whether the EcmaString created through calling CreateEmptyString function is within expectations. * @tc.type: FUNC * @tc.require: */ @@ -100,18 +75,11 @@ HWTEST_F_L0(EcmaStringTest, CreateEmptyString) EXPECT_EQ(handleEcmaStrEmpty->GetLength(), 0U); EXPECT_TRUE(handleEcmaStrEmpty->IsUtf8()); EXPECT_FALSE(handleEcmaStrEmpty->IsUtf16()); - - - EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EXPECT_EQ(handleEcmaStrEmpty->GetLength(), 0U); - EXPECT_TRUE(handleEcmaStrEmpty->IsUtf16()); - EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } /* * @tc.name: AllocStringObject - * @tc.desc: Check whether the EcmaString created through calling AllocStringObject function is within expectations - * before and after calling SetCompressedStringsEnabled function with false. + * @tc.desc: Check whether the EcmaString created through calling AllocStringObject function is within expectations. * @tc.type: FUNC * @tc.require: */ @@ -137,9 +105,6 @@ HWTEST_F_L0(EcmaStringTest, AllocStringObject) EXPECT_EQ(handleEcmaStrAllocNotComp->GetLength(), sizeAllocNotComp); EXPECT_FALSE(handleEcmaStrAllocNotComp->IsUtf8()); EXPECT_TRUE(handleEcmaStrAllocNotComp->IsUtf16()); - EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EXPECT_TRUE(handleEcmaStrAllocNotComp->IsUtf16()); - EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } /* @@ -164,8 +129,7 @@ HWTEST_F_L0(EcmaStringTest, CreateFromUtf8) /* * @tc.name: CreateFromUtf16 - * @tc.desc: Check whether the EcmaString created through calling CreateFromUtf16 function is within expectations - * before and after calling SetCompressedStringsEnabled function with false. + * @tc.desc: Check whether the EcmaString created through calling CreateFromUtf16 function is within expectations. * @tc.type: FUNC * @tc.require: */ @@ -188,9 +152,6 @@ HWTEST_F_L0(EcmaStringTest, CreateFromUtf16) EXPECT_EQ(handleEcmaStrU16NotComp->GetLength(), lengthEcmaStrU16NotComp); EXPECT_FALSE(handleEcmaStrU16NotComp->IsUtf8()); EXPECT_TRUE(handleEcmaStrU16NotComp->IsUtf16()); - EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EXPECT_TRUE(handleEcmaStrU16NotComp->IsUtf16()); - EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } /* @@ -570,42 +531,6 @@ HWTEST_F_L0(EcmaStringTest, Concat_003) EXPECT_EQ(handleEcmaStrConcatU8U16NotComp->GetLength(), lengthEcmaStrFrontU8 + lengthEcmaStrBackU16NotComp); } -/* - * @tc.name: Concat_004 - * @tc.desc: Call SetCompressedStringsEnabled() function with false, check whether the EcmaString returned through - * calling Concat function between EcmaString made by CreateFromUtf8() and EcmaString made by - * CreateFromUtf16( , , , false) is within expectations. - * @tc.type: FUNC - * @tc.require: - */ -HWTEST_F_L0(EcmaStringTest, Concat_004) -{ - /* Concat() after SetCompressedStringsEnabled(false). EcmaString made by CreateFromUtf16( , , , false) and - * EcmaString made by CreateFromUtf16( , , , false). - */ - // CompressedStringEnabled cannot be changed - uint16_t arrayFrontU16NotComp[] = {128, 129, 256, 11100, 65535, 100}; - uint16_t arrayBackU16NotComp[] = {88, 768, 1, 270, 345, 333}; - uint32_t lengthEcmaStrFrontU16NotComp = sizeof(arrayFrontU16NotComp) / sizeof(arrayFrontU16NotComp[0]); - uint32_t lengthEcmaStrBackU16NotComp = sizeof(arrayBackU16NotComp) / sizeof(arrayBackU16NotComp[0]); - JSHandle handleEcmaStrFrontU16NotComp(thread, - EcmaString::CreateFromUtf16(&arrayFrontU16NotComp[0], lengthEcmaStrFrontU16NotComp, ecmaVMPtr, false)); - JSHandle handleEcmaStrBackU16NotComp(thread, - EcmaString::CreateFromUtf16(&arrayBackU16NotComp[0], lengthEcmaStrBackU16NotComp, ecmaVMPtr, false)); - JSHandle handleEcmaStrConcatU16NotCompAfterSetFalse(thread, - EcmaString::Concat(handleEcmaStrFrontU16NotComp, handleEcmaStrBackU16NotComp, ecmaVMPtr)); - EXPECT_TRUE(handleEcmaStrConcatU16NotCompAfterSetFalse->IsUtf16()); - for (uint32_t i = 0; i < lengthEcmaStrFrontU16NotComp; i++) { - EXPECT_EQ(handleEcmaStrConcatU16NotCompAfterSetFalse->At(i), arrayFrontU16NotComp[i]); - } - for (uint32_t i = 0; i < lengthEcmaStrBackU16NotComp; i++) { - EXPECT_EQ(handleEcmaStrConcatU16NotCompAfterSetFalse->At(i + lengthEcmaStrFrontU16NotComp), - arrayBackU16NotComp[i]); - } - EXPECT_EQ(handleEcmaStrConcatU16NotCompAfterSetFalse->GetLength(), - lengthEcmaStrFrontU16NotComp + lengthEcmaStrBackU16NotComp); -} - /* * @tc.name: FastSubString_001 * @tc.desc: Check whether the EcmaString returned through calling FastSubString function from EcmaString made by @@ -1666,8 +1591,7 @@ HWTEST_F_L0(EcmaStringTest, GetHashcode_002) /* * @tc.name: GetHashcode_003 * @tc.desc: Check whether the value returned through an EcmaString made by CreateFromUtf16( , , , false) calling - * GetHashcode function is within expectations before and after calling SetCompressedStringsEnabled function with - * false. + * GetHashcode function is within expectations. * @tc.type: FUNC * @tc.require: */ @@ -1683,15 +1607,12 @@ HWTEST_F_L0(EcmaStringTest, GetHashcode_003) hashExpect = hashExpect * 31 + arrayU16NotComp[i]; } EXPECT_EQ(handleEcmaStrU16NotComp->GetHashcode(), hashExpect); - EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EXPECT_EQ(handleEcmaStrU16NotComp->GetHashcode(), hashExpect); - EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } /* * @tc.name: GetHashcode_004 * @tc.desc: Check whether the value returned through an EcmaString made by CreateEmptyString() calling GetHashcode - * function is within expectations before and after calling SetCompressedStringsEnabled function with false. + * function is within expectations. * @tc.type: FUNC * @tc.require: */ @@ -1700,17 +1621,12 @@ HWTEST_F_L0(EcmaStringTest, GetHashcode_004) // GetHashcode(). EcmaString made by CreateEmptyString(). JSHandle handleEcmaStrEmpty(thread, EcmaString::CreateEmptyString(ecmaVMPtr)); EXPECT_EQ(handleEcmaStrEmpty->GetHashcode(), 0U); - - EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EXPECT_EQ(handleEcmaStrEmpty->GetHashcode(), 0U); - EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } /* * @tc.name: GetHashcode_005 * @tc.desc: Check whether the value returned through an EcmaString made by AllocStringObject(, true/false, ) calling - * GetHashcode function is within expectations before and after calling SetCompressedStringsEnabled function with - * false. + * GetHashcode function is within expectations. * @tc.type: FUNC * @tc.require: */ @@ -1722,10 +1638,6 @@ HWTEST_F_L0(EcmaStringTest, GetHashcode_005) JSHandle handleEcmaStrAllocNotComp(thread, EcmaString::AllocStringObject(sizeAlloc, false, ecmaVMPtr)); EXPECT_EQ(handleEcmaStrAllocComp->GetHashcode(), 0U); EXPECT_EQ(handleEcmaStrAllocNotComp->GetHashcode(), 0U); - - EcmaString::SetCompressedStringsEnabled(false); // Set compressedStringsEnabled false. - EXPECT_EQ(handleEcmaStrAllocNotComp->GetHashcode(), 0U); - EcmaString::SetCompressedStringsEnabled(true); // Set compressedStringsEnabled true(default). } /* From f74d22da9366a5745e9d74044a58316dc71fec28 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Thu, 2 Jun 2022 22:01:42 +0800 Subject: [PATCH 10/35] bug fix framehander should update optimizedReturnAddr_ Signed-off-by: songzhengchao Change-Id: I78c1b054ca527f5fa3dd5f15a699114be9352ad3 --- .../compiler/llvm/llvm_stackmap_parser.cpp | 18 ++++------ .../compiler/llvm/llvm_stackmap_parser.h | 5 +-- ecmascript/frames.h | 3 ++ ecmascript/interpreter/frame_handler.cpp | 35 ++++++++++++------- ecmascript/interpreter/frame_handler.h | 2 +- 5 files changed, 36 insertions(+), 27 deletions(-) diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp index aae31468ab..5b53f39065 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -93,7 +93,7 @@ void LLVMStackMapParser::PrintCallSiteInfo(const CallSiteInfo *infos, OptimizedL } } -void LLVMStackMapParser::PrintCallSiteInfo(const CallSiteInfo *infos, uintptr_t *fp, uintptr_t callSiteAddr) const +void LLVMStackMapParser::PrintCallSiteInfo(const CallSiteInfo *infos, uintptr_t *fp, uintptr_t curPc) const { if (!IsLogEnabled()) { return; @@ -105,7 +105,7 @@ void LLVMStackMapParser::PrintCallSiteInfo(const CallSiteInfo *infos, uintptr_t uintptr_t derived = 0; uintptr_t callsiteFp = *fp; - uintptr_t callSiteSp = FrameHandler::GetPrevFrameCallSiteSp(reinterpret_cast(fp), callSiteAddr); + uintptr_t callSiteSp = FrameHandler::GetPrevFrameCallSiteSp(reinterpret_cast(fp), curPc); for (auto &info: *infos) { if (info.first == GCStackMapRegisters::SP) { @@ -138,7 +138,8 @@ bool LLVMStackMapParser::IsDeriveredPointer(int callsitetime) const } bool LLVMStackMapParser::CollectStackMapSlots(uintptr_t callSiteAddr, uintptr_t frameFp, - std::set &baseSet, ChunkMap *data, [[maybe_unused]] bool isVerifying) const + std::set &baseSet, ChunkMap *data, [[maybe_unused]] bool isVerifying, + uintptr_t curPc) const { const CallSiteInfo *infos = GetCallSiteInfoByPc(callSiteAddr); if (infos == nullptr) { @@ -147,21 +148,14 @@ bool LLVMStackMapParser::CollectStackMapSlots(uintptr_t callSiteAddr, uintptr_t uintptr_t *fp = reinterpret_cast(frameFp); uintptr_t callsiteFp = *fp; - uintptr_t callSiteSp = 0x0; - auto type = FrameHandler::GetFrameType(reinterpret_cast(frameFp)); - if (type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME || type == FrameType::OPTIMIZED_FRAME) { - callSiteSp = FrameHandler::GetPrevFrameCallSiteSp(reinterpret_cast(frameFp), callSiteAddr); - } else { - callSiteSp = FrameHandler::GetPrevFrameCallSiteSp(reinterpret_cast(frameFp)); - } - + uintptr_t callSiteSp = FrameHandler::GetPrevFrameCallSiteSp(reinterpret_cast(frameFp), curPc); uintptr_t address = 0; uintptr_t base = 0; uintptr_t derived = 0; int i = 0; if (IsLogEnabled()) { - PrintCallSiteInfo(infos, fp, callSiteAddr); + PrintCallSiteInfo(infos, fp, curPc); } for (auto &info: *infos) { diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.h b/ecmascript/compiler/llvm/llvm_stackmap_parser.h index 3e3b904613..e209cb516f 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.h +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.h @@ -209,7 +209,8 @@ public: const CallSiteInfo *GetCallSiteInfoByPc(uintptr_t funcAddr) const; bool CollectStackMapSlots(uintptr_t callSiteAddr, uintptr_t frameFp, std::set &baseSet, ChunkMap *data, - [[maybe_unused]] bool isVerifying) const; + [[maybe_unused]] bool isVerifying, + uintptr_t curPc) const; bool IsLogEnabled() const { @@ -251,7 +252,7 @@ private: void CalcCallSite(); bool IsDeriveredPointer(int callsitetime) const; void PrintCallSiteInfo(const CallSiteInfo *infos, OptimizedLeaveFrame *frame) const; - void PrintCallSiteInfo(const CallSiteInfo *infos, uintptr_t *fp, uintptr_t callSiteAddr) const; + void PrintCallSiteInfo(const CallSiteInfo *infos, uintptr_t *fp, uintptr_t curPc) const; int FindFpDelta(uintptr_t funcAddr, uintptr_t callsitePc) const; struct LLVMStackMap llvmStackMap_; diff --git a/ecmascript/frames.h b/ecmascript/frames.h index e27d91ca54..d377b476fc 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -281,12 +281,14 @@ enum class JSCallMode : uintptr_t { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) struct OptimizedFrame : public base::AlignedStruct { public: enum class Index : size_t { TypeIndex = 0, PrevFpIndex, + ReturnAddrIndex, NumOfMembers }; static_assert(static_cast(Index::NumOfMembers) == NumOfTypes); @@ -302,6 +304,7 @@ public: } alignas(EAS) FrameType type {0}; alignas(EAS) JSTaggedType *prevFp {nullptr}; + alignas(EAS) uintptr_t returnAddr {0}; }; STATIC_ASSERT_EQ_ARCH(sizeof(OptimizedFrame), OptimizedFrame::SizeArch32, OptimizedFrame::SizeArch64); diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index d048c9bdf5..f531f341da 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -105,7 +105,7 @@ void FrameHandler::PrevFrame() } } -uintptr_t FrameHandler::GetPrevFrameCallSiteSp(const JSTaggedType *sp, uintptr_t callSiteAddr) +uintptr_t FrameHandler::GetPrevFrameCallSiteSp(const JSTaggedType *sp, uintptr_t curPc) { if (sp == nullptr) { return 0U; @@ -132,7 +132,7 @@ uintptr_t FrameHandler::GetPrevFrameCallSiteSp(const JSTaggedType *sp, uintptr_t case FrameType::OPTIMIZED_FRAME: case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: { auto callSiteSp = reinterpret_cast(sp) + - kungfu::LLVMStackMapParser::GetInstance().GetFuncFpDelta(callSiteAddr); + kungfu::LLVMStackMapParser::GetInstance().GetFuncFpDelta(curPc); return callSiteSp; } case FrameType::BUILTIN_ENTRY_FRAME: @@ -430,7 +430,8 @@ ARK_INLINE void FrameHandler::BuiltinFrameIterate(const JSTaggedType *sp, std::set slotAddrs; bool ret = kungfu::LLVMStackMapParser::GetInstance().CollectStackMapSlots( - frame->returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying); + frame->returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying, + optimizedReturnAddr_); if (!ret) { #ifndef NDEBUG LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << frame->returnAddr; @@ -458,7 +459,8 @@ ARK_INLINE void FrameHandler::BuiltinWithArgvFrameIterate(const JSTaggedType *sp std::set slotAddrs; bool ret = kungfu::LLVMStackMapParser::GetInstance().CollectStackMapSlots( - frame->returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying); + frame->returnAddr, reinterpret_cast(sp), slotAddrs, + derivedPointers, isVerifying, optimizedReturnAddr_); if (!ret) { #ifndef NDEBUG LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << frame->returnAddr; @@ -500,7 +502,7 @@ ARK_INLINE void FrameHandler::OptimizedFrameIterate(const JSTaggedType *sp, reinterpret_cast(*(reinterpret_cast(const_cast(sp)) + 1)); bool enableCompilerLog = thread_->GetEcmaVM()->GetJSOptions().WasSetlogCompiledMethods(); bool ret = kungfu::LLVMStackMapParser::GetInstance(enableCompilerLog).CollectStackMapSlots( - returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying); + returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying, optimizedReturnAddr_); if (!ret) { #ifndef NDEBUG LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << returnAddr; @@ -538,7 +540,7 @@ ARK_INLINE void FrameHandler::OptimizedJSFunctionFrameIterate(const JSTaggedType reinterpret_cast(*(reinterpret_cast(const_cast(sp)) + 1)); bool enableCompilerLog = thread_->GetEcmaVM()->GetJSOptions().WasSetlogCompiledMethods(); bool ret = kungfu::LLVMStackMapParser::GetInstance(enableCompilerLog).CollectStackMapSlots( - returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying); + returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying, optimizedReturnAddr_); if (!ret) { #ifndef NDEBUG LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << returnAddr; @@ -559,11 +561,10 @@ ARK_INLINE void FrameHandler::OptimizedEntryFrameIterate(const JSTaggedType *sp, { std::set slotAddrs; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - optimizedReturnAddr_ = 0; auto returnAddr = reinterpret_cast(*(reinterpret_cast(const_cast(sp)) + 1)); bool enableCompilerLog = thread_->GetEcmaVM()->GetJSOptions().WasSetlogCompiledMethods(); bool ret = kungfu::LLVMStackMapParser::GetInstance(enableCompilerLog).CollectStackMapSlots( - returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying); + returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying, optimizedReturnAddr_); if (!ret) { #ifndef NDEBUG LOG_ECMA(DEBUG) << " stackmap don't found returnAddr " << returnAddr; @@ -583,7 +584,6 @@ ARK_INLINE void FrameHandler::OptimizedLeaveFrameIterate(const JSTaggedType *sp, bool isVerifying) { OptimizedLeaveFrame *frame = OptimizedLeaveFrame::GetFrameFromSp(sp); - optimizedReturnAddr_ = frame->returnAddr; if (frame->argc > 0) { JSTaggedType *argv = reinterpret_cast(&frame->argc + 1); uintptr_t start = ToUintPtr(argv); // argv @@ -593,7 +593,7 @@ ARK_INLINE void FrameHandler::OptimizedLeaveFrameIterate(const JSTaggedType *sp, std::set slotAddrs; bool ret = kungfu::LLVMStackMapParser::GetInstance().CollectStackMapSlots( - frame->returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying); + frame->returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying, optimizedReturnAddr_); if (!ret) { return; } @@ -610,7 +610,6 @@ ARK_INLINE void FrameHandler::OptimizedWithArgvLeaveFrameIterate(const JSTaggedT bool isVerifying) { OptimizedLeaveFrame *frame = OptimizedLeaveFrame::GetFrameFromSp(sp); - optimizedReturnAddr_ = frame->returnAddr; if (frame->argc > 0) { uintptr_t* argvPtr = reinterpret_cast(&frame->argc + 1); JSTaggedType *argv = reinterpret_cast(*argvPtr); @@ -621,7 +620,8 @@ ARK_INLINE void FrameHandler::OptimizedWithArgvLeaveFrameIterate(const JSTaggedT std::set slotAddrs; bool ret = kungfu::LLVMStackMapParser::GetInstance().CollectStackMapSlots( - frame->returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying); + frame->returnAddr, reinterpret_cast(sp), slotAddrs, + derivedPointers, isVerifying, optimizedReturnAddr_); if (!ret) { return; } @@ -684,6 +684,7 @@ void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &v0, auto prevFrame = frame->GetPrevFrameFp(); OptimizedFrameIterate(current, v0, v1, derivedPointers, isVerifying); current = prevFrame; + optimizedReturnAddr_ = frame->returnAddr; break; } case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME: { @@ -697,16 +698,19 @@ void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &v0, auto prevFrame = frame->GetPrevFrameFp(); OptimizedJSFunctionFrameIterate(current, v0, v1, derivedPointers, isVerifying); current = prevFrame; + optimizedReturnAddr_ = frame->returnAddr; break; } case FrameType::OPTIMIZED_ENTRY_FRAME: { auto frame = OptimizedEntryFrame::GetFrameFromSp(current); current = frame->GetPrevFrameFp(); + optimizedReturnAddr_ = 0; break; } case FrameType::ASM_INTERPRETER_ENTRY_FRAME: { auto frame = AsmInterpretedEntryFrame::GetFrameFromSp(current); current = frame->GetPrevFrameFp(); + optimizedReturnAddr_ = 0; break; } case FrameType::ASM_INTERPRETER_FRAME: @@ -714,6 +718,7 @@ void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &v0, auto frame = AsmInterpretedFrame::GetFrameFromSp(current); AsmInterpretedFrameIterate(current, v0, v1); current = frame->GetPrevFrameFp(); + optimizedReturnAddr_ = 0; break; } case FrameType::INTERPRETER_FRAME: @@ -721,24 +726,28 @@ void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &v0, auto frame = InterpretedFrame::GetFrameFromSp(current); InterpretedFrameIterate(current, v0, v1); current = frame->GetPrevFrameFp(); + optimizedReturnAddr_ = 0; break; } case FrameType::LEAVE_FRAME: { auto frame = OptimizedLeaveFrame::GetFrameFromSp(current); OptimizedLeaveFrameIterate(current, v0, v1, derivedPointers, isVerifying); current = frame->GetPrevFrameFp(); + optimizedReturnAddr_ = frame->returnAddr; break; } case FrameType::LEAVE_FRAME_WITH_ARGV: { auto frame = OptimizedLeaveFrame::GetFrameFromSp(current); OptimizedWithArgvLeaveFrameIterate(current, v0, v1, derivedPointers, isVerifying); current = frame->GetPrevFrameFp(); + optimizedReturnAddr_ = frame->returnAddr; break; } case FrameType::BUILTIN_FRAME_WITH_ARGV: { auto frame = BuiltinWithArgvFrame::GetFrameFromSp(current); BuiltinWithArgvFrameIterate(current, v0, v1, derivedPointers, isVerifying); current = frame->GetPrevFrameFp(); + optimizedReturnAddr_ = frame->returnAddr; break; } case FrameType::BUILTIN_ENTRY_FRAME: @@ -746,12 +755,14 @@ void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &v0, auto frame = BuiltinFrame::GetFrameFromSp(current); BuiltinFrameIterate(current, v0, v1, derivedPointers, isVerifying); current = frame->GetPrevFrameFp(); + optimizedReturnAddr_ = frame->returnAddr; break; } case FrameType::INTERPRETER_ENTRY_FRAME: { auto frame = InterpretedEntryFrame::GetFrameFromSp(current); InterpretedEntryFrameIterate(current, v0, v1); current = frame->GetPrevFrameFp(); + optimizedReturnAddr_ = 0; break; } default: { diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index af50ccc82c..92b7937bb6 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -115,7 +115,7 @@ public: JSTaggedType *GetPrevInterpretedFrame(); // for llvm. - static uintptr_t GetPrevFrameCallSiteSp(const JSTaggedType *sp, uintptr_t callSiteAddr = 0); + static uintptr_t GetPrevFrameCallSiteSp(const JSTaggedType *sp, uintptr_t curPc); // for InterpretedFrame. JSTaggedValue GetVRegValue(size_t index) const; From 5a220920ee1cb0930e5b0e9ff040de8aeb5f38db Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Tue, 31 May 2022 21:16:08 +0800 Subject: [PATCH 11/35] Descriptor: debugger refactor [ part-2 ] details: 1. modify unique ptr to const reference 2. delete some unused method issue: https://gitee.com/openharmony/ark_js_runtime/issues/I59PAK Signed-off-by: wengchangcheng Change-Id: I9432b021b2257932d943a832e7401e25d5a1c37d --- .../dfx/cpu_profiler/samples_record.cpp | 6 +- ecmascript/dfx/cpu_profiler/samples_record.h | 6 +- ecmascript/tooling/agent/debugger_impl.cpp | 119 ++- ecmascript/tooling/agent/debugger_impl.h | 16 +- .../tooling/agent/heapprofiler_impl.cpp | 79 +- ecmascript/tooling/agent/profiler_impl.cpp | 116 +-- ecmascript/tooling/agent/profiler_impl.h | 6 +- ecmascript/tooling/agent/runtime_impl.cpp | 26 +- ecmascript/tooling/base/pt_events.cpp | 854 +---------------- ecmascript/tooling/base/pt_events.h | 71 +- ecmascript/tooling/base/pt_params.cpp | 14 +- ecmascript/tooling/base/pt_params.h | 44 +- ecmascript/tooling/base/pt_returns.cpp | 48 +- ecmascript/tooling/base/pt_returns.h | 48 +- ecmascript/tooling/base/pt_types.cpp | 113 ++- ecmascript/tooling/base/pt_types.h | 58 +- ecmascript/tooling/dispatcher.cpp | 4 +- ecmascript/tooling/dispatcher.h | 3 +- ecmascript/tooling/protocol_channel.h | 4 +- ecmascript/tooling/protocol_handler.cpp | 23 +- ecmascript/tooling/protocol_handler.h | 9 +- .../tooling/test/debugger_events_test.cpp | 873 ++---------------- ecmascript/tooling/test/utils/test_hooks.h | 4 +- 23 files changed, 484 insertions(+), 2060 deletions(-) diff --git a/ecmascript/dfx/cpu_profiler/samples_record.cpp b/ecmascript/dfx/cpu_profiler/samples_record.cpp index bf43e3d3bf..66fe7557d1 100644 --- a/ecmascript/dfx/cpu_profiler/samples_record.cpp +++ b/ecmascript/dfx/cpu_profiler/samples_record.cpp @@ -24,7 +24,7 @@ SamplesRecord::SamplesRecord() { stackTopLines_.push_back(0); struct MethodKey methodkey; - struct ProfileNode methodNode; + struct CpuProfileNode methodNode; methodkey.method = reinterpret_cast(INT_MAX - 1); methodMap_.insert(std::make_pair(methodkey, methodMap_.size() + 1)); methodNode.parentId = 0; @@ -46,7 +46,7 @@ void SamplesRecord::AddSample(CVector sample, uint64_t sampleTimeSta { static int PreviousId = 0; struct MethodKey methodkey; - struct ProfileNode methodNode; + struct CpuProfileNode methodNode; if (staticGcState_) { methodkey.method = reinterpret_cast(INT_MAX); methodNode.parentId = methodkey.parentId = PreviousId; @@ -191,7 +191,7 @@ void SamplesRecord::WriteMethodsAndSampleInfo(bool timeEnd) std::to_string(tts) + "},\n"; } -CVector SamplesRecord::GetMethodNodes() const +CVector SamplesRecord::GetMethodNodes() const { return profileInfo_->nodes; } diff --git a/ecmascript/dfx/cpu_profiler/samples_record.h b/ecmascript/dfx/cpu_profiler/samples_record.h index 7db3035603..4fceb19b89 100644 --- a/ecmascript/dfx/cpu_profiler/samples_record.h +++ b/ecmascript/dfx/cpu_profiler/samples_record.h @@ -33,7 +33,7 @@ struct FrameInfo { int scriptId = 0; std::string url = ""; }; -struct ProfileNode { +struct CpuProfileNode { int id = 0; int parentId = 0; int hitCount = 0; @@ -43,7 +43,7 @@ struct ProfileNode { struct ProfileInfo { uint64_t startTime = 0; uint64_t stopTime = 0; - CVector nodes; + CVector nodes; CVector samples; CVector timeDeltas; }; @@ -68,7 +68,7 @@ public: void AddSample(CVector sample, uint64_t sampleTimeStamp, bool outToFile); void WriteMethodsAndSampleInfo(bool timeEnd); - CVector GetMethodNodes() const; + CVector GetMethodNodes() const; CDeque GetSamples() const; std::string GetSampleData() const; void SetThreadStartTime(uint64_t threadStartTime); diff --git a/ecmascript/tooling/agent/debugger_impl.cpp b/ecmascript/tooling/agent/debugger_impl.cpp index 0bf104a339..cbefad38cd 100644 --- a/ecmascript/tooling/agent/debugger_impl.cpp +++ b/ecmascript/tooling/agent/debugger_impl.cpp @@ -108,7 +108,7 @@ bool DebuggerImpl::NotifyScriptParsed(ScriptId scriptId, const CString &fileName // Notify script parsed event std::unique_ptr script = std::make_unique(scriptId, fileName, url, source); - frontend_.ScriptParsed(vm_, script); + frontend_.ScriptParsed(vm_, *script); // Store parsed script in map scripts_[script->GetScriptId()] = std::move(script); @@ -213,13 +213,13 @@ void DebuggerImpl::NotifyPaused(std::optional location, PauseReaso LOG(ERROR, DEBUGGER) << "NotifyPaused: GenerateCallFrames failed"; return; } - std::unique_ptr paused = std::make_unique(); - paused->SetCallFrames(std::move(callFrames)).SetReason(reason).SetHitBreakpoints(std::move(hitBreakpoints)); + tooling::Paused paused; + paused.SetCallFrames(std::move(callFrames)).SetReason(reason).SetHitBreakpoints(std::move(hitBreakpoints)); if (reason == EXCEPTION && exception->IsError()) { std::unique_ptr tmpException = RemoteObject::FromTagged(vm_, exception); - paused->SetData(std::move(tmpException)); + paused.SetData(std::move(tmpException)); } - frontend_.Paused(vm_, std::move(paused)); + frontend_.Paused(vm_, paused); // Waiting for Debugger frontend_.WaitForDebugger(vm_); @@ -259,7 +259,7 @@ void DebuggerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) if (entry != dispatcherTable.end() && entry->second != nullptr) { (this->*(entry->second))(request); } else { - SendResponse(request, DispatchResponse::Fail("Unknown method: " + method), nullptr); + SendResponse(request, DispatchResponse::Fail("Unknown method: " + method)); } } @@ -267,21 +267,21 @@ void DebuggerImpl::DispatcherImpl::Enable(const DispatchRequest &request) { std::unique_ptr params = EnableParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("Debugger got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } UniqueDebuggerId id; DispatchResponse response = debugger_->Enable(std::move(params), &id); - std::unique_ptr result = std::make_unique(id); - SendResponse(request, response, std::move(result)); + EnableReturns result(id); + SendResponse(request, response, result); } void DebuggerImpl::DispatcherImpl::Disable(const DispatchRequest &request) { DispatchResponse response = debugger_->Disable(); - SendResponse(request, response, nullptr); + SendResponse(request, response); } void DebuggerImpl::DispatcherImpl::EvaluateOnCallFrame(const DispatchRequest &request) @@ -289,15 +289,14 @@ void DebuggerImpl::DispatcherImpl::EvaluateOnCallFrame(const DispatchRequest &re std::unique_ptr params = EvaluateOnCallFrameParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("Debugger got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } - std::unique_ptr result1 = std::make_unique(); + std::unique_ptr result1; DispatchResponse response = debugger_->EvaluateOnCallFrame(std::move(params), &result1); - std::unique_ptr result = - std::make_unique(std::move(result1)); - SendResponse(request, response, std::move(result)); + EvaluateOnCallFrameReturns result(std::move(result1)); + SendResponse(request, response, result); } void DebuggerImpl::DispatcherImpl::GetPossibleBreakpoints(const DispatchRequest &request) @@ -305,14 +304,13 @@ void DebuggerImpl::DispatcherImpl::GetPossibleBreakpoints(const DispatchRequest std::unique_ptr params = GetPossibleBreakpointsParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("Debugger got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } CVector> locations; DispatchResponse response = debugger_->GetPossibleBreakpoints(std::move(params), &locations); - std::unique_ptr points = - std::make_unique(std::move(locations)); - SendResponse(request, response, std::move(points)); + GetPossibleBreakpointsReturns result(std::move(locations)); + SendResponse(request, response, result); } void DebuggerImpl::DispatcherImpl::GetScriptSource(const DispatchRequest &request) @@ -320,20 +318,19 @@ void DebuggerImpl::DispatcherImpl::GetScriptSource(const DispatchRequest &reques std::unique_ptr params = GetScriptSourceParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("Debugger got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } CString source; DispatchResponse response = debugger_->GetScriptSource(std::move(params), &source); - std::unique_ptr result = std::make_unique(std::move(source)); - SendResponse(request, response, std::move(result)); + GetScriptSourceReturns result(source); + SendResponse(request, response, result); } void DebuggerImpl::DispatcherImpl::Pause(const DispatchRequest &request) { DispatchResponse response = debugger_->Pause(); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void DebuggerImpl::DispatcherImpl::RemoveBreakpoint(const DispatchRequest &request) @@ -341,31 +338,28 @@ void DebuggerImpl::DispatcherImpl::RemoveBreakpoint(const DispatchRequest &reque std::unique_ptr params = RemoveBreakpointParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("Debugger got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } DispatchResponse response = debugger_->RemoveBreakpoint(std::move(params)); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void DebuggerImpl::DispatcherImpl::Resume(const DispatchRequest &request) { std::unique_ptr params = ResumeParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("Debugger got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } DispatchResponse response = debugger_->Resume(std::move(params)); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void DebuggerImpl::DispatcherImpl::SetAsyncCallStackDepth(const DispatchRequest &request) { DispatchResponse response = debugger_->SetAsyncCallStackDepth(); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void DebuggerImpl::DispatcherImpl::SetBreakpointByUrl(const DispatchRequest &request) @@ -373,16 +367,15 @@ void DebuggerImpl::DispatcherImpl::SetBreakpointByUrl(const DispatchRequest &req std::unique_ptr params = SetBreakpointByUrlParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("Debugger got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } CString out_id; CVector> outLocations; DispatchResponse response = debugger_->SetBreakpointByUrl(std::move(params), &out_id, &outLocations); - std::unique_ptr result = - std::make_unique(out_id, std::move(outLocations)); - SendResponse(request, response, std::move(result)); + SetBreakpointByUrlReturns result(out_id, std::move(outLocations)); + SendResponse(request, response, result); } void DebuggerImpl::DispatcherImpl::SetPauseOnExceptions(const DispatchRequest &request) @@ -390,51 +383,46 @@ void DebuggerImpl::DispatcherImpl::SetPauseOnExceptions(const DispatchRequest &r std::unique_ptr params = SetPauseOnExceptionsParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("Debugger got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } DispatchResponse response = debugger_->SetPauseOnExceptions(std::move(params)); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void DebuggerImpl::DispatcherImpl::StepInto(const DispatchRequest &request) { std::unique_ptr params = StepIntoParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("Debugger got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } DispatchResponse response = debugger_->StepInto(std::move(params)); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void DebuggerImpl::DispatcherImpl::StepOut(const DispatchRequest &request) { DispatchResponse response = debugger_->StepOut(); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void DebuggerImpl::DispatcherImpl::StepOver(const DispatchRequest &request) { std::unique_ptr params = StepOverParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("Debugger got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } DispatchResponse response = debugger_->StepOver(std::move(params)); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void DebuggerImpl::DispatcherImpl::SetBlackboxPatterns(const DispatchRequest &request) { DispatchResponse response = debugger_->SetBlackboxPatterns(); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } bool DebuggerImpl::Frontend::AllowNotify(const EcmaVM *vm) const @@ -448,17 +436,17 @@ void DebuggerImpl::Frontend::BreakpointResolved(const EcmaVM *vm) return; } - auto breakpointResolved = std::make_unique(); - channel_->SendNotification(std::move(breakpointResolved)); + tooling::BreakpointResolved breakpointResolved; + channel_->SendNotification(breakpointResolved); } -void DebuggerImpl::Frontend::Paused(const EcmaVM *vm, std::unique_ptr paused) +void DebuggerImpl::Frontend::Paused(const EcmaVM *vm, const tooling::Paused &paused) { if (!AllowNotify(vm)) { return; } - channel_->SendNotification(std::move(paused)); + channel_->SendNotification(paused); } void DebuggerImpl::Frontend::Resumed(const EcmaVM *vm) @@ -468,8 +456,8 @@ void DebuggerImpl::Frontend::Resumed(const EcmaVM *vm) } channel_->RunIfWaitingForDebugger(); - auto resumed = std::make_unique(); - channel_->SendNotification(std::move(resumed)); + tooling::Resumed resumed; + channel_->SendNotification(resumed); } void DebuggerImpl::Frontend::ScriptFailedToParse(const EcmaVM *vm) @@ -478,18 +466,27 @@ void DebuggerImpl::Frontend::ScriptFailedToParse(const EcmaVM *vm) return; } - auto scriptFailedToParse = std::make_unique(); - channel_->SendNotification(std::move(scriptFailedToParse)); + tooling::ScriptFailedToParse scriptFailedToParse; + channel_->SendNotification(scriptFailedToParse); } -void DebuggerImpl::Frontend::ScriptParsed(const EcmaVM *vm, const std::unique_ptr &script) +void DebuggerImpl::Frontend::ScriptParsed(const EcmaVM *vm, const PtScript &script) { if (!AllowNotify(vm)) { return; } - auto scriptParsed = ScriptParsed::Create(script); - channel_->SendNotification(std::move(scriptParsed)); + tooling::ScriptParsed scriptParsed; + scriptParsed.SetScriptId(script.GetScriptId()) + .SetUrl(script.GetUrl()) + .SetStartLine(0) + .SetStartColumn(0) + .SetEndLine(script.GetEndLine()) + .SetEndColumn(0) + .SetExecutionContextId(0) + .SetHash(script.GetHash()); + + channel_->SendNotification(scriptParsed); } void DebuggerImpl::Frontend::WaitForDebugger(const EcmaVM *vm) @@ -507,7 +504,7 @@ DispatchResponse DebuggerImpl::Enable([[maybe_unused]] std::unique_ptrGetJsDebuggerManager()->SetDebugMode(true); for (auto &script : scripts_) { - frontend_.ScriptParsed(vm_, script.second); + frontend_.ScriptParsed(vm_, *script.second); } return DispatchResponse::Ok(); } diff --git a/ecmascript/tooling/agent/debugger_impl.h b/ecmascript/tooling/agent/debugger_impl.h index 04dfa0ddf7..53fa39ed88 100644 --- a/ecmascript/tooling/agent/debugger_impl.h +++ b/ecmascript/tooling/agent/debugger_impl.h @@ -25,6 +25,9 @@ #include "ecmascript/tooling/interface/js_debugger_manager.h" namespace panda::ecmascript::tooling { +namespace test { +class TestHooks; +} // namespace test class DebuggerImpl final { public: DebuggerImpl(const EcmaVM *vm, ProtocolChannel *channel, RuntimeImpl *runtime); @@ -55,13 +58,6 @@ public: DispatchResponse StepOver(std::unique_ptr params); DispatchResponse SetBlackboxPatterns(); - // for testcase - JSDebugger *GetDebugger() const - { - return jsDebugger_; - } - bool GenerateCallFrames(CVector> *callFrames); - /** * @brief: match first script and callback * @@ -95,6 +91,7 @@ public: } return false; } + bool GenerateCallFrames(CVector> *callFrames); class DispatcherImpl final : public DispatcherBase { public: @@ -154,10 +151,10 @@ private: explicit Frontend(ProtocolChannel *channel) : channel_(channel) {} void BreakpointResolved(const EcmaVM *vm); - void Paused(const EcmaVM *vm, std::unique_ptr paused); + void Paused(const EcmaVM *vm, const tooling::Paused &paused); void Resumed(const EcmaVM *vm); void ScriptFailedToParse(const EcmaVM *vm); - void ScriptParsed(const EcmaVM *vm, const std::unique_ptr &script); + void ScriptParsed(const EcmaVM *vm, const PtScript &script); void WaitForDebugger(const EcmaVM *vm); private: @@ -184,6 +181,7 @@ private: JsDebuggerManager::ObjectUpdaterFunc updaterFunc_ {nullptr}; friend class JSPtHooks; + friend class test::TestHooks; }; } // namespace panda::ecmascript::tooling #endif \ No newline at end of file diff --git a/ecmascript/tooling/agent/heapprofiler_impl.cpp b/ecmascript/tooling/agent/heapprofiler_impl.cpp index 678309b147..a666519813 100644 --- a/ecmascript/tooling/agent/heapprofiler_impl.cpp +++ b/ecmascript/tooling/agent/heapprofiler_impl.cpp @@ -40,7 +40,7 @@ void HeapProfilerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) if (entry != dispatcherTable.end() && entry->second != nullptr) { (this->*(entry->second))(request); } else { - SendResponse(request, DispatchResponse::Fail("Unknown method: " + method), nullptr); + SendResponse(request, DispatchResponse::Fail("Unknown method: " + method)); } } @@ -49,30 +49,29 @@ void HeapProfilerImpl::DispatcherImpl::AddInspectedHeapObject(const DispatchRequ std::unique_ptr params = AddInspectedHeapObjectParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("HeapProfiler got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } DispatchResponse response = heapprofiler_->AddInspectedHeapObject(std::move(params)); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void HeapProfilerImpl::DispatcherImpl::CollectGarbage(const DispatchRequest &request) { DispatchResponse response = heapprofiler_->CollectGarbage(); - SendResponse(request, response, nullptr); + SendResponse(request, response); } void HeapProfilerImpl::DispatcherImpl::Enable(const DispatchRequest &request) { DispatchResponse response = heapprofiler_->Enable(); - SendResponse(request, response, nullptr); + SendResponse(request, response); } void HeapProfilerImpl::DispatcherImpl::Disable(const DispatchRequest &request) { DispatchResponse response = heapprofiler_->Disable(); - SendResponse(request, response, nullptr); + SendResponse(request, response); } void HeapProfilerImpl::DispatcherImpl::GetHeapObjectId(const DispatchRequest &request) @@ -80,14 +79,14 @@ void HeapProfilerImpl::DispatcherImpl::GetHeapObjectId(const DispatchRequest &re std::unique_ptr params = GetHeapObjectIdParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("HeapProfiler got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } HeapSnapshotObjectId objectId; DispatchResponse response = heapprofiler_->GetHeapObjectId(std::move(params), &objectId); - std::unique_ptr result = std::make_unique(std::move(objectId)); - SendResponse(request, response, std::move(result)); + GetHeapObjectIdReturns result(std::move(objectId)); + SendResponse(request, response, result); } void HeapProfilerImpl::DispatcherImpl::GetObjectByHeapObjectId(const DispatchRequest &request) @@ -95,15 +94,14 @@ void HeapProfilerImpl::DispatcherImpl::GetObjectByHeapObjectId(const DispatchReq std::unique_ptr params = GetObjectByHeapObjectIdParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("HeapProfiler got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } std::unique_ptr remoteObjectResult; DispatchResponse response = heapprofiler_->GetObjectByHeapObjectId(std::move(params), &remoteObjectResult); - std::unique_ptr result = - std::make_unique(std::move(remoteObjectResult)); - SendResponse(request, response, std::move(result)); + GetObjectByHeapObjectIdReturns result(std::move(remoteObjectResult)); + SendResponse(request, response, result); } void HeapProfilerImpl::DispatcherImpl::GetSamplingProfile(const DispatchRequest &request) @@ -111,8 +109,8 @@ void HeapProfilerImpl::DispatcherImpl::GetSamplingProfile(const DispatchRequest std::unique_ptr profile; DispatchResponse response = heapprofiler_->GetSamplingProfile(&profile); // The return value type of GetSamplingProfile is the same as of StopSampling. - std::unique_ptr result = std::make_unique(std::move(profile)); - SendResponse(request, response, std::move(result)); + StopSamplingReturns result(std::move(profile)); + SendResponse(request, response, result); } void HeapProfilerImpl::DispatcherImpl::StartSampling(const DispatchRequest &request) @@ -120,12 +118,11 @@ void HeapProfilerImpl::DispatcherImpl::StartSampling(const DispatchRequest &requ std::unique_ptr params = StartSamplingParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("HeapProfiler got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } DispatchResponse response = heapprofiler_->StartSampling(std::move(params)); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void HeapProfilerImpl::DispatcherImpl::StartTrackingHeapObjects(const DispatchRequest &request) @@ -133,12 +130,11 @@ void HeapProfilerImpl::DispatcherImpl::StartTrackingHeapObjects(const DispatchRe std::unique_ptr params = StartTrackingHeapObjectsParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("HeapProfiler got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } DispatchResponse response = heapprofiler_->StartTrackingHeapObjects(std::move(params)); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } @@ -146,8 +142,8 @@ void HeapProfilerImpl::DispatcherImpl::StopSampling(const DispatchRequest &reque { std::unique_ptr profile; DispatchResponse response = heapprofiler_->StopSampling(&profile); - std::unique_ptr result = std::make_unique(std::move(profile)); - SendResponse(request, response, std::move(result)); + StopSamplingReturns result(std::move(profile)); + SendResponse(request, response, result); } void HeapProfilerImpl::DispatcherImpl::StopTrackingHeapObjects(const DispatchRequest &request) @@ -155,12 +151,11 @@ void HeapProfilerImpl::DispatcherImpl::StopTrackingHeapObjects(const DispatchReq std::unique_ptr params = StopTrackingHeapObjectsParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("HeapProfiler got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } DispatchResponse response = heapprofiler_->StopTrackingHeapObjects(std::move(params)); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void HeapProfilerImpl::DispatcherImpl::TakeHeapSnapshot(const DispatchRequest &request) @@ -168,12 +163,11 @@ void HeapProfilerImpl::DispatcherImpl::TakeHeapSnapshot(const DispatchRequest &r std::unique_ptr params = StopTrackingHeapObjectsParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("HeapProfiler got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } DispatchResponse response = heapprofiler_->TakeHeapSnapshot(std::move(params)); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } class HeapProfilerStream final : public Stream { @@ -235,7 +229,13 @@ void HeapProfilerImpl::Frontend::AddHeapSnapshotChunk(char *data, int size) return; } - channel_->SendNotification(AddHeapSnapshotChunk::Create(data, size)); + tooling::AddHeapSnapshotChunk addHeapSnapshotChunk; + addHeapSnapshotChunk.GetChunk().resize(size); + for (int i = 0; i < size; ++i) { + addHeapSnapshotChunk.GetChunk()[i] = data[i]; + } + + channel_->SendNotification(addHeapSnapshotChunk); } void HeapProfilerImpl::Frontend::ReportHeapSnapshotProgress(int32_t done, int32_t total) @@ -244,13 +244,12 @@ void HeapProfilerImpl::Frontend::ReportHeapSnapshotProgress(int32_t done, int32_ return; } - auto reportHeapSnapshotProgress = std::make_unique(); - reportHeapSnapshotProgress->SetDone(done); - reportHeapSnapshotProgress->SetTotal(total); + tooling::ReportHeapSnapshotProgress reportHeapSnapshotProgress; + reportHeapSnapshotProgress.SetDone(done).SetTotal(total); if (done >= total) { - reportHeapSnapshotProgress->SetFinished(true); + reportHeapSnapshotProgress.SetFinished(true); } - channel_->SendNotification(std::move(reportHeapSnapshotProgress)); + channel_->SendNotification(reportHeapSnapshotProgress); } void HeapProfilerImpl::Frontend::HeapStatsUpdate() @@ -259,8 +258,8 @@ void HeapProfilerImpl::Frontend::HeapStatsUpdate() return; } - auto heapStatsUpdate = std::make_unique(); - channel_->SendNotification(std::move(heapStatsUpdate)); + tooling::HeapStatsUpdate heapStatsUpdate; + channel_->SendNotification(heapStatsUpdate); } void HeapProfilerImpl::Frontend::LastSeenObjectId() @@ -269,8 +268,8 @@ void HeapProfilerImpl::Frontend::LastSeenObjectId() return; } - auto lastSeenObjectId = std::make_unique(); - channel_->SendNotification(std::move(lastSeenObjectId)); + tooling::LastSeenObjectId lastSeenObjectId; + channel_->SendNotification(lastSeenObjectId); } void HeapProfilerImpl::Frontend::ResetProfiles() diff --git a/ecmascript/tooling/agent/profiler_impl.cpp b/ecmascript/tooling/agent/profiler_impl.cpp index 3384d8a336..7167d3e456 100644 --- a/ecmascript/tooling/agent/profiler_impl.cpp +++ b/ecmascript/tooling/agent/profiler_impl.cpp @@ -43,58 +43,52 @@ void ProfilerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) if (entry != dispatcherTable.end() && entry->second != nullptr) { (this->*(entry->second))(request); } else { - SendResponse(request, DispatchResponse::Fail("Unknown method: " + method), nullptr); + SendResponse(request, DispatchResponse::Fail("Unknown method: " + method)); } } void ProfilerImpl::DispatcherImpl::Disable(const DispatchRequest &request) { DispatchResponse response = profiler_->Disable(); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void ProfilerImpl::DispatcherImpl::Enable(const DispatchRequest &request) { DispatchResponse response = profiler_->Enable(); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void ProfilerImpl::DispatcherImpl::Start(const DispatchRequest &request) { DispatchResponse response = profiler_->Start(); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void ProfilerImpl::DispatcherImpl::Stop(const DispatchRequest &request) { std::unique_ptr profile; - DispatchResponse response = profiler_->Stop(profile); - std::unique_ptr result = std::make_unique(std::move(profile)); - SendResponse(request, response, std::move(result)); + DispatchResponse response = profiler_->Stop(&profile); + StopReturns result(std::move(profile)); + SendResponse(request, response, result); } void ProfilerImpl::DispatcherImpl::GetBestEffortCoverage(const DispatchRequest &request) { DispatchResponse response = profiler_->GetBestEffortCoverage(); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void ProfilerImpl::DispatcherImpl::StopPreciseCoverage(const DispatchRequest &request) { DispatchResponse response = profiler_->StopPreciseCoverage(); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void ProfilerImpl::DispatcherImpl::TakePreciseCoverage(const DispatchRequest &request) { DispatchResponse response = profiler_->TakePreciseCoverage(); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void ProfilerImpl::DispatcherImpl::StartPreciseCoverage(const DispatchRequest &request) @@ -102,33 +96,29 @@ void ProfilerImpl::DispatcherImpl::StartPreciseCoverage(const DispatchRequest &r std::unique_ptr params = StartPreciseCoverageParam::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("Profiler got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } DispatchResponse response = profiler_->StartPreciseCoverage(std::move(params)); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void ProfilerImpl::DispatcherImpl::StartTypeProfile(const DispatchRequest &request) { DispatchResponse response = profiler_->StartTypeProfile(); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void ProfilerImpl::DispatcherImpl::StopTypeProfile(const DispatchRequest &request) { DispatchResponse response = profiler_->StopTypeProfile(); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } void ProfilerImpl::DispatcherImpl::TakeTypeProfile(const DispatchRequest &request) { DispatchResponse response = profiler_->TakeTypeProfile(); - std::unique_ptr result = std::make_unique(); - SendResponse(request, response, std::move(result)); + SendResponse(request, response); } bool ProfilerImpl::Frontend::AllowNotify() const @@ -142,8 +132,8 @@ void ProfilerImpl::Frontend::ConsoleProfileFinished() return; } - auto consoleProfileFinished = std::make_unique(); - channel_->SendNotification(std::move(consoleProfileFinished)); + tooling::ConsoleProfileFinished consoleProfileFinished; + channel_->SendNotification(consoleProfileFinished); } void ProfilerImpl::Frontend::ConsoleProfileStarted() @@ -152,8 +142,8 @@ void ProfilerImpl::Frontend::ConsoleProfileStarted() return; } - auto consoleProfileStarted = std::make_unique(); - channel_->SendNotification(std::move(consoleProfileStarted)); + tooling::ConsoleProfileStarted consoleProfileStarted; + channel_->SendNotification(consoleProfileStarted); } void ProfilerImpl::Frontend::PreciseCoverageDeltaUpdate() @@ -162,8 +152,8 @@ void ProfilerImpl::Frontend::PreciseCoverageDeltaUpdate() return; } - auto preciseCoverageDeltaUpdate = std::make_unique(); - channel_->SendNotification(std::move(preciseCoverageDeltaUpdate)); + tooling::PreciseCoverageDeltaUpdate preciseCoverageDeltaUpdate; + channel_->SendNotification(preciseCoverageDeltaUpdate); } DispatchResponse ProfilerImpl::Disable() @@ -184,14 +174,14 @@ DispatchResponse ProfilerImpl::Start() return DispatchResponse::Ok(); } -DispatchResponse ProfilerImpl::Stop(std::unique_ptr &profile) +DispatchResponse ProfilerImpl::Stop(std::unique_ptr *profile) { auto profileInfo = panda::DFXJSNApi::StopCpuProfilerForInfo(); if (profileInfo == nullptr) { LOG(ERROR, DEBUGGER) << "Transfer DFXJSNApi::StopCpuProfilerImpl is failure"; return DispatchResponse::Fail("Stop is failure"); } - profile = FromCpuProfiler(profileInfo); + *profile = Profile::FromProfileInfo(*profileInfo); return DispatchResponse::Ok(); } @@ -236,64 +226,4 @@ DispatchResponse ProfilerImpl::TakeTypeProfile() LOG(ERROR, DEBUGGER) << "TakeTypeProfile not support now."; return DispatchResponse::Ok(); } - -std::unique_ptr ProfilerImpl::FromCpuFrameInfo(const std::unique_ptr &cpuFrameInfo) -{ - auto runtimeCallFrame = std::make_unique(); - runtimeCallFrame->SetFunctionName(cpuFrameInfo->functionName.c_str()); - runtimeCallFrame->SetScriptId(std::to_string(cpuFrameInfo->scriptId).c_str()); - runtimeCallFrame->SetColumnNumber(cpuFrameInfo->columnNumber); - runtimeCallFrame->SetLineNumber(cpuFrameInfo->lineNumber); - runtimeCallFrame->SetUrl(cpuFrameInfo->url.c_str()); - return runtimeCallFrame; -} - -std::unique_ptr ProfilerImpl::FromCpuProfileNode(const std::unique_ptr &cpuProfileNode) -{ - auto profileNode = std::make_unique(); - profileNode->SetId(cpuProfileNode->id); - profileNode->SetHitCount(cpuProfileNode->hitCount); - - size_t childrenLen = cpuProfileNode->children.size(); - CVector tmpChildren; - tmpChildren.reserve(childrenLen); - for (uint32_t i = 0; i < childrenLen; ++i) { - tmpChildren.push_back(cpuProfileNode->children[i]); - } - profileNode->SetChildren(tmpChildren); - auto frameInfo = std::make_unique(cpuProfileNode->codeEntry); - profileNode->SetCallFrame(FromCpuFrameInfo(frameInfo)); - return profileNode; -} - -std::unique_ptr ProfilerImpl::FromCpuProfiler(const std::unique_ptr &profileInfo) -{ - auto profile = std::make_unique(); - profile->SetStartTime(static_cast(profileInfo->startTime)); - profile->SetEndTime(static_cast(profileInfo->stopTime)); - size_t samplesLen = profileInfo->samples.size(); - CVector tmpSamples; - tmpSamples.reserve(samplesLen); - for (uint32_t i = 0; i < samplesLen; ++i) { - tmpSamples.push_back(profileInfo->samples[i]); - } - profile->SetSamples(tmpSamples); - - size_t timeDeltasLen = profileInfo->timeDeltas.size(); - CVector tmpTimeDeltas; - tmpTimeDeltas.reserve(timeDeltasLen); - for (uint32_t i = 0; i < timeDeltasLen; ++i) { - tmpTimeDeltas.push_back(profileInfo->timeDeltas[i]); - } - profile->SetTimeDeltas(tmpTimeDeltas); - - CVector> profileNode; - size_t nodesLen = profileInfo->nodes.size(); - for (uint32_t i = 0; i < nodesLen; ++i) { - auto cpuProfileNode = std::make_unique(profileInfo->nodes[i]); - profileNode.push_back(FromCpuProfileNode(cpuProfileNode)); - } - profile->SetNodes(std::move(profileNode)); - return profile; -} } // namespace panda::ecmascript::tooling diff --git a/ecmascript/tooling/agent/profiler_impl.h b/ecmascript/tooling/agent/profiler_impl.h index 0153672fd9..05a9650be7 100644 --- a/ecmascript/tooling/agent/profiler_impl.h +++ b/ecmascript/tooling/agent/profiler_impl.h @@ -23,7 +23,6 @@ #include "libpandabase/macros.h" namespace panda::ecmascript::tooling { -using CpuProfileNode = ecmascript::ProfileNode; class ProfilerImpl final { public: ProfilerImpl(const EcmaVM *vm, ProtocolChannel *channel) : vm_(vm), frontend_(channel) {} @@ -32,7 +31,7 @@ public: DispatchResponse Disable(); DispatchResponse Enable(); DispatchResponse Start(); - DispatchResponse Stop(std::unique_ptr &profile); + DispatchResponse Stop(std::unique_ptr *profile); DispatchResponse GetBestEffortCoverage(); DispatchResponse StopPreciseCoverage(); DispatchResponse TakePreciseCoverage(); @@ -40,9 +39,6 @@ public: DispatchResponse StartTypeProfile(); DispatchResponse StopTypeProfile(); DispatchResponse TakeTypeProfile(); - std::unique_ptr FromCpuProfiler(const std::unique_ptr &profileInfo); - std::unique_ptr FromCpuProfileNode(const std::unique_ptr &cpuProfileNode); - std::unique_ptr FromCpuFrameInfo(const std::unique_ptr &cpuFrameInfo); class DispatcherImpl final : public DispatcherBase { public: diff --git a/ecmascript/tooling/agent/runtime_impl.cpp b/ecmascript/tooling/agent/runtime_impl.cpp index 9ad5d8a0b3..41ac8f9032 100644 --- a/ecmascript/tooling/agent/runtime_impl.cpp +++ b/ecmascript/tooling/agent/runtime_impl.cpp @@ -41,33 +41,33 @@ void RuntimeImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) (this->*(entry->second))(request); } else { LOG(ERROR, DEBUGGER) << "unknown method: " << method; - SendResponse(request, DispatchResponse::Fail("unknown method: " + method), nullptr); + SendResponse(request, DispatchResponse::Fail("unknown method: " + method)); } } void RuntimeImpl::DispatcherImpl::Enable(const DispatchRequest &request) { DispatchResponse response = runtime_->Enable(); - SendResponse(request, response, nullptr); + SendResponse(request, response); } void RuntimeImpl::DispatcherImpl::Disable(const DispatchRequest &request) { DispatchResponse response = runtime_->Disable(); - SendResponse(request, response, nullptr); + SendResponse(request, response); } void RuntimeImpl::DispatcherImpl::RunIfWaitingForDebugger(const DispatchRequest &request) { DispatchResponse response = runtime_->RunIfWaitingForDebugger(); - SendResponse(request, response, nullptr); + SendResponse(request, response); } void RuntimeImpl::DispatcherImpl::GetProperties(const DispatchRequest &request) { std::unique_ptr params = GetPropertiesParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("Debugger got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } @@ -80,11 +80,11 @@ void RuntimeImpl::DispatcherImpl::GetProperties(const DispatchRequest &request) if (outExceptionDetails) { LOG(WARNING, DEBUGGER) << "GetProperties thrown an exception"; } - std::unique_ptr result = std::make_unique(std::move(outPropertyDesc), + GetPropertiesReturns result(std::move(outPropertyDesc), std::move(outInternalDescs), std::move(outPrivateProperties), std::move(outExceptionDetails)); - SendResponse(request, response, std::move(result)); + SendResponse(request, response, result); } void RuntimeImpl::DispatcherImpl::CallFunctionOn(const DispatchRequest &request) @@ -92,7 +92,7 @@ void RuntimeImpl::DispatcherImpl::CallFunctionOn(const DispatchRequest &request) std::unique_ptr params = CallFunctionOnParams::Create(request.GetEcmaVM(), request.GetParams()); if (params == nullptr) { - SendResponse(request, DispatchResponse::Fail("Debugger got wrong params"), nullptr); + SendResponse(request, DispatchResponse::Fail("wrong params")); return; } @@ -102,9 +102,8 @@ void RuntimeImpl::DispatcherImpl::CallFunctionOn(const DispatchRequest &request) if (outExceptionDetails) { LOG(WARNING, DEBUGGER) << "CallFunctionOn thrown an exception"; } - std::unique_ptr result = std::make_unique(std::move(outRemoteObject), - std::move(outExceptionDetails)); - SendResponse(request, response, std::move(result)); + CallFunctionOnReturns result(std::move(outRemoteObject), std::move(outExceptionDetails)); + SendResponse(request, response, result); } void RuntimeImpl::DispatcherImpl::GetHeapUsage(const DispatchRequest &request) @@ -112,9 +111,8 @@ void RuntimeImpl::DispatcherImpl::GetHeapUsage(const DispatchRequest &request) double usedSize = 0; double totalSize = 0; DispatchResponse response = runtime_->GetHeapUsage(&usedSize, &totalSize); - std::unique_ptr result = std::make_unique(usedSize, - totalSize); - SendResponse(request, response, std::move(result)); + GetHeapUsageReturns result(usedSize, totalSize); + SendResponse(request, response, result); } bool RuntimeImpl::Frontend::AllowNotify() const diff --git a/ecmascript/tooling/base/pt_events.cpp b/ecmascript/tooling/base/pt_events.cpp index 8e6e14470e..eba703cf3a 100644 --- a/ecmascript/tooling/base/pt_events.cpp +++ b/ecmascript/tooling/base/pt_events.cpp @@ -16,50 +16,7 @@ #include "ecmascript/tooling/base/pt_events.h" namespace panda::ecmascript::tooling { -std::unique_ptr BreakpointResolved::Create(const EcmaVM *ecmaVm, const Local ¶ms) -{ - if (params.IsEmpty()) { - LOG(ERROR, DEBUGGER) << "BreakpointResolved::Create params is nullptr"; - return nullptr; - } - CString error; - auto breakpointResolved = std::make_unique(); - - Local result = - Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "breakpointId"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - breakpointResolved->breakpointId_ = DebuggerApi::ToCString(result); - } else { - error += "'breakpointId' should a String;"; - } - } else { - error += "should contain 'breakpointId';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "location"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsObject()) { - std::unique_ptr location = Location::Create(ecmaVm, result); - if (location == nullptr) { - error += "'location' format error;"; - } else { - breakpointResolved->location_ = std::move(location); - } - } else { - error += "'exception' should a Object;"; - } - } else { - error += "should contain 'location';"; - } - if (!error.empty()) { - LOG(ERROR, DEBUGGER) << "BreakpointResolved::Create " << error; - return nullptr; - } - - return breakpointResolved; -} - -Local BreakpointResolved::ToObject(const EcmaVM *ecmaVm) +Local BreakpointResolved::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -79,89 +36,7 @@ Local BreakpointResolved::ToObject(const EcmaVM *ecmaVm) return object; } -std::unique_ptr Paused::Create(const EcmaVM *ecmaVm, const Local ¶ms) -{ - if (params.IsEmpty()) { - LOG(ERROR, DEBUGGER) << "Paused::Create params is nullptr"; - return nullptr; - } - CString error; - auto paused = std::make_unique(); - - Local result = - Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "callFrames"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsArray(ecmaVm)) { - auto array = Local(result); - int32_t len = array->Length(ecmaVm); - Local key = JSValueRef::Undefined(ecmaVm); - for (int32_t i = 0; i < len; ++i) { - key = IntegerRef::New(ecmaVm, i); - Local resultValue = Local(array)->Get(ecmaVm, key->ToString(ecmaVm)); - std::unique_ptr callFrame = CallFrame::Create(ecmaVm, resultValue); - if (resultValue.IsEmpty() || callFrame == nullptr) { - error += "'callFrames' format invalid;"; - } - paused->callFrames_.emplace_back(std::move(callFrame)); - } - } else { - error += "'callFrames' should a Array;"; - } - } else { - error += "should contain 'callFrames';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "reason"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - paused->reason_ = DebuggerApi::ToCString(result); - } else { - error += "'reason' should a String;"; - } - } else { - error += "should contain 'reason';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "data"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsObject()) { - std::unique_ptr obj = RemoteObject::Create(ecmaVm, result); - if (obj == nullptr) { - error += "'data' format error;"; - } else { - paused->data_ = std::move(obj); - } - } else { - error += "'data' should a Object;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "hitBreakpoints"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsArray(ecmaVm)) { - CVector breakPoints; - auto array = Local(result); - int32_t len = array->Length(ecmaVm); - Local key = JSValueRef::Undefined(ecmaVm); - for (int32_t i = 0; i < len; ++i) { - key = IntegerRef::New(ecmaVm, i); - Local resultValue = Local(array)->Get(ecmaVm, key->ToString(ecmaVm)); - if (resultValue.IsEmpty()) { - error += "'hitBreakpoints' format invalid;"; - } - breakPoints.emplace_back(DebuggerApi::ToCString(result)); - } - paused->hitBreakpoints_ = std::move(breakPoints); - } else { - error += "'hitBreakpoints' should a Array;"; - } - } - if (!error.empty()) { - LOG(ERROR, DEBUGGER) << "Parsed::Create " << error; - return nullptr; - } - - return paused; -} - -Local Paused::ToObject(const EcmaVM *ecmaVm) +Local Paused::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -198,13 +73,7 @@ Local Paused::ToObject(const EcmaVM *ecmaVm) return object; } -std::unique_ptr Resumed::Create([[maybe_unused]] const EcmaVM *ecmaVm, - [[maybe_unused]] const Local ¶ms) -{ - return std::make_unique(); -} - -Local Resumed::ToObject(const EcmaVM *ecmaVm) +Local Resumed::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -217,170 +86,7 @@ Local Resumed::ToObject(const EcmaVM *ecmaVm) return object; } -std::unique_ptr ScriptFailedToParse::Create(const EcmaVM *ecmaVm, const Local ¶ms) -{ - if (params.IsEmpty()) { - LOG(ERROR, DEBUGGER) << "ScriptFailedToParse::Create params is nullptr"; - return nullptr; - } - CString error; - auto scriptEvent = std::make_unique(); - - Local result = Local(params)->Get(ecmaVm, StringRef::NewFromUtf8(ecmaVm, "scriptId")); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - scriptEvent->scriptId_ = static_cast(DebuggerApi::StringToInt(result)); - } else { - error += "'scriptId' should a String;"; - } - } else { - error += "should contain 'scriptId';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "url"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - scriptEvent->url_ = DebuggerApi::ToCString(result); - } else { - error += "'url' should a String;"; - } - } else { - error += "should contain 'url';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "startLine"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->startLine_ = Local(result)->Value(); - } else { - error += "'startLine' should a Number;"; - } - } else { - error += "should contain 'startLine';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "startColumn"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->startColumn_ = Local(result)->Value(); - } else { - error += "'startColumn' should a Number;"; - } - } else { - error += "should contain 'startColumn';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "endLine"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->endLine_ = Local(result)->Value(); - } else { - error += "'endLine' should a Number;"; - } - } else { - error += "should contain 'endLine';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "endColumn"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->endColumn_ = Local(result)->Value(); - } else { - error += "'endColumn' should a Number;"; - } - } else { - error += "should contain 'endColumn';"; - } - result = - Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "executionContextId"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->executionContextId_ = static_cast(Local(result)->Value()); - } else { - error += "'executionContextId' should a Number;"; - } - } else { - error += "should contain 'executionContextId';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "hash"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - scriptEvent->hash_ = DebuggerApi::ToCString(result); - } else { - error += "'hash' should a String;"; - } - } else { - error += "should contain 'hash';"; - } - result = Local(params)->Get(ecmaVm, - Local(StringRef::NewFromUtf8(ecmaVm, "executionContextAuxData"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsObject()) { - scriptEvent->execContextAuxData_ = Local(result); - } else { - error += "'executionContextAuxData' should a Object;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "sourceMapURL"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - scriptEvent->sourceMapUrl_ = DebuggerApi::ToCString(result); - } else { - error += "'sourceMapURL' should a String;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "hasSourceURL"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsBoolean()) { - scriptEvent->hasSourceUrl_ = result->IsTrue(); - } else { - error += "'hasSourceURL' should a Boolean;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "isModule"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsBoolean()) { - scriptEvent->isModule_ = result->IsTrue(); - } else { - error += "'isModule' should a Boolean;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "length"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->length_ = static_cast(Local(result)->Value()); - } else { - error += "'length' should a Number;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "codeOffset"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->codeOffset_ = static_cast(Local(result)->Value()); - } else { - error += "'codeOffset' should a Number;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "scriptLanguage"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - scriptEvent->scriptLanguage_ = DebuggerApi::ToCString(result); - } else { - error += "'scriptLanguage' should a String;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "embedderName"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - scriptEvent->embedderName_ = DebuggerApi::ToCString(result); - } else { - error += "'embedderName' should a String;"; - } - } - if (!error.empty()) { - LOG(ERROR, DEBUGGER) << "ScriptFailedToParse::Create " << error; - return nullptr; - } - - return scriptEvent; -} - -Local ScriptFailedToParse::ToObject(const EcmaVM *ecmaVm) +Local ScriptFailedToParse::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -455,193 +161,7 @@ Local ScriptFailedToParse::ToObject(const EcmaVM *ecmaVm) return object; } -std::unique_ptr ScriptParsed::Create(const std::unique_ptr &script) -{ - std::unique_ptr scriptParsed = std::make_unique(); - scriptParsed->SetScriptId(script->GetScriptId()) - .SetUrl(script->GetUrl()) - .SetStartLine(0) - .SetStartColumn(0) - .SetEndLine(script->GetEndLine()) - .SetEndColumn(0) - .SetExecutionContextId(0) - .SetHash(script->GetHash()); - return scriptParsed; -} - -std::unique_ptr ScriptParsed::Create(const EcmaVM *ecmaVm, const Local ¶ms) -{ - if (params.IsEmpty()) { - LOG(ERROR, DEBUGGER) << "ScriptParsed::Create params is nullptr"; - return nullptr; - } - CString error; - auto scriptEvent = std::make_unique(); - - Local result = - Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "scriptId"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - scriptEvent->scriptId_ = static_cast(DebuggerApi::StringToInt(result)); - } else { - error += "'scriptId' should a String;"; - } - } else { - error += "should contain 'scriptId';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "url"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - scriptEvent->url_ = DebuggerApi::ToCString(result); - } else { - error += "'url' should a String;"; - } - } else { - error += "should contain 'url';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "startLine"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->startLine_ = Local(result)->Value(); - } else { - error += "'startLine' should a Number;"; - } - } else { - error += "should contain 'startLine';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "startColumn"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->startColumn_ = Local(result)->Value(); - } else { - error += "'startColumn' should a Number;"; - } - } else { - error += "should contain 'startColumn';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "endLine"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->endLine_ = Local(result)->Value(); - } else { - error += "'endLine' should a Number;"; - } - } else { - error += "should contain 'endLine';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "endColumn"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->endColumn_ = Local(result)->Value(); - } else { - error += "'endColumn' should a Number;"; - } - } else { - error += "should contain 'endColumn';"; - } - result = - Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "executionContextId"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->executionContextId_ = static_cast(Local(result)->Value()); - } else { - error += "'executionContextId' should a Number;"; - } - } else { - error += "should contain 'executionContextId';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "hash"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - scriptEvent->hash_ = DebuggerApi::ToCString(result); - } else { - error += "'hash' should a String;"; - } - } else { - error += "should contain 'hash';"; - } - result = Local(params)->Get(ecmaVm, - Local(StringRef::NewFromUtf8(ecmaVm, "executionContextAuxData"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsObject()) { - scriptEvent->execContextAuxData_ = Local(result); - } else { - error += "'executionContextAuxData' should a Object;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "isLiveEdit"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsBoolean()) { - scriptEvent->isLiveEdit_ = result->IsTrue(); - } else { - error += "'isLiveEdit' should a Boolean;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "sourceMapURL"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - scriptEvent->sourceMapUrl_ = DebuggerApi::ToCString(result); - } else { - error += "'sourceMapURL' should a String;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "hasSourceURL"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsBoolean()) { - scriptEvent->hasSourceUrl_ = result->IsTrue(); - } else { - error += "'hasSourceURL' should a Boolean;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "isModule"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsBoolean()) { - scriptEvent->isModule_ = result->IsTrue(); - } else { - error += "'isModule' should a Boolean;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "length"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->length_ = static_cast(Local(result)->Value()); - } else { - error += "'length' should a Number;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "codeOffset"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - scriptEvent->codeOffset_ = static_cast(Local(result)->Value()); - } else { - error += "'codeOffset' should a Number;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "scriptLanguage"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - scriptEvent->scriptLanguage_ = DebuggerApi::ToCString(result); - } else { - error += "'scriptLanguage' should a String;"; - } - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "embedderName"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - scriptEvent->embedderName_ = DebuggerApi::ToCString(result); - } else { - error += "'embedderName' should a String;"; - } - } - if (!error.empty()) { - LOG(ERROR, DEBUGGER) << "ScriptParsed::Create " << error; - return nullptr; - } - - return scriptEvent; -} - -Local ScriptParsed::ToObject(const EcmaVM *ecmaVm) +Local ScriptParsed::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -720,49 +240,7 @@ Local ScriptParsed::ToObject(const EcmaVM *ecmaVm) return object; } -std::unique_ptr AddHeapSnapshotChunk::Create(char* data, int size) -{ - auto addHeapSnapshotChunk = std::make_unique(); - - addHeapSnapshotChunk->chunk_.resize(size); - for (int i = 0; i < size; ++i) { - addHeapSnapshotChunk->chunk_[i] = data[i]; - } - - return addHeapSnapshotChunk; -} - -std::unique_ptr AddHeapSnapshotChunk::Create(const EcmaVM *ecmaVm, - const Local ¶ms) -{ - if (params.IsEmpty()) { - LOG(ERROR, DEBUGGER) << "AddHeapSnapshotChunk::Create params is nullptr"; - return nullptr; - } - CString error; - auto addHeapSnapshotChunk = std::make_unique(); - - Local result = - Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "chunk"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - addHeapSnapshotChunk->chunk_ = DebuggerApi::ToCString(result); - } else { - error += "'chunk' should a String;"; - } - } else { - error += "should contain 'chunk';"; - } - - if (!error.empty()) { - LOG(ERROR, DEBUGGER) << "AddHeapSnapshotChunk::Create " << error; - return nullptr; - } - - return addHeapSnapshotChunk; -} - -Local AddHeapSnapshotChunk::ToObject(const EcmaVM *ecmaVm) +Local AddHeapSnapshotChunk::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -779,76 +257,7 @@ Local AddHeapSnapshotChunk::ToObject(const EcmaVM *ecmaVm) return object; } -std::unique_ptr ConsoleProfileFinished::Create(const EcmaVM *ecmaVm, - const Local ¶ms) -{ - if (params.IsEmpty()) { - LOG(ERROR, DEBUGGER) << "ConsoleProfileFinished::Create params is nullptr"; - return nullptr; - } - CString error; - auto consoleProfileFinished = std::make_unique(); - - Local result = - Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "id"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - consoleProfileFinished->id_ = DebuggerApi::ToCString(result); - } else { - error += "'id' should a String;"; - } - } else { - error += "should contain 'id';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "location"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsObject()) { - std::unique_ptr location = Location::Create(ecmaVm, result); - if (location == nullptr) { - error += "'location' format error;"; - } else { - consoleProfileFinished->location_ = std::move(location); - } - } else { - error += "'location' should a Object;"; - } - } else { - error += "should contain 'location';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "profile"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsObject()) { - std::unique_ptr profile = Profile::Create(ecmaVm, result); - if (profile == nullptr) { - error += "'profile' format error;"; - } else { - consoleProfileFinished->profile_ = std::move(profile); - } - } else { - error += "'profile' should a Object;"; - } - } else { - error += "should contain 'profile';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "title"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - consoleProfileFinished->title_ = DebuggerApi::ToCString(result); - } else { - error += "'title' should a String;"; - } - } else { - error += "should contain 'title';"; - } - if (!error.empty()) { - LOG(ERROR, DEBUGGER) << "ConsoleProfileFinished::Create " << error; - return nullptr; - } - - return consoleProfileFinished; -} - -Local ConsoleProfileFinished::ToObject(const EcmaVM *ecmaVm) +Local ConsoleProfileFinished::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -876,61 +285,7 @@ Local ConsoleProfileFinished::ToObject(const EcmaVM *ecmaVm) return object; } -std::unique_ptr ConsoleProfileStarted::Create(const EcmaVM *ecmaVm, - const Local ¶ms) -{ - if (params.IsEmpty()) { - LOG(ERROR, DEBUGGER) << "ConsoleProfileStarted::Create params is nullptr"; - return nullptr; - } - CString error; - auto consoleProfileStarted = std::make_unique(); - - Local result = - Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "id"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - consoleProfileStarted->id_ = DebuggerApi::ToCString(result); - } else { - error += "'id' should a String;"; - } - } else { - error += "should contain 'id';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "location"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsObject()) { - std::unique_ptr location = Location::Create(ecmaVm, result); - if (location == nullptr) { - error += "'location' format error;"; - } else { - consoleProfileStarted->location_ = std::move(location); - } - } else { - error += "'location' should a Object;"; - } - } else { - error += "should contain 'location';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "title"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - consoleProfileStarted->title_ = DebuggerApi::ToCString(result); - } else { - error += "'title' should a String;"; - } - } else { - error += "should contain 'title';"; - } - if (!error.empty()) { - LOG(ERROR, DEBUGGER) << "ConsoleProfileStarted::Create " << error; - return nullptr; - } - - return consoleProfileStarted; -} - -Local ConsoleProfileStarted::ToObject(const EcmaVM *ecmaVm) +Local ConsoleProfileStarted::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -955,64 +310,7 @@ Local ConsoleProfileStarted::ToObject(const EcmaVM *ecmaVm) return object; } -std::unique_ptr PreciseCoverageDeltaUpdate::Create(const EcmaVM *ecmaVm, - const Local ¶ms) -{ - if (params.IsEmpty()) { - LOG(ERROR, DEBUGGER) << "PreciseCoverageDeltaUpdate::Create params is nullptr"; - return nullptr; - } - CString error; - auto preciseCoverageDeltaUpdate = std::make_unique(); - - Local result = - Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "timestamp"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - preciseCoverageDeltaUpdate->timestamp_ = static_cast(Local(result)->Value()); - } else { - error += "'timestamp' should a Number;"; - } - } else { - error += "should contain 'timestamp';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "occasion"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsString()) { - preciseCoverageDeltaUpdate->occasion_ = DebuggerApi::ToCString(result); - } else { - error += "'occasion' should a String;"; - } - } else { - error += "should contain 'occasion';"; - } - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "result"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsArray(ecmaVm)) { - auto array = Local(result); - int32_t resultLen = array->Length(ecmaVm); - Local key = JSValueRef::Undefined(ecmaVm); - for (int32_t i = 0; i < resultLen; ++i) { - key = IntegerRef::New(ecmaVm, i); - Local resultValue = Local(array)->Get(ecmaVm, key->ToString(ecmaVm)); - std::unique_ptr tmpResult = ScriptCoverage::Create(ecmaVm, resultValue); - preciseCoverageDeltaUpdate->result_.emplace_back(std::move(tmpResult)); - } - } else { - error += "'result' should be an Array;"; - } - } else { - error += "should contain 'result';"; - } - if (!error.empty()) { - LOG(ERROR, DEBUGGER) << "PreciseCoverageDeltaUpdate::Create " << error; - return nullptr; - } - - return preciseCoverageDeltaUpdate; -} - -Local PreciseCoverageDeltaUpdate::ToObject(const EcmaVM *ecmaVm) +Local PreciseCoverageDeltaUpdate::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1038,44 +336,7 @@ Local PreciseCoverageDeltaUpdate::ToObject(const EcmaVM *ecmaVm) return object; } -std::unique_ptr HeapStatsUpdate::Create(const EcmaVM *ecmaVm, const Local ¶ms) -{ - if (params.IsEmpty()) { - LOG(ERROR, DEBUGGER) << "HeapStatsUpdate::Create params is nullptr"; - return nullptr; - } - CString error; - auto heapStatsUpdate = std::make_unique(); - - Local result = - Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "statsUpdate"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsArray(ecmaVm)) { - auto array = Local(result); - int32_t resultLen = array->Length(ecmaVm); - Local key = JSValueRef::Undefined(ecmaVm); - for (int32_t i = 0; i < resultLen; ++i) { - key = IntegerRef::New(ecmaVm, i); - int32_t statsUpdate; - Local resultValue = Local(array)->Get(ecmaVm, key->ToString(ecmaVm)); - statsUpdate = resultValue->Int32Value(ecmaVm); - heapStatsUpdate ->statsUpdate_[i] = statsUpdate; - } - } else { - error += "'statsUpdate' should be an Array;"; - } - } else { - error += "should contain 'statsUpdate';"; - } - if (!error.empty()) { - LOG(ERROR, DEBUGGER) << "HeapStatsUpdate::Create " << error; - return nullptr; - } - - return heapStatsUpdate; -} - -Local HeapStatsUpdate::ToObject(const EcmaVM *ecmaVm) +Local HeapStatsUpdate::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1096,48 +357,7 @@ Local HeapStatsUpdate::ToObject(const EcmaVM *ecmaVm) return object; } -std::unique_ptr LastSeenObjectId::Create(const EcmaVM *ecmaVm, const Local ¶ms) -{ - if (params.IsEmpty()) { - LOG(ERROR, DEBUGGER) << "LastSeenObjectId::Create params is nullptr"; - return nullptr; - } - CString error; - auto lastSeenObjectId = std::make_unique(); - - Local result = - Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "timestamp"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - lastSeenObjectId->timestamp_ = static_cast(Local(result)->Value()); - } else { - error += "'timestamp' should a Number;"; - } - } else { - error += "should contain 'timestamp';"; - } - - result = - Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "lastSeenObjectId"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - lastSeenObjectId->lastSeenObjectId_ = Local(result)->Value(); - } else { - error += "'lastSeenObjectId' should a Number;"; - } - } else { - error += "should contain 'lastSeenObjectId';"; - } - - if (!error.empty()) { - LOG(ERROR, DEBUGGER) << "LastSeenObjectId::Create " << error; - return nullptr; - } - - return lastSeenObjectId; -} - -Local LastSeenObjectId::ToObject(const EcmaVM *ecmaVm) +Local LastSeenObjectId::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1155,57 +375,7 @@ Local LastSeenObjectId::ToObject(const EcmaVM *ecmaVm) return object; } -std::unique_ptr ReportHeapSnapshotProgress::Create(const EcmaVM *ecmaVm, - const Local ¶ms) -{ - if (params.IsEmpty()) { - LOG(ERROR, DEBUGGER) << "ReportHeapSnapshotProgress::Create params is nullptr"; - return nullptr; - } - CString error; - auto reportHeapSnapshotProgress = std::make_unique(); - - Local result = - Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "done"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - reportHeapSnapshotProgress->done_ = Local(result)->Value(); - } else { - error += "'done' should a Number;"; - } - } else { - error += "should contain 'done';"; - } - - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "total"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsNumber()) { - reportHeapSnapshotProgress->total_ = Local(result)->Value(); - } else { - error += "'total' should a Number;"; - } - } else { - error += "should contain 'total';"; - } - - result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "finished"))); - if (!result.IsEmpty() && !result->IsUndefined()) { - if (result->IsBoolean()) { - reportHeapSnapshotProgress->finished_ = result->IsTrue(); - } else { - error += "'finished' should a Boolean;"; - } - } - - if (!error.empty()) { - LOG(ERROR, DEBUGGER) << "ReportHeapSnapshotProgress::Create " << error; - return nullptr; - } - - return reportHeapSnapshotProgress; -} - -Local ReportHeapSnapshotProgress::ToObject(const EcmaVM *ecmaVm) +Local ReportHeapSnapshotProgress::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); diff --git a/ecmascript/tooling/base/pt_events.h b/ecmascript/tooling/base/pt_events.h index 7c7dbb78a9..5bce1087ac 100644 --- a/ecmascript/tooling/base/pt_events.h +++ b/ecmascript/tooling/base/pt_events.h @@ -29,8 +29,8 @@ class PtBaseEvents : public PtBaseTypes { public: PtBaseEvents() = default; ~PtBaseEvents() override = default; - Local ToObject(const EcmaVM *ecmaVm) override = 0; - virtual CString GetName() = 0; + Local ToObject(const EcmaVM *ecmaVm) const override = 0; + virtual CString GetName() const = 0; private: NO_COPY_SEMANTIC(PtBaseEvents); @@ -41,10 +41,9 @@ class BreakpointResolved final : public PtBaseEvents { public: BreakpointResolved() = default; ~BreakpointResolved() override = default; - static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() override + CString GetName() const override { return "Debugger.breakpointResolved"; } @@ -83,10 +82,9 @@ class Paused final : public PtBaseEvents { public: Paused() = default; ~Paused() override = default; - static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() override + CString GetName() const override { return "Debugger.paused"; } @@ -208,10 +206,9 @@ class Resumed final : public PtBaseEvents { public: Resumed() = default; ~Resumed() override = default; - static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() override + CString GetName() const override { return "Debugger.resumed"; } @@ -225,10 +222,9 @@ class ScriptFailedToParse final : public PtBaseEvents { public: ScriptFailedToParse() = default; ~ScriptFailedToParse() override = default; - static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() override + CString GetName() const override { return "Debugger.scriptFailedToParse"; } @@ -475,11 +471,9 @@ class ScriptParsed final : public PtBaseEvents { public: ScriptParsed() = default; ~ScriptParsed() override = default; - static std::unique_ptr Create(const std::unique_ptr &script); - static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() override + CString GetName() const override { return "Debugger.scriptParsed"; } @@ -743,15 +737,18 @@ class AddHeapSnapshotChunk final : public PtBaseEvents { public: AddHeapSnapshotChunk() = default; ~AddHeapSnapshotChunk() override = default; - static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - static std::unique_ptr Create(char* data, int size); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() override + CString GetName() const override { return "HeapProfiler.addHeapSnapshotChunk"; } + CString &GetChunk() + { + return chunk_; + } + private: NO_COPY_SEMANTIC(AddHeapSnapshotChunk); NO_MOVE_SEMANTIC(AddHeapSnapshotChunk); @@ -763,9 +760,8 @@ class ConsoleProfileFinished final : public PtBaseEvents { public: ConsoleProfileFinished() = default; ~ConsoleProfileFinished() override = default; - static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; - CString GetName() override + Local ToObject(const EcmaVM *ecmaVm) const override; + CString GetName() const override { return "Profile.ConsoleProfileFinished"; } @@ -833,9 +829,8 @@ class ConsoleProfileStarted final : public PtBaseEvents { public: ConsoleProfileStarted() = default; ~ConsoleProfileStarted() override = default; - static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; - CString GetName() override + Local ToObject(const EcmaVM *ecmaVm) const override; + CString GetName() const override { return "Profile.ConsoleProfileStarted"; } @@ -891,9 +886,8 @@ class PreciseCoverageDeltaUpdate final : public PtBaseEvents { public: PreciseCoverageDeltaUpdate() = default; ~PreciseCoverageDeltaUpdate() override = default; - static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; - CString GetName() override + Local ToObject(const EcmaVM *ecmaVm) const override; + CString GetName() const override { return "Profile.PreciseCoverageDeltaUpdate"; } @@ -944,10 +938,9 @@ class HeapStatsUpdate final : public PtBaseEvents { public: HeapStatsUpdate() = default; ~HeapStatsUpdate() override = default; - static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() override + CString GetName() const override { return "HeapProfiler.heapStatsUpdate"; } @@ -974,10 +967,9 @@ class LastSeenObjectId final : public PtBaseEvents { public: LastSeenObjectId() = default; ~LastSeenObjectId() override = default; - static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() override + CString GetName() const override { return "HeapProfiler.lastSeenObjectId"; } @@ -1016,10 +1008,9 @@ class ReportHeapSnapshotProgress final : public PtBaseEvents { public: ReportHeapSnapshotProgress() = default; ~ReportHeapSnapshotProgress() override = default; - static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() override + CString GetName() const override { return "HeapProfiler.reportHeapSnapshotProgress"; } diff --git a/ecmascript/tooling/base/pt_params.cpp b/ecmascript/tooling/base/pt_params.cpp index 2666845fef..2066def7d1 100644 --- a/ecmascript/tooling/base/pt_params.cpp +++ b/ecmascript/tooling/base/pt_params.cpp @@ -753,7 +753,7 @@ std::unique_ptr StartSamplingParams::Create(const EcmaVM *e return paramsObject; } -Local StartSamplingParams::ToObject(const EcmaVM *ecmaVm) +Local StartSamplingParams::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -790,7 +790,7 @@ std::unique_ptr StartTrackingHeapObjectsParams:: return paramsObject; } -Local StartTrackingHeapObjectsParams::ToObject(const EcmaVM *ecmaVm) +Local StartTrackingHeapObjectsParams::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -848,7 +848,7 @@ std::unique_ptr StopTrackingHeapObjectsParams::Cr return paramsObject; } -Local StopTrackingHeapObjectsParams::ToObject(const EcmaVM *ecmaVm) +Local StopTrackingHeapObjectsParams::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -892,7 +892,7 @@ std::unique_ptr AddInspectedHeapObjectParams::Crea return paramsObject; } -Local AddInspectedHeapObjectParams::ToObject(const EcmaVM *ecmaVm) +Local AddInspectedHeapObjectParams::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -933,7 +933,7 @@ std::unique_ptr GetHeapObjectIdParams::Create(const EcmaV return paramsObject; } -Local GetHeapObjectIdParams::ToObject(const EcmaVM *ecmaVm) +Local GetHeapObjectIdParams::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -983,7 +983,7 @@ std::unique_ptr GetObjectByHeapObjectIdParams::Cr return paramsObject; } -Local GetObjectByHeapObjectIdParams::ToObject(const EcmaVM *ecmaVm) +Local GetObjectByHeapObjectIdParams::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1044,7 +1044,7 @@ std::unique_ptr StartPreciseCoverageParam::Create(con return paramsObject; } -Local StartPreciseCoverageParam::ToObject(const EcmaVM *ecmaVm) +Local StartPreciseCoverageParam::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); diff --git a/ecmascript/tooling/base/pt_params.h b/ecmascript/tooling/base/pt_params.h index fdebd84711..cb16cc45e7 100644 --- a/ecmascript/tooling/base/pt_params.h +++ b/ecmascript/tooling/base/pt_params.h @@ -24,7 +24,7 @@ public: PtBaseParams() = default; ~PtBaseParams() override = default; - Local ToObject(const EcmaVM *ecmaVm) override = 0; + Local ToObject(const EcmaVM *ecmaVm) const override = 0; private: NO_COPY_SEMANTIC(PtBaseParams); @@ -37,7 +37,7 @@ public: ~EnableParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -65,7 +65,7 @@ public: ~EvaluateOnCallFrameParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -100,7 +100,7 @@ public: ~GetPossibleBreakpointsParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -148,7 +148,7 @@ public: ~GetScriptSourceParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -171,7 +171,7 @@ public: ~RemoveBreakpointParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -194,7 +194,7 @@ public: ~ResumeParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -222,7 +222,7 @@ public: ~SetAsyncCallStackDepthParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -244,7 +244,7 @@ public: SetBlackboxPatternsParams() = default; ~SetBlackboxPatternsParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -267,7 +267,7 @@ public: ~SetBreakpointByUrlParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -346,7 +346,7 @@ public: SetPauseOnExceptionsParams() = default; ~SetPauseOnExceptionsParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -386,7 +386,7 @@ public: ~StepIntoParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -428,7 +428,7 @@ public: ~StepOverParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -459,7 +459,7 @@ public: ~GetPropertiesParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -515,7 +515,7 @@ public: ~CallFunctionOnParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) override + Local ToObject([[maybe_unused]] const EcmaVM *ecmaVm) const override { return Local(); } @@ -663,7 +663,7 @@ public: ~StartSamplingParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; int32_t GetSamplingInterval() const { @@ -684,7 +684,7 @@ public: static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; bool GetTrackAllocations() const { @@ -709,7 +709,7 @@ public: ~StopTrackingHeapObjectsParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; bool GetReportProgress() const { @@ -756,7 +756,7 @@ public: ~AddInspectedHeapObjectParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; HeapSnapshotObjectId GetHeapObjectId() const { @@ -776,7 +776,7 @@ public: ~GetHeapObjectIdParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; RemoteObjectId GetObjectId() const { @@ -796,7 +796,7 @@ public: ~GetObjectByHeapObjectIdParams() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; HeapSnapshotObjectId GetObjectId() const { @@ -828,7 +828,7 @@ public: static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; bool GetCallCount() const { diff --git a/ecmascript/tooling/base/pt_returns.cpp b/ecmascript/tooling/base/pt_returns.cpp index 582b1146c8..f39a9afecd 100644 --- a/ecmascript/tooling/base/pt_returns.cpp +++ b/ecmascript/tooling/base/pt_returns.cpp @@ -16,7 +16,7 @@ #include "ecmascript/tooling/base/pt_returns.h" namespace panda::ecmascript::tooling { -Local EnableReturns::ToObject(const EcmaVM *ecmaVm) +Local EnableReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); @@ -27,7 +27,7 @@ Local EnableReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local SetBreakpointByUrlReturns::ToObject(const EcmaVM *ecmaVm) +Local SetBreakpointByUrlReturns::ToObject(const EcmaVM *ecmaVm) const { size_t len = locations_.size(); Local values = ArrayRef::New(ecmaVm, len); @@ -45,7 +45,7 @@ Local SetBreakpointByUrlReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local EvaluateOnCallFrameReturns::ToObject(const EcmaVM *ecmaVm) +Local EvaluateOnCallFrameReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); @@ -61,7 +61,7 @@ Local EvaluateOnCallFrameReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local GetPossibleBreakpointsReturns::ToObject(const EcmaVM *ecmaVm) +Local GetPossibleBreakpointsReturns::ToObject(const EcmaVM *ecmaVm) const { size_t len = locations_.size(); Local values = ArrayRef::New(ecmaVm, len); @@ -76,7 +76,7 @@ Local GetPossibleBreakpointsReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local GetScriptSourceReturns::ToObject(const EcmaVM *ecmaVm) +Local GetScriptSourceReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); @@ -92,7 +92,7 @@ Local GetScriptSourceReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local RestartFrameReturns::ToObject(const EcmaVM *ecmaVm) +Local RestartFrameReturns::ToObject(const EcmaVM *ecmaVm) const { size_t len = callFrames_.size(); Local values = ArrayRef::New(ecmaVm, len); @@ -106,7 +106,7 @@ Local RestartFrameReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local SearchInContentReturns::ToObject(const EcmaVM *ecmaVm) +Local SearchInContentReturns::ToObject(const EcmaVM *ecmaVm) const { size_t len = result_.size(); Local values = ArrayRef::New(ecmaVm, len); @@ -121,7 +121,7 @@ Local SearchInContentReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local SetBreakpointReturns::ToObject(const EcmaVM *ecmaVm) +Local SetBreakpointReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); @@ -136,7 +136,7 @@ Local SetBreakpointReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local SetInstrumentationBreakpointReturns::ToObject(const EcmaVM *ecmaVm) +Local SetInstrumentationBreakpointReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); @@ -147,12 +147,12 @@ Local SetInstrumentationBreakpointReturns::ToObject(const EcmaVM *ecm return result; } -Local SetScriptSourceReturns::ToObject(const EcmaVM *ecmaVm) +Local SetScriptSourceReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); if (callFrames_) { - CVector> callFrame(std::move(callFrames_.value())); + const CVector> &callFrame = callFrames_.value(); size_t len = callFrame.size(); Local values = ArrayRef::New(ecmaVm, len); for (size_t i = 0; i < len; i++) { @@ -177,7 +177,7 @@ Local SetScriptSourceReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local GetPropertiesReturns::ToObject(const EcmaVM *ecmaVm) +Local GetPropertiesReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); @@ -189,7 +189,7 @@ Local GetPropertiesReturns::ToObject(const EcmaVM *ecmaVm) } result->Set(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "result")), values); if (internalPropertyDescripties_) { - auto descripties = std::move(internalPropertyDescripties_.value()); + auto &descripties = internalPropertyDescripties_.value(); len = descripties.size(); values = ArrayRef::New(ecmaVm, len); for (size_t i = 0; i < len; i++) { @@ -199,7 +199,7 @@ Local GetPropertiesReturns::ToObject(const EcmaVM *ecmaVm) result->Set(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "internalProperties")), values); } if (privateProperties_) { - auto descripties = std::move(privateProperties_.value()); + auto &descripties = privateProperties_.value(); len = descripties.size(); values = ArrayRef::New(ecmaVm, len); for (size_t i = 0; i < len; i++) { @@ -217,7 +217,7 @@ Local GetPropertiesReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local CallFunctionOnReturns::ToObject(const EcmaVM *ecmaVm) +Local CallFunctionOnReturns::ToObject(const EcmaVM *ecmaVm) const { // For this Local returns = NewObject(ecmaVm); @@ -235,7 +235,7 @@ Local CallFunctionOnReturns::ToObject(const EcmaVM *ecmaVm) return returns; } -Local StopSamplingReturns::ToObject(const EcmaVM *ecmaVm) +Local StopSamplingReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); @@ -247,7 +247,7 @@ Local StopSamplingReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local GetHeapObjectIdReturns::ToObject(const EcmaVM *ecmaVm) +Local GetHeapObjectIdReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); @@ -258,7 +258,7 @@ Local GetHeapObjectIdReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local GetObjectByHeapObjectIdReturns::ToObject(const EcmaVM *ecmaVm) +Local GetObjectByHeapObjectIdReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); @@ -271,7 +271,7 @@ Local GetObjectByHeapObjectIdReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local StopReturns::ToObject(const EcmaVM *ecmaVm) +Local StopReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); @@ -281,7 +281,7 @@ Local StopReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local GetHeapUsageReturns::ToObject(const EcmaVM *ecmaVm) +Local GetHeapUsageReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); @@ -295,7 +295,7 @@ Local GetHeapUsageReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local GetBestEffortCoverageReturns::ToObject(const EcmaVM *ecmaVm) +Local GetBestEffortCoverageReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); @@ -310,7 +310,7 @@ Local GetBestEffortCoverageReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local StartPreciseCoverageReturns::ToObject(const EcmaVM *ecmaVm) +Local StartPreciseCoverageReturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); result->Set(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "timestamp")), @@ -319,7 +319,7 @@ Local StartPreciseCoverageReturns::ToObject(const EcmaVM *ecmaVm) return result; } -Local TakePreciseCoverageReturns::ToObject(const EcmaVM *ecmaVm) +Local TakePreciseCoverageReturns::ToObject(const EcmaVM *ecmaVm) const { Local returns = NewObject(ecmaVm); @@ -338,7 +338,7 @@ Local TakePreciseCoverageReturns::ToObject(const EcmaVM *ecmaVm) return returns; } -Local TakeTypeProfileturns::ToObject(const EcmaVM *ecmaVm) +Local TakeTypeProfileturns::ToObject(const EcmaVM *ecmaVm) const { Local result = NewObject(ecmaVm); diff --git a/ecmascript/tooling/base/pt_returns.h b/ecmascript/tooling/base/pt_returns.h index 4dcfb47909..8ed0fc8cc7 100644 --- a/ecmascript/tooling/base/pt_returns.h +++ b/ecmascript/tooling/base/pt_returns.h @@ -24,7 +24,7 @@ public: PtBaseReturns() = default; ~PtBaseReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override + Local ToObject(const EcmaVM *ecmaVm) const override { return NewObject(ecmaVm); } @@ -39,7 +39,7 @@ public: explicit EnableReturns(UniqueDebuggerId id) : debuggerId_(id) {} ~EnableReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: EnableReturns() = default; @@ -56,7 +56,7 @@ public: {} ~SetBreakpointByUrlReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: SetBreakpointByUrlReturns() = default; @@ -74,7 +74,7 @@ public: : result_(std::move(result)), exceptionDetails_(std::move(exceptionDetails)) {} ~EvaluateOnCallFrameReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: EvaluateOnCallFrameReturns() = default; @@ -92,7 +92,7 @@ public: {} ~GetPossibleBreakpointsReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: GetPossibleBreakpointsReturns() = default; @@ -104,12 +104,12 @@ private: class GetScriptSourceReturns : public PtBaseReturns { public: - explicit GetScriptSourceReturns(CString scriptSource, std::optional bytecode = std::nullopt) - : scriptSource_(std::move(scriptSource)), bytecode_(std::move(bytecode)) + explicit GetScriptSourceReturns(const CString &scriptSource, std::optional bytecode = std::nullopt) + : scriptSource_(scriptSource), bytecode_(std::move(bytecode)) {} ~GetScriptSourceReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: GetScriptSourceReturns() = default; @@ -126,7 +126,7 @@ public: : callFrames_(std::move(callFrames)) {} ~RestartFrameReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: RestartFrameReturns() = default; @@ -141,7 +141,7 @@ public: explicit SearchInContentReturns(CVector> result) : result_(std::move(result)) {} ~SearchInContentReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: SearchInContentReturns() = default; @@ -157,7 +157,7 @@ public: : breakpointId_(id), location_(std::move(location)) {} ~SetBreakpointReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: SetBreakpointReturns() = default; @@ -172,7 +172,7 @@ public: explicit SetInstrumentationBreakpointReturns(const CString &id) : breakpointId_(id) {} ~SetInstrumentationBreakpointReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: SetInstrumentationBreakpointReturns() = default; @@ -192,7 +192,7 @@ public: exceptionDetails_(std::move(exceptionDetails)) {} ~SetScriptSourceReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: SetScriptSourceReturns() = default; @@ -216,7 +216,7 @@ public: exceptionDetails_(std::move(exceptionDetails)) {} ~GetPropertiesReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: GetPropertiesReturns() = default; @@ -237,7 +237,7 @@ public: exceptionDetails_(std::move(exceptionDetails)) {} ~CallFunctionOnReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: CallFunctionOnReturns() = default; @@ -255,7 +255,7 @@ public: {} ~StopSamplingReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: StopSamplingReturns() = default; @@ -272,7 +272,7 @@ public: {} ~GetHeapObjectIdReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: GetHeapObjectIdReturns() = default; @@ -289,7 +289,7 @@ public: {} ~GetObjectByHeapObjectIdReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: GetObjectByHeapObjectIdReturns() = default; @@ -303,7 +303,7 @@ class StopReturns : public PtBaseReturns { public: explicit StopReturns(std::unique_ptr profile) : profile_(std::move(profile)) {} ~StopReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: StopReturns() = default; @@ -318,7 +318,7 @@ public: explicit GetHeapUsageReturns(double usedSize, double totalSize) : usedSize_(usedSize), totalSize_(totalSize) {} ~GetHeapUsageReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: GetHeapUsageReturns() = default; @@ -335,7 +335,7 @@ public: : result_(std::move(result)) {} ~GetBestEffortCoverageReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: GetBestEffortCoverageReturns() = default; @@ -349,7 +349,7 @@ class StartPreciseCoverageReturns : public PtBaseReturns { public: explicit StartPreciseCoverageReturns(size_t tamp) : timestamp_(tamp) {} ~StartPreciseCoverageReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: StartPreciseCoverageReturns() = default; @@ -366,7 +366,7 @@ public: timestamp_(tamp) {} ~TakePreciseCoverageReturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: TakePreciseCoverageReturns() = default; @@ -383,7 +383,7 @@ public: : result_(std::move(result)) {} ~TakeTypeProfileturns() override = default; - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: TakeTypeProfileturns() = default; diff --git a/ecmascript/tooling/base/pt_types.cpp b/ecmascript/tooling/base/pt_types.cpp index 421368546e..be87bbe3d2 100644 --- a/ecmascript/tooling/base/pt_types.cpp +++ b/ecmascript/tooling/base/pt_types.cpp @@ -15,6 +15,8 @@ #include "pt_types.h" +#include "ecmascript/dfx/cpu_profiler/samples_record.h" + namespace panda::ecmascript::tooling { using ObjectType = RemoteObject::TypeName; using ObjectSubType = RemoteObject::SubTypeName; @@ -389,7 +391,7 @@ std::unique_ptr RemoteObject::Create(const EcmaVM *ecmaVm, const L return remoteObject; } -Local RemoteObject::ToObject(const EcmaVM *ecmaVm) +Local RemoteObject::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -525,7 +527,7 @@ std::unique_ptr ExceptionDetails::Create(const EcmaVM *ecmaVm, return exceptionDetails; } -Local ExceptionDetails::ToObject(const EcmaVM *ecmaVm) +Local ExceptionDetails::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -606,7 +608,7 @@ std::unique_ptr InternalPropertyDescriptor::Create(c return internalPropertyDescriptor; } -Local InternalPropertyDescriptor::ToObject(const EcmaVM *ecmaVm) +Local InternalPropertyDescriptor::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -691,7 +693,7 @@ std::unique_ptr PrivatePropertyDescriptor::Create(con return propertyDescriptor; } -Local PrivatePropertyDescriptor::ToObject(const EcmaVM *ecmaVm) +Local PrivatePropertyDescriptor::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -879,7 +881,7 @@ std::unique_ptr PropertyDescriptor::Create(const EcmaVM *ecm return propertyDescriptor; } -Local PropertyDescriptor::ToObject(const EcmaVM *ecmaVm) +Local PropertyDescriptor::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -973,7 +975,7 @@ std::unique_ptr CallArgument::Create(const EcmaVM *ecmaVm, const L return callArgument; } -Local CallArgument::ToObject(const EcmaVM *ecmaVm) +Local CallArgument::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1040,7 +1042,7 @@ std::unique_ptr Location::Create(const EcmaVM *ecmaVm, const Local Location::ToObject(const EcmaVM *ecmaVm) +Local Location::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1096,7 +1098,7 @@ std::unique_ptr ScriptPosition::Create(const EcmaVM *ecmaVm, con return scriptPosition; } -Local ScriptPosition::ToObject(const EcmaVM *ecmaVm) +Local ScriptPosition::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1148,7 +1150,7 @@ std::unique_ptr SearchMatch::Create(const EcmaVM *ecmaVm, const Loc return locationSearch; } -Local SearchMatch::ToObject(const EcmaVM *ecmaVm) +Local SearchMatch::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1218,7 +1220,7 @@ std::unique_ptr LocationRange::Create(const EcmaVM *ecmaVm, const return locationRange; } -Local LocationRange::ToObject(const EcmaVM *ecmaVm) +Local LocationRange::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1295,7 +1297,7 @@ std::unique_ptr BreakLocation::Create(const EcmaVM *ecmaVm, const return breakLocation; } -Local BreakLocation::ToObject(const EcmaVM *ecmaVm) +Local BreakLocation::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1400,7 +1402,7 @@ std::unique_ptr Scope::Create(const EcmaVM *ecmaVm, const Local Scope::ToObject(const EcmaVM *ecmaVm) +Local Scope::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1558,7 +1560,7 @@ std::unique_ptr CallFrame::Create(const EcmaVM *ecmaVm, const Local CallFrame::ToObject(const EcmaVM *ecmaVm) +Local CallFrame::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1653,7 +1655,7 @@ std::unique_ptr SamplingHeapProfileSample::Create(con return samplingHeapProfileSample; } -Local SamplingHeapProfileSample::ToObject(const EcmaVM *ecmaVm) +Local SamplingHeapProfileSample::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1740,7 +1742,18 @@ std::unique_ptr RuntimeCallFrame::Create(const EcmaVM *ecmaVm, return runtimeCallFrame; } -Local RuntimeCallFrame::ToObject(const EcmaVM *ecmaVm) +std::unique_ptr RuntimeCallFrame::FromFrameInfo(const FrameInfo &cpuFrameInfo) +{ + auto runtimeCallFrame = std::make_unique(); + runtimeCallFrame->SetFunctionName(cpuFrameInfo.functionName.c_str()); + runtimeCallFrame->SetScriptId(std::to_string(cpuFrameInfo.scriptId).c_str()); + runtimeCallFrame->SetColumnNumber(cpuFrameInfo.columnNumber); + runtimeCallFrame->SetLineNumber(cpuFrameInfo.lineNumber); + runtimeCallFrame->SetUrl(cpuFrameInfo.url.c_str()); + return runtimeCallFrame; +} + +Local RuntimeCallFrame::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1842,7 +1855,7 @@ std::unique_ptr SamplingHeapProfileNode::Create(const E return samplingHeapProfileNode; } -Local SamplingHeapProfileNode::ToObject(const EcmaVM *ecmaVm) +Local SamplingHeapProfileNode::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1927,7 +1940,7 @@ std::unique_ptr SamplingHeapProfile::Create(const EcmaVM *e return samplingHeapProfile; } -Local SamplingHeapProfile::ToObject(const EcmaVM *ecmaVm) +Local SamplingHeapProfile::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); @@ -1987,7 +2000,7 @@ std::unique_ptr PositionTickInfo::Create(const EcmaVM *ecmaVm, return positionTicks; } -Local PositionTickInfo::ToObject(const EcmaVM *ecmaVm) +Local PositionTickInfo::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); params->Set(ecmaVm, @@ -2099,7 +2112,24 @@ std::unique_ptr ProfileNode::Create(const EcmaVM *ecmaVm, const Loc return profileNode; } -Local ProfileNode::ToObject(const EcmaVM *ecmaVm) +std::unique_ptr ProfileNode::FromCpuProfileNode(const CpuProfileNode &cpuProfileNode) +{ + auto profileNode = std::make_unique(); + profileNode->SetId(cpuProfileNode.id); + profileNode->SetHitCount(cpuProfileNode.hitCount); + + size_t childrenLen = cpuProfileNode.children.size(); + CVector tmpChildren; + tmpChildren.reserve(childrenLen); + for (uint32_t i = 0; i < childrenLen; ++i) { + tmpChildren.push_back(cpuProfileNode.children[i]); + } + profileNode->SetChildren(tmpChildren); + profileNode->SetCallFrame(RuntimeCallFrame::FromFrameInfo(cpuProfileNode.codeEntry)); + return profileNode; +} + +Local ProfileNode::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); params->Set(ecmaVm, @@ -2237,7 +2267,38 @@ std::unique_ptr Profile::Create(const EcmaVM *ecmaVm, const Local Profile::ToObject(const EcmaVM *ecmaVm) +std::unique_ptr Profile::FromProfileInfo(const ProfileInfo &profileInfo) +{ + auto profile = std::make_unique(); + profile->SetStartTime(static_cast(profileInfo.startTime)); + profile->SetEndTime(static_cast(profileInfo.stopTime)); + size_t samplesLen = profileInfo.samples.size(); + CVector tmpSamples; + tmpSamples.reserve(samplesLen); + for (uint32_t i = 0; i < samplesLen; ++i) { + tmpSamples.push_back(profileInfo.samples[i]); + } + profile->SetSamples(tmpSamples); + + size_t timeDeltasLen = profileInfo.timeDeltas.size(); + CVector tmpTimeDeltas; + tmpTimeDeltas.reserve(timeDeltasLen); + for (uint32_t i = 0; i < timeDeltasLen; ++i) { + tmpTimeDeltas.push_back(profileInfo.timeDeltas[i]); + } + profile->SetTimeDeltas(tmpTimeDeltas); + + CVector> profileNode; + size_t nodesLen = profileInfo.nodes.size(); + for (uint32_t i = 0; i < nodesLen; ++i) { + const auto &cpuProfileNode = profileInfo.nodes[i]; + profileNode.push_back(ProfileNode::FromCpuProfileNode(cpuProfileNode)); + } + profile->SetNodes(std::move(profileNode)); + return profile; +} + +Local Profile::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); size_t nodeLen = nodes_.size(); @@ -2324,7 +2385,7 @@ std::unique_ptr Coverage::Create(const EcmaVM *ecmaVm, const Local Coverage::ToObject(const EcmaVM *ecmaVm) +Local Coverage::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); params->Set(ecmaVm, @@ -2392,7 +2453,7 @@ std::unique_ptr FunctionCoverage::Create(const EcmaVM *ecmaVm, return functionCoverage; } -Local FunctionCoverage::ToObject(const EcmaVM *ecmaVm) +Local FunctionCoverage::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); params->Set(ecmaVm, @@ -2469,7 +2530,7 @@ std::unique_ptr ScriptCoverage::Create(const EcmaVM *ecmaVm, con return scriptCoverage; } -Local ScriptCoverage::ToObject(const EcmaVM *ecmaVm) +Local ScriptCoverage::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); params->Set(ecmaVm, @@ -2515,7 +2576,7 @@ std::unique_ptr TypeObject::Create(const EcmaVM *ecmaVm, const Local return typeObject; } -Local TypeObject::ToObject(const EcmaVM *ecmaVm) +Local TypeObject::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); params->Set(ecmaVm, @@ -2568,7 +2629,7 @@ std::unique_ptr TypeProfileEntry::Create(const EcmaVM *ecmaVm, return typeProfileEntry; } -Local TypeProfileEntry::ToObject(const EcmaVM *ecmaVm) +Local TypeProfileEntry::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); params->Set(ecmaVm, @@ -2640,7 +2701,7 @@ std::unique_ptr ScriptTypeProfile::Create(const EcmaVM *ecmaV return scriptTypeProfile; } -Local ScriptTypeProfile::ToObject(const EcmaVM *ecmaVm) +Local ScriptTypeProfile::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); params->Set(ecmaVm, diff --git a/ecmascript/tooling/base/pt_types.h b/ecmascript/tooling/base/pt_types.h index a5bfbafb2c..c116267f48 100644 --- a/ecmascript/tooling/base/pt_types.h +++ b/ecmascript/tooling/base/pt_types.h @@ -19,6 +19,7 @@ #include #include +#include "ecmascript/dfx/cpu_profiler/samples_record.h" #include "ecmascript/mem/c_containers.h" #include "ecmascript/mem/c_string.h" #include "ecmascript/tooling/backend/debugger_api.h" @@ -30,7 +31,7 @@ class PtBaseTypes { public: PtBaseTypes() = default; virtual ~PtBaseTypes() = default; - virtual Local ToObject(const EcmaVM *ecmaVm) = 0; + virtual Local ToObject(const EcmaVM *ecmaVm) const = 0; protected: static Local NewObject(const EcmaVM *ecmaVm); @@ -110,7 +111,7 @@ public: static std::unique_ptr FromTagged(const EcmaVM *ecmaVm, const Local &tagged); static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; /* * @see {#ObjectType} @@ -402,7 +403,7 @@ public: ExceptionDetails() = default; ~ExceptionDetails() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; int32_t GetExceptionId() const { @@ -536,7 +537,7 @@ public: ~InternalPropertyDescriptor() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; CString GetName() const { @@ -583,7 +584,7 @@ public: ~PrivatePropertyDescriptor() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; CString GetName() const { @@ -672,7 +673,7 @@ public: static std::unique_ptr FromProperty(const EcmaVM *ecmaVm, const Local &name, const PropertyAttribute &property); static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; CString GetName() const { @@ -854,7 +855,7 @@ public: ~CallArgument() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; Local GetValue() const { @@ -937,7 +938,7 @@ public: ~Location() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; ScriptId GetScriptId() const { @@ -993,7 +994,7 @@ public: ~ScriptPosition() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; int32_t GetLine() const { @@ -1031,7 +1032,7 @@ public: SearchMatch() = default; ~SearchMatch() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; private: NO_COPY_SEMANTIC(SearchMatch); @@ -1048,7 +1049,7 @@ public: ~LocationRange() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; ScriptId GetScriptId() const { @@ -1099,7 +1100,7 @@ public: ~BreakLocation() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; ScriptId GetScriptId() const { @@ -1208,7 +1209,7 @@ public: ~Scope() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; /* * @see {#Scope::Type} @@ -1356,7 +1357,7 @@ public: ~CallFrame() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; CallFrameId GetCallFrameId() const { @@ -1484,7 +1485,7 @@ public: SamplingHeapProfileSample() = default; ~SamplingHeapProfileSample() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; SamplingHeapProfileSample &SetSize(size_t size) { @@ -1533,7 +1534,8 @@ public: RuntimeCallFrame() = default; ~RuntimeCallFrame() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + static std::unique_ptr FromFrameInfo(const FrameInfo &cpuFrameInfo); + Local ToObject(const EcmaVM *ecmaVm) const override; RuntimeCallFrame &SetFunctionName(const CString &functionName) { @@ -1606,7 +1608,7 @@ public: SamplingHeapProfileNode() = default; ~SamplingHeapProfileNode() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; SamplingHeapProfileNode &SetCallFrame(std::unique_ptr callFrame) { @@ -1667,7 +1669,7 @@ public: SamplingHeapProfile() = default; ~SamplingHeapProfile() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; SamplingHeapProfile &SetHead(std::unique_ptr head) { @@ -1707,7 +1709,7 @@ public: ~PositionTickInfo() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; int32_t GetLine() const { return line_; @@ -1744,7 +1746,8 @@ public: ~ProfileNode() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + static std::unique_ptr FromCpuProfileNode(const CpuProfileNode &cpuProfileNode); + Local ToObject(const EcmaVM *ecmaVm) const override; int32_t GetId() const { @@ -1856,7 +1859,8 @@ public: ~Profile() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + static std::unique_ptr FromProfileInfo(const ProfileInfo &profileInfo); + Local ToObject(const EcmaVM *ecmaVm) const override; int64_t GetStartTime() const { @@ -1947,7 +1951,7 @@ public: ~Coverage() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; int32_t GetStartOffset() const { @@ -1998,7 +2002,7 @@ public: ~FunctionCoverage() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; const CString &GetFunctionName() const { @@ -2050,7 +2054,7 @@ public: ~ScriptCoverage() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; const CString &GetScriptId() const { @@ -2101,7 +2105,7 @@ public: ~TypeObject() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; const CString &GetName() const { return name_; @@ -2127,7 +2131,7 @@ public: ~TypeProfileEntry() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; int32_t GetOffset() const { return offset_; @@ -2165,7 +2169,7 @@ public: ~ScriptTypeProfile() override = default; static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); - Local ToObject(const EcmaVM *ecmaVm) override; + Local ToObject(const EcmaVM *ecmaVm) const override; const CString &GetScriptId() const { return scriptId_; diff --git a/ecmascript/tooling/dispatcher.cpp b/ecmascript/tooling/dispatcher.cpp index 36f091be5f..6b22f2ee91 100644 --- a/ecmascript/tooling/dispatcher.cpp +++ b/ecmascript/tooling/dispatcher.cpp @@ -126,10 +126,10 @@ DispatchResponse DispatchResponse::Fail(const CString &message) } void DispatcherBase::SendResponse(const DispatchRequest &request, const DispatchResponse &response, - std::unique_ptr result) + const PtBaseReturns &result) { if (channel_ != nullptr) { - channel_->SendResponse(request, response, std::move(result)); + channel_->SendResponse(request, response, result); } } diff --git a/ecmascript/tooling/dispatcher.h b/ecmascript/tooling/dispatcher.h index 0f28dfd29e..3138dacacb 100644 --- a/ecmascript/tooling/dispatcher.h +++ b/ecmascript/tooling/dispatcher.h @@ -23,6 +23,7 @@ #include "ecmascript/mem/c_string.h" #include "ecmascript/napi/include/jsnapi.h" #include "ecmascript/tooling/backend/js_debugger_interface.h" +#include "ecmascript/tooling/base/pt_returns.h" #include "libpandabase/macros.h" namespace panda::ecmascript::tooling { @@ -129,7 +130,7 @@ public: protected: void SendResponse(const DispatchRequest &request, const DispatchResponse &response, - std::unique_ptr result); + const PtBaseReturns &result = PtBaseReturns()); private: ProtocolChannel *channel_ {nullptr}; diff --git a/ecmascript/tooling/protocol_channel.h b/ecmascript/tooling/protocol_channel.h index 09711aecfd..3c2d7ba238 100644 --- a/ecmascript/tooling/protocol_channel.h +++ b/ecmascript/tooling/protocol_channel.h @@ -31,8 +31,8 @@ public: virtual void WaitForDebugger() = 0; virtual void RunIfWaitingForDebugger() = 0; virtual void SendResponse(const DispatchRequest &request, const DispatchResponse &response, - std::unique_ptr result) = 0; - virtual void SendNotification(std::unique_ptr events) = 0; + const PtBaseReturns &result) = 0; + virtual void SendNotification(const PtBaseEvents &events) = 0; private: NO_COPY_SEMANTIC(ProtocolChannel); diff --git a/ecmascript/tooling/protocol_handler.cpp b/ecmascript/tooling/protocol_handler.cpp index 0c1245b6d3..ca045d52a3 100644 --- a/ecmascript/tooling/protocol_handler.cpp +++ b/ecmascript/tooling/protocol_handler.cpp @@ -20,12 +20,6 @@ #include "utils/logger.h" namespace panda::ecmascript::tooling { -ProtocolHandler::ProtocolHandler(std::function callback, const EcmaVM *vm) - : callback_(std::move(callback)), vm_(vm) -{ - dispatcher_ = std::make_unique(vm_, this); -} - void ProtocolHandler::WaitForDebugger() { waitingForDebugger_ = true; @@ -45,12 +39,12 @@ void ProtocolHandler::ProcessCommand(const CString &msg) LOG(DEBUG, DEBUGGER) << "ProtocolHandler::ProcessCommand: " << msg; [[maybe_unused]] LocalScope scope(vm_); Local exception = DebuggerApi::GetAndClearException(vm_); - dispatcher_->Dispatch(DispatchRequest(vm_, msg)); + dispatcher_.Dispatch(DispatchRequest(vm_, msg)); DebuggerApi::SetException(vm_, exception); } void ProtocolHandler::SendResponse(const DispatchRequest &request, const DispatchResponse &response, - std::unique_ptr result) + const PtBaseReturns &result) { LOG(INFO, DEBUGGER) << "ProtocolHandler::SendResponse: " << (response.IsOk() ? "success" : "failed: " + response.GetMessage()); @@ -58,8 +52,8 @@ void ProtocolHandler::SendResponse(const DispatchRequest &request, const Dispatc Local reply = PtBaseTypes::NewObject(vm_); reply->Set(vm_, StringRef::NewFromUtf8(vm_, "id"), IntegerRef::New(vm_, request.GetCallId())); Local resultObj; - if (response.IsOk() && result != nullptr) { - resultObj = result->ToObject(vm_); + if (response.IsOk()) { + resultObj = result.ToObject(vm_); } else { resultObj = CreateErrorReply(response); } @@ -67,13 +61,10 @@ void ProtocolHandler::SendResponse(const DispatchRequest &request, const Dispatc SendReply(reply); } -void ProtocolHandler::SendNotification(std::unique_ptr events) +void ProtocolHandler::SendNotification(const PtBaseEvents &events) { - if (events == nullptr) { - return; - } - LOG(DEBUG, DEBUGGER) << "ProtocolHandler::SendNotification: " << events->GetName(); - SendReply(events->ToObject(vm_)); + LOG(DEBUG, DEBUGGER) << "ProtocolHandler::SendNotification: " << events.GetName(); + SendReply(events.ToObject(vm_)); } void ProtocolHandler::SendReply(Local reply) diff --git a/ecmascript/tooling/protocol_handler.h b/ecmascript/tooling/protocol_handler.h index 4667805fc0..d4141ed72f 100644 --- a/ecmascript/tooling/protocol_handler.h +++ b/ecmascript/tooling/protocol_handler.h @@ -25,15 +25,16 @@ namespace panda::ecmascript::tooling { class ProtocolHandler final : public ProtocolChannel { public: - ProtocolHandler(std::function callback, const EcmaVM *vm); + ProtocolHandler(std::function callback, const EcmaVM *vm) + : callback_(std::move(callback)), dispatcher_(vm, this), vm_(vm) {} ~ProtocolHandler() override = default; void WaitForDebugger() override; void RunIfWaitingForDebugger() override; void ProcessCommand(const CString &msg); void SendResponse(const DispatchRequest &request, const DispatchResponse &response, - std::unique_ptr result) override; - void SendNotification(std::unique_ptr events) override; + const PtBaseReturns &result) override; + void SendNotification(const PtBaseEvents &events) override; private: NO_MOVE_SEMANTIC(ProtocolHandler); @@ -42,7 +43,7 @@ private: void SendReply(Local reply); std::function callback_; - std::unique_ptr dispatcher_ {}; + Dispatcher dispatcher_; bool waitingForDebugger_ {false}; const EcmaVM *vm_ {nullptr}; diff --git a/ecmascript/tooling/test/debugger_events_test.cpp b/ecmascript/tooling/test/debugger_events_test.cpp index 62ed370c53..d92d1fd559 100644 --- a/ecmascript/tooling/test/debugger_events_test.cpp +++ b/ecmascript/tooling/test/debugger_events_test.cpp @@ -60,58 +60,16 @@ protected: JSThread *thread {nullptr}; }; -HWTEST_F_L0(DebuggerEventsTest, BreakpointResolvedCreateTest) -{ - CString msg; - std::unique_ptr breakpointResolved; - - // abnormal params of null msg - msg = CString() + R"({})"; - breakpointResolved = BreakpointResolved::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(breakpointResolved, nullptr); - - // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; - breakpointResolved = BreakpointResolved::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(breakpointResolved, nullptr); - - // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; - breakpointResolved = BreakpointResolved::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(breakpointResolved, nullptr); - - // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; - breakpointResolved = BreakpointResolved::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(breakpointResolved, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"breakpointId":"00"}})"; - breakpointResolved = BreakpointResolved::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(breakpointResolved, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"location":{"scriptId":"2","lineNumber":99}}})"; - breakpointResolved = BreakpointResolved::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(breakpointResolved, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"breakpointId":"00", - "location":{"scriptId":"2","lineNumber":99}}})"; - breakpointResolved = BreakpointResolved::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(breakpointResolved, nullptr); -} - HWTEST_F_L0(DebuggerEventsTest, BreakpointResolvedToObjectTest) { CString msg; - std::unique_ptr breakpointResolved; + BreakpointResolved breakpointResolved; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"breakpointId":"00", - "location":{"scriptId":"2","lineNumber":99}}})"; - breakpointResolved = BreakpointResolved::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - - ASSERT_NE(breakpointResolved, nullptr); - Local object1 = breakpointResolved->ToObject(ecmaVm); + auto location = std::make_unique(); + location->SetScriptId(2).SetLine(99); + breakpointResolved.SetBreakpointId("00").SetLocation(std::move(location)); + Local object1 = breakpointResolved.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); ASSERT_TRUE(result->IsObject()); @@ -130,63 +88,10 @@ HWTEST_F_L0(DebuggerEventsTest, BreakpointResolvedToObjectTest) ASSERT_TRUE(result->IsObject()); } -HWTEST_F_L0(DebuggerEventsTest, PausedCreateTest) -{ - CString msg; - std::unique_ptr paused; - - // abnormal params of null msg - msg = CString() + R"({})"; - paused = Paused::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(paused, nullptr); - - // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; - paused = Paused::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(paused, nullptr); - - // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; - paused = Paused::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(paused, nullptr); - - // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; - paused = Paused::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(paused, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"reason":"exception"}})"; - paused = Paused::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(paused, nullptr); - - msg = CString() + - R"({"id":0,"method":"Debugger.Test","params": - {"callFrames":[)" + - R"({"id":0,"method":"Debugger.Test","params":{ - "callFrameId":10,"functionName":"name0", - "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": - [{"type":"global","object":{"type":")" + - ObjectType::Object + R"("}}, {"type":"local","object":{"type":")" + ObjectType::Object + - R"("}}],"this":{"type":")" + ObjectType::Object + R"(","subtype":")" + ObjectSubType::V128 + R"("}}})" + - R"(]}})"; - paused = Paused::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(paused, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"callFrames":[)" + - R"({"callFrameId":"10","functionName":"name0", - "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": - [{"type":"global","object":{"type":")" + - ObjectType::Object + R"("}}, {"type":"local","object":{"type":")" + ObjectType::Object + - R"("}}],"this":{"type":")" + ObjectType::Object + R"(","subtype":")" + ObjectSubType::V128 + R"("}})" + - R"(],"reason":"exception"}})"; - paused = Paused::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(paused, nullptr); -} - HWTEST_F_L0(DebuggerEventsTest, PausedToObjectTest) { CString msg; - std::unique_ptr paused; + Paused paused; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); msg = CString() + R"({"id":0,"method":"Debugger.Test","params": @@ -194,10 +99,9 @@ HWTEST_F_L0(DebuggerEventsTest, PausedToObjectTest) "location":{"scriptId":"5","lineNumber":19},"url":"url7", "scopeChain":[{"type":"global","object":{"type":"object"}}, {"type":"local","object":{"type":"object"}}], "this":{"type":"object","subtype":"v128"}}],"reason":"exception"}})"; - paused = Paused::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(paused, nullptr); - - Local object1 = paused->ToObject(ecmaVm); + paused.SetCallFrames(CVector>{}) + .SetReason(PauseReason::EXCEPTION); + Local object1 = paused.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); ASSERT_TRUE(result->IsObject()); @@ -219,16 +123,16 @@ HWTEST_F_L0(DebuggerEventsTest, PausedToObjectTest) HWTEST_F_L0(DebuggerEventsTest, ResumedToObjectTest) { CString msg; - std::unique_ptr resumed = std::make_unique(); + Resumed resumed; Local tmpStr; - Local object = resumed->ToObject(ecmaVm); + Local object = resumed.ToObject(ecmaVm); tmpStr = StringRef::NewFromUtf8(ecmaVm, "method"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); Local result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(CString(resumed->GetName().c_str()), DebuggerApi::ToCString(result)); + EXPECT_EQ(resumed.GetName(), DebuggerApi::ToCString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); @@ -237,318 +141,28 @@ HWTEST_F_L0(DebuggerEventsTest, ResumedToObjectTest) ASSERT_TRUE(result->IsObject()); } -HWTEST_F_L0(DebuggerEventsTest, ScriptFailedToParseCreateTest) -{ - CString msg; - std::unique_ptr parse; - - // abnormal params of null msg - msg = CString() + R"({})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2}})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn:"10}})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10}})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4}})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0}})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js"}})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100"}})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001"}})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001", - "executionContextAuxData":{"a":1}, - "sourceMapURL":"usr/", - "hasSourceURL":true, - "isModule":true, - "length":34, - "stackTrace":{"callFrames":[{"callFrameId":"10","functionName":"name0", - "location":{"scriptId":"5","lineNumber":19},"url":"url7", - "scopeChain":[{"type":"global","object":{"type":"object"}}, {"type":"local","object":{"type":"object"}}], - "this":{"type":"object","subtype":"v128"}}]}, - "codeOffset":432, - "scriptLanguage":"JavaScript" - }})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001", - "executionContextAuxData":{"a":1}, - "sourceMapURL":"usr/", - "hasSourceURL":true, - "isModule":true, - "length":34, - "stackTrace":{"callFrames":[{"callFrameId":"10","functionName":"name0", - "location":{"scriptId":"5","lineNumber":19},"url":"url7", - "scopeChain":[{"type":"global","object":{"type":"object"}}, {"type":"local","object":{"type":"object"}}], - "this":{"type":"object","subtype":"v128"}}]}, - "codeOffset":432 - }})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001", - "executionContextAuxData":{"a":1}, - "sourceMapURL":"usr/", - "hasSourceURL":true, - "isModule":true, - "length":34, - "stackTrace":{"callFrames":[{"callFrameId":"10","functionName":"name0", - "location":{"scriptId":"5","lineNumber":19},"url":"url7", - "scopeChain":[{"type":"global","object":{"type":"object"}}, {"type":"local","object":{"type":"object"}}], - "this":{"type":"object","subtype":"v128"}}]} - }})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001", - "executionContextAuxData":{"a":1}, - "sourceMapURL":"usr/", - "hasSourceURL":true, - "isModule":true, - "length":34 - }})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001", - "executionContextAuxData":{"a":1}, - "sourceMapURL":"usr/", - "hasSourceURL":true, - "isModule":true - }})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001", - "executionContextAuxData":{"a":1}, - "sourceMapURL":"usr/", - "hasSourceURL":true - }})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001", - "executionContextAuxData":{"a":1}, - "sourceMapURL":"usr/" - }})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001", - "executionContextAuxData":{"a":1} - }})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001" - }})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001", - "executionContextAuxData":{"a":1}, - "sourceMapURL":"usr/", - "hasSourceURL":true, - "isModule":true, - "length":34, - "stackTrace":{"callFrames":[{"callFrameId":"10","functionName":"name0", - "location":{"scriptId":"5","lineNumber":19},"url":"url7", - "scopeChain":[{"type":"global","object":{"type":"object"}}, {"type":"local","object":{"type":"object"}}], - "this":{"type":"object","subtype":"v128"}}]}, - "codeOffset":432, - "scriptLanguage":"JavaScript", - "embedderName":"hh" - }})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(parse, nullptr); -} - HWTEST_F_L0(DebuggerEventsTest, ScriptFailedToParseToObjectTest) { CString msg; - std::unique_ptr parse; + ScriptFailedToParse parsed; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001", - "executionContextAuxData":{"a":1}, - "sourceMapURL":"usr/", - "hasSourceURL":true, - "isModule":true, - "length":34, - "stackTrace":{"callFrames":[{"callFrameId":"10","functionName":"name0", - "location":{"scriptId":"5","lineNumber":19},"url":"url7", - "scopeChain":[{"type":"global","object":{"type":"object"}}, {"type":"local","object":{"type":"object"}}], - "this":{"type":"object","subtype":"v128"}}]}, - "codeOffset":432, - "scriptLanguage":"JavaScript", - "embedderName":"hh" - }})"; - parse = ScriptFailedToParse::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(parse, nullptr); - - Local object1 = parse->ToObject(ecmaVm); + parsed.SetScriptId(100) + .SetUrl("use/test.js") + .SetStartLine(0) + .SetStartColumn(4) + .SetEndLine(10) + .SetEndColumn(10) + .SetExecutionContextId(2) + .SetHash("hash0001") + .SetSourceMapURL("usr/") + .SetHasSourceURL(true) + .SetIsModule(true) + .SetLength(34) + .SetCodeOffset(432) + .SetScriptLanguage("JavaScript") + .SetEmbedderName("hh"); + Local object1 = parsed.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); ASSERT_TRUE(result->IsObject()); @@ -603,10 +217,7 @@ HWTEST_F_L0(DebuggerEventsTest, ScriptFailedToParseToObjectTest) EXPECT_EQ("hash0001", DebuggerApi::ToCString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "executionContextAuxData"); - ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); - result = object->Get(ecmaVm, tmpStr); - ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - ASSERT_TRUE(result->IsObject()); + ASSERT_FALSE(object->Has(ecmaVm, tmpStr)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "sourceMapURL"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); @@ -651,158 +262,29 @@ HWTEST_F_L0(DebuggerEventsTest, ScriptFailedToParseToObjectTest) EXPECT_EQ("hh", DebuggerApi::ToCString(result)); } -HWTEST_F_L0(DebuggerEventsTest, ScriptParsedCreateTest) -{ - CString msg; - std::unique_ptr parse; - - // abnormal params of null msg - msg = CString() + R"({})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2}})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn:"10}})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10}})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4}})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0}})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js"}})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100"}})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001"}})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(parse, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"100", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001", - "executionContextAuxData":{"a":1}, - "isLiveEdit":true, - "sourceMapURL":"usr/", - "hasSourceURL":true, - "isModule":true, - "length":34, - "stackTrace":{"callFrames":[{"callFrameId":"10","functionName":"name0", - "location":{"scriptId":"5","lineNumber":19},"url":"url7", - "scopeChain":[{"type":"global","object":{"type":"object"}}, {"type":"local","object":{"type":"object"}}], - "this":{"type":"object","subtype":"v128"}}]}, - "codeOffset":432, - "scriptLanguage":"JavaScript", - "embedderName":"hh" - }})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(parse, nullptr); -} - HWTEST_F_L0(DebuggerEventsTest, ScriptParsedToObjectTest) { CString msg; - std::unique_ptr parse; + ScriptParsed parsed; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"scriptId":"10", - "url":"use/test.js", - "startLine":0, - "startColumn":4, - "endLine":10, - "endColumn":10, - "executionContextId":2, - "hash":"hash0001", - "executionContextAuxData":{"a":1}, - "isLiveEdit":true, - "sourceMapURL":"usr/", - "hasSourceURL":true, - "isModule":true, - "length":34, - "stackTrace":{"callFrames":[{"callFrameId":"10","functionName":"name0", - "location":{"scriptId":"5","lineNumber":19},"url":"url7", - "scopeChain":[{"type":"global","object":{"type":"object"}}, {"type":"local","object":{"type":"object"}}], - "this":{"type":"object","subtype":"v128"}}]}, - "codeOffset":432, - "scriptLanguage":"JavaScript", - "embedderName":"hh" - }})"; - parse = ScriptParsed::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(parse, nullptr); - - Local object1 = parse->ToObject(ecmaVm); + parsed.SetScriptId(10) + .SetUrl("use/test.js") + .SetStartLine(0) + .SetStartColumn(4) + .SetEndLine(10) + .SetEndColumn(10) + .SetExecutionContextId(2) + .SetHash("hash0001") + .SetIsLiveEdit(true) + .SetSourceMapURL("usr/") + .SetHasSourceURL(true) + .SetIsModule(true) + .SetLength(34) + .SetCodeOffset(432) + .SetScriptLanguage("JavaScript") + .SetEmbedderName("hh"); + Local object1 = parsed.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); ASSERT_TRUE(result->IsObject()); @@ -857,10 +339,7 @@ HWTEST_F_L0(DebuggerEventsTest, ScriptParsedToObjectTest) EXPECT_EQ("hash0001", DebuggerApi::ToCString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "executionContextAuxData"); - ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); - result = object->Get(ecmaVm, tmpStr); - ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - ASSERT_TRUE(result->IsObject()); + ASSERT_FALSE(object->Has(ecmaVm, tmpStr)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "isLiveEdit"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); @@ -911,54 +390,22 @@ HWTEST_F_L0(DebuggerEventsTest, ScriptParsedToObjectTest) EXPECT_EQ("hh", DebuggerApi::ToCString(result)); } -HWTEST_F_L0(DebuggerEventsTest, ConsoleProfileFinishedCreateTest) -{ - CString msg; - std::unique_ptr consoleProfileFinished; - - // abnormal params of null msg - msg = CString() + R"({})"; - consoleProfileFinished = ConsoleProfileFinished::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(consoleProfileFinished, nullptr); - - // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; - consoleProfileFinished = ConsoleProfileFinished::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(consoleProfileFinished, nullptr); - - // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; - consoleProfileFinished = ConsoleProfileFinished::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(consoleProfileFinished, nullptr); - - // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; - consoleProfileFinished = ConsoleProfileFinished::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(consoleProfileFinished, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ - "id":"11", - "location": {"scriptId":"13", "lineNumber":20}, - "profile": {"nodes":[], "startTime":0, "endTime":15, "samples":[], "timeDeltas":[]}, - "title":"001"}})"; - consoleProfileFinished = ConsoleProfileFinished::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(consoleProfileFinished, nullptr); -} - HWTEST_F_L0(DebuggerEventsTest, ConsoleProfileFinishedToObjectTest) { CString msg; - std::unique_ptr consoleProfileFinished; + ConsoleProfileFinished consoleProfileFinished; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ - "id":"11", - "location": {"scriptId":"13", "lineNumber":20}, - "profile": {"nodes":[], "startTime":0, "endTime":15, "samples":[], "timeDeltas":[]}, - "title":"001"}})"; - consoleProfileFinished = ConsoleProfileFinished::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(consoleProfileFinished, nullptr); - Local object1 = consoleProfileFinished->ToObject(ecmaVm); + auto location = std::make_unique(); + location->SetScriptId(13).SetLine(20); + auto profile = std::make_unique(); + profile->SetNodes(CVector>{}) + .SetStartTime(0) + .SetEndTime(15) + .SetSamples(CVector{}) + .SetTimeDeltas(CVector{}); + consoleProfileFinished.SetId("11").SetLocation(std::move(location)).SetProfile(std::move(profile)).SetTitle("001"); + Local object1 = consoleProfileFinished.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); ASSERT_TRUE(result->IsObject()); @@ -989,48 +436,16 @@ HWTEST_F_L0(DebuggerEventsTest, ConsoleProfileFinishedToObjectTest) EXPECT_EQ(DebuggerApi::ToCString(result), "001"); } -HWTEST_F_L0(DebuggerEventsTest, ConsoleProfileStartedCreateTest) -{ - CString msg; - std::unique_ptr consoleProfileStarted; - - // abnormal params of null msg - msg = CString() + R"({})"; - consoleProfileStarted = ConsoleProfileStarted::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(consoleProfileStarted, nullptr); - - // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; - consoleProfileStarted = ConsoleProfileStarted::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(consoleProfileStarted, nullptr); - - // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; - consoleProfileStarted = ConsoleProfileStarted::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(consoleProfileStarted, nullptr); - - // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; - consoleProfileStarted = ConsoleProfileStarted::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(consoleProfileStarted, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ - "id":"12","location":{"scriptId":"17","lineNumber":30},"title":"002"}})"; - consoleProfileStarted = ConsoleProfileStarted::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(consoleProfileStarted, nullptr); -} - HWTEST_F_L0(DebuggerEventsTest, ConsoleProfileStartedToObjectTest) { CString msg; - std::unique_ptr consoleProfileStarted; + ConsoleProfileStarted consoleProfileStarted; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ - "id":"12","location":{"scriptId":"17","lineNumber":30},"title":"002"}})"; - consoleProfileStarted = ConsoleProfileStarted::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(consoleProfileStarted, nullptr); - Local object1 = consoleProfileStarted->ToObject(ecmaVm); + auto location = std::make_unique(); + location->SetScriptId(17).SetLine(30); + consoleProfileStarted.SetId("12").SetLocation(std::move(location)).SetTitle("002"); + Local object1 = consoleProfileStarted.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); ASSERT_TRUE(result->IsObject()); @@ -1042,7 +457,7 @@ HWTEST_F_L0(DebuggerEventsTest, ConsoleProfileStartedToObjectTest) ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); EXPECT_EQ(DebuggerApi::ToCString(result), "12"); - Local tmpObject = consoleProfileStarted->GetLocation()->ToObject(ecmaVm); + Local tmpObject = consoleProfileStarted.GetLocation()->ToObject(ecmaVm); tmpStr = StringRef::NewFromUtf8(ecmaVm, "scriptId"); ASSERT_TRUE(tmpObject->Has(ecmaVm, tmpStr)); Local tmpResult = tmpObject->Get(ecmaVm, tmpStr); @@ -1061,48 +476,16 @@ HWTEST_F_L0(DebuggerEventsTest, ConsoleProfileStartedToObjectTest) EXPECT_EQ(DebuggerApi::ToCString(result), "002"); } -HWTEST_F_L0(DebuggerEventsTest, PreciseCoverageDeltaUpdateCreateTest) -{ - CString msg; - std::unique_ptr preciseCoverageDeltaUpdate; - - // abnormal params of null msg - msg = CString() + R"({})"; - preciseCoverageDeltaUpdate = PreciseCoverageDeltaUpdate::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(preciseCoverageDeltaUpdate, nullptr); - - // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; - preciseCoverageDeltaUpdate = PreciseCoverageDeltaUpdate::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(preciseCoverageDeltaUpdate, nullptr); - - // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; - preciseCoverageDeltaUpdate = PreciseCoverageDeltaUpdate::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(preciseCoverageDeltaUpdate, nullptr); - - // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; - preciseCoverageDeltaUpdate = PreciseCoverageDeltaUpdate::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(preciseCoverageDeltaUpdate, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ - "timestamp":77,"occasion":"percise","result":[]}})"; - preciseCoverageDeltaUpdate = PreciseCoverageDeltaUpdate::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(preciseCoverageDeltaUpdate, nullptr); -} - HWTEST_F_L0(DebuggerEventsTest, PreciseCoverageDeltaUpdateToObjectTest) { CString msg; - std::unique_ptr preciseCoverageDeltaUpdate; + PreciseCoverageDeltaUpdate preciseCoverageDeltaUpdate; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ - "timestamp":77,"occasion":"percise","result":[]}})"; - preciseCoverageDeltaUpdate = PreciseCoverageDeltaUpdate::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(preciseCoverageDeltaUpdate, nullptr); - Local object1 = preciseCoverageDeltaUpdate->ToObject(ecmaVm); + preciseCoverageDeltaUpdate.SetOccasion("percise") + .SetResult(CVector>{}) + .SetTimestamp(77); + Local object1 = preciseCoverageDeltaUpdate.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); ASSERT_TRUE(result->IsObject()); @@ -1125,46 +508,14 @@ HWTEST_F_L0(DebuggerEventsTest, PreciseCoverageDeltaUpdateToObjectTest) ASSERT_TRUE(result->IsArray(ecmaVm)); } -HWTEST_F_L0(DebuggerEventsTest, HeapStatsUpdateCreateTest) -{ - CString msg; - std::unique_ptr heapStatsUpdate; - - // abnormal params of null msg - msg = CString() + R"({})"; - heapStatsUpdate = HeapStatsUpdate::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(heapStatsUpdate, nullptr); - - // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; - heapStatsUpdate = HeapStatsUpdate::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(heapStatsUpdate, nullptr); - - // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; - heapStatsUpdate = HeapStatsUpdate::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(heapStatsUpdate, nullptr); - - // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; - heapStatsUpdate = HeapStatsUpdate::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(heapStatsUpdate, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"statsUpdate":[]}})"; - heapStatsUpdate = HeapStatsUpdate::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(heapStatsUpdate, nullptr); -} - HWTEST_F_L0(DebuggerEventsTest, HeapStatsUpdateToObjectTest) { CString msg; - std::unique_ptr heapStatsUpdate; + HeapStatsUpdate heapStatsUpdate; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"statsUpdate":[]}})"; - heapStatsUpdate = HeapStatsUpdate::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(heapStatsUpdate, nullptr); - Local object1 = heapStatsUpdate->ToObject(ecmaVm); + heapStatsUpdate.SetStatsUpdate(CVector {}); + Local object1 = heapStatsUpdate.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); ASSERT_TRUE(result->IsObject()); @@ -1177,46 +528,14 @@ HWTEST_F_L0(DebuggerEventsTest, HeapStatsUpdateToObjectTest) ASSERT_TRUE(result->IsArray(ecmaVm)); } -HWTEST_F_L0(DebuggerEventsTest, LastSeenObjectIdCreateTest) -{ - CString msg; - std::unique_ptr lastSeenObjectId; - - // abnormal params of null msg - msg = CString() + R"({})"; - lastSeenObjectId = LastSeenObjectId::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(lastSeenObjectId, nullptr); - - // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; - lastSeenObjectId = LastSeenObjectId::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(lastSeenObjectId, nullptr); - - // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; - lastSeenObjectId = LastSeenObjectId::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(lastSeenObjectId, nullptr); - - // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; - lastSeenObjectId = LastSeenObjectId::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(lastSeenObjectId, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"lastSeenObjectId":10,"timestamp":77}})"; - lastSeenObjectId = LastSeenObjectId::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(lastSeenObjectId, nullptr); -} - HWTEST_F_L0(DebuggerEventsTest, LastSeenObjectIdToObjectTest) { CString msg; - std::unique_ptr lastSeenObjectId; + LastSeenObjectId lastSeenObjectId; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"lastSeenObjectId":10,"timestamp":77}})"; - lastSeenObjectId = LastSeenObjectId::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(lastSeenObjectId, nullptr); - Local object1 = lastSeenObjectId->ToObject(ecmaVm); + lastSeenObjectId.SetLastSeenObjectId(10).SetTimestamp(77); + Local object1 = lastSeenObjectId.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); ASSERT_TRUE(result->IsObject()); @@ -1234,46 +553,14 @@ HWTEST_F_L0(DebuggerEventsTest, LastSeenObjectIdToObjectTest) EXPECT_EQ(Local(result)->Value(), 77); } -HWTEST_F_L0(DebuggerEventsTest, ReportHeapSnapshotProgressCreateTest) -{ - CString msg; - std::unique_ptr reportHeapSnapshotProgress; - - // abnormal params of null msg - msg = CString() + R"({})"; - reportHeapSnapshotProgress = ReportHeapSnapshotProgress::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(reportHeapSnapshotProgress, nullptr); - - // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; - reportHeapSnapshotProgress = ReportHeapSnapshotProgress::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(reportHeapSnapshotProgress, nullptr); - - // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; - reportHeapSnapshotProgress = ReportHeapSnapshotProgress::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(reportHeapSnapshotProgress, nullptr); - - // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; - reportHeapSnapshotProgress = ReportHeapSnapshotProgress::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - EXPECT_EQ(reportHeapSnapshotProgress, nullptr); - - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"done":10,"total":100}})"; - reportHeapSnapshotProgress = ReportHeapSnapshotProgress::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(reportHeapSnapshotProgress, nullptr); -} - HWTEST_F_L0(DebuggerEventsTest, ReportHeapSnapshotProgressToObjectTest) { CString msg; - std::unique_ptr reportHeapSnapshotProgress; + ReportHeapSnapshotProgress reportHeapSnapshotProgress; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"done":10,"total":100}})"; - reportHeapSnapshotProgress = ReportHeapSnapshotProgress::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); - ASSERT_NE(reportHeapSnapshotProgress, nullptr); - Local object1 = reportHeapSnapshotProgress->ToObject(ecmaVm); + reportHeapSnapshotProgress.SetDone(10).SetTotal(100); + Local object1 = reportHeapSnapshotProgress.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); ASSERT_TRUE(result->IsObject()); diff --git a/ecmascript/tooling/test/utils/test_hooks.h b/ecmascript/tooling/test/utils/test_hooks.h index 3ab19159e2..c5adf6c373 100644 --- a/ecmascript/tooling/test/utils/test_hooks.h +++ b/ecmascript/tooling/test/utils/test_hooks.h @@ -31,8 +31,8 @@ public: test_ = TestUtil::GetTest(testName); test_->vm_ = vm; test_->debugger_ = debugger_.get(); - test_->debugInterface_ = debugger_->GetDebugger(); - debugInterface_ = debugger_->GetDebugger(); + test_->debugInterface_ = debugger_->jsDebugger_; + debugInterface_ = debugger_->jsDebugger_; TestUtil::Reset(); debugInterface_->RegisterHooks(this); } From d79015d4a4a32d609904e1b3ca6a7ee04161a8bd Mon Sep 17 00:00:00 2001 From: zhangyukun Date: Tue, 31 May 2022 16:21:27 +0800 Subject: [PATCH 12/35] refactor rsp frame of arm64 1. adapt jscalldispatch 2. fix print(helloworld) Issue:https://gitee.com/openharmony/ark_js_runtime/issues/I5A78L?from=project-issue Signed-off-by: zhangyukun Change-Id: Ie6891d4fd812144dda4fd3a57c236eff5f276831 --- .../aarch64/assembler_aarch64_constants.h | 1 + .../assembler/aarch64/extend_assembler.cpp | 14 + .../assembler/aarch64/extend_assembler.h | 83 ++ ecmascript/compiler/bc_call_signature.h | 5 +- .../trampoline/aarch64/assembler_stubs.cpp | 874 ++++++++---------- .../trampoline/aarch64/assembler_stubs.h | 39 +- 6 files changed, 492 insertions(+), 524 deletions(-) diff --git a/ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h b/ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h index e0541c168f..88941ef154 100644 --- a/ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h +++ b/ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h @@ -22,6 +22,7 @@ enum RegisterId : uint8_t { X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, SP, Zero = SP, + FP = X29, INVALID_REG = 0xFF, }; diff --git a/ecmascript/compiler/assembler/aarch64/extend_assembler.cpp b/ecmascript/compiler/assembler/aarch64/extend_assembler.cpp index fbc9cc0f26..5c3a670278 100644 --- a/ecmascript/compiler/assembler/aarch64/extend_assembler.cpp +++ b/ecmascript/compiler/assembler/aarch64/extend_assembler.cpp @@ -16,6 +16,11 @@ #include "ecmascript/frames.h" namespace panda::ecmascript::aarch64 { +Register ExtendedAssembler::ghcJSCallDispacherArgs_[JS_CALL_DISPATCHER_ARGS_COUNT] = + { X19, FP, X20, X21, X22, X23, X24, X25 }; +Register ExtendedAssembler::cppJSCallDispacherArgs_[JS_CALL_DISPATCHER_ARGS_COUNT] = + { X0, FP, X1, X2, X3, X4, X5, INVALID_REG}; + void ExtendedAssembler::CalleeSave() { Register sp(SP); @@ -55,6 +60,15 @@ void ExtendedAssembler::BindAssemblerStub(int id) { Label *target = module_->GetFunctionLabel(id); Bind(target); + auto callSigns = module_->GetCSigns(); + auto cs = callSigns[id]; + isGhcCallingConv_ = cs->GetCallConv() == CallSignature::CallConv::GHCCallConv; +} + +void ExtendedAssembler::PushFpAndLr() +{ + Register sp(SP); + Stp(Register(X29), Register(X30), MemoryOperand(sp, -16, PREINDEX)); } void ExtendedAssembler::SaveFpAndLr() diff --git a/ecmascript/compiler/assembler/aarch64/extend_assembler.h b/ecmascript/compiler/assembler/aarch64/extend_assembler.h index e56003aac9..6ce250401c 100644 --- a/ecmascript/compiler/assembler/aarch64/extend_assembler.h +++ b/ecmascript/compiler/assembler/aarch64/extend_assembler.h @@ -17,6 +17,7 @@ #include "assembler_aarch64.h" #include "ecmascript/compiler/assembler_module.h" +#include "ecmascript/compiler/bc_call_signature.h" namespace panda::ecmascript::aarch64 { using namespace panda::ecmascript::kungfu; @@ -31,13 +32,95 @@ public: void CalleeSave(); void CalleeRestore(); void CallAssemblerStub(int id, bool isTail = false); + void PushFpAndLr(); void SaveFpAndLr(); void RestoreFpAndLr(); void PushArgsWithArgv(Register argc, Register argv, Register op, panda::ecmascript::Label *next); void PushArgc(int32_t argc, Register op); void PushArgc(Register argc, Register op); + + Register TempRegister1() + { + if (temp1InUse_) { + COMPILER_LOG(ERROR) << "temp register1 inuse."; + UNREACHABLE(); + } + temp1InUse_ = true; + return X7; + } + Register TempRegister2() + { + if (temp2InUse_) { + COMPILER_LOG(ERROR) << "temp register2 inuse."; + UNREACHABLE(); + } + temp2InUse_ = true; + return X16; + } + Register AvailableRegister1() const + { + // X17 is neither callee saved reegister nor argument register + return X17; + } + Register AvailableRegister2() const + { + // X18 is neither callee saved reegister nor argument register + return X18; + } + Register CallDispatcherArgument(kungfu::CallDispatchInputs index) + { + size_t i = static_cast(index); + return isGhcCallingConv_ ? ghcJSCallDispacherArgs_[i] : cppJSCallDispacherArgs_[i]; + } + Register GlueRegister() + { + return isGhcCallingConv_ ? X19 : X0; + } + + bool FromInterpreterHandler() const + { + return isGhcCallingConv_; + } private: AssemblerModule *module_ {nullptr}; + bool isGhcCallingConv_ {false}; + bool temp1InUse_ {false}; + bool temp2InUse_ {false}; + friend class TempRegister1Scope; + friend class TempRegister2Scope; + + static constexpr size_t JS_CALL_DISPATCHER_ARGS_COUNT = + static_cast(kungfu::CallDispatchInputs::NUM_OF_INPUTS); + static Register ghcJSCallDispacherArgs_[JS_CALL_DISPATCHER_ARGS_COUNT]; + static Register cppJSCallDispacherArgs_[JS_CALL_DISPATCHER_ARGS_COUNT]; +}; + +class TempRegister1Scope { +public: + explicit TempRegister1Scope(ExtendedAssembler *assembler) : assembler_(assembler) {} + ~TempRegister1Scope() + { + assembler_->temp1InUse_ = false; + } + + NO_COPY_SEMANTIC(TempRegister1Scope); + NO_MOVE_SEMANTIC(TempRegister1Scope); +private: + ExtendedAssembler *assembler_; +}; + +class TempRegister2Scope { +public: + explicit TempRegister2Scope(ExtendedAssembler *assembler) : assembler_(assembler) {} + ~TempRegister2Scope() + { + assembler_->temp2InUse_ = false; + } + + NO_COPY_SEMANTIC(TempRegister2Scope); + NO_MOVE_SEMANTIC(TempRegister2Scope); +private: + ExtendedAssembler *assembler_; }; } // panda::ecmascript::aarch64 #endif // ECMASCRIPT_COMPILER_AARCH64_EXTEND_ASSEMBLER_H \ No newline at end of file diff --git a/ecmascript/compiler/bc_call_signature.h b/ecmascript/compiler/bc_call_signature.h index e847220952..8ad5cbf93b 100644 --- a/ecmascript/compiler/bc_call_signature.h +++ b/ecmascript/compiler/bc_call_signature.h @@ -262,7 +262,10 @@ enum class CallDispatchInputs : size_t { ARG0, ARG1, ARG2, - NUM_OF_INPUTS + NUM_OF_INPUTS, + + ARGC = ARG0, + ARGV = ARG1, }; #define BYTECODE_STUB_END_ID BytecodeStubCSigns::ID_ExceptionHandler diff --git a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp index b8a3bfc388..4ca0628fb1 100644 --- a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp +++ b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp @@ -677,12 +677,7 @@ void AssemblerStubs::AsmInterpreterEntry(ExtendedAssembler *assembler) Register pcRegister(X21); PushAsmInterpEntryFrame(assembler, frameTypeRegister, prevFrameRegister, pcRegister); - Register tempRegister(X5); - __ Mov(tempRegister, Immediate(static_cast(kungfu::RuntimeStubCSigns::ID_JSCallDispatch))); - // 3 : 3 means *8 - __ Add(tempRegister, glueRegister, Operand(tempRegister, LSL, 3)); - __ Ldr(tempRegister, MemoryOperand(tempRegister, JSThread::GlueData::GetRTStubEntriesOffset(false))); - __ Blr(tempRegister); + __ CallAssemblerStub(RTSTUB_ID(JSCallDispatch), false); PopAsmInterpEntryFrame(assembler, prevFrameRegister); __ Ldr(glueRegister, MemoryOperand(spRegister, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); @@ -713,22 +708,24 @@ void AssemblerStubs::JSCallDispatch(ExtendedAssembler *assembler) Register methodRegister(X4); Register bitFieldRegister(X5); Register tempRegister(X6); // can not be used to store any variable + Register functionTypeRegister(X7, W); __ Ldr(callTargetRegister, MemoryOperand(argvRegister, 0)); __ Ldr(tempRegister, MemoryOperand(callTargetRegister, 0)); // hclass __ Ldr(bitFieldRegister, MemoryOperand(tempRegister, JSHClass::BIT_FIELD_OFFSET)); - __ Mov(tempRegister, Immediate(static_cast(JSType::JS_FUNCTION_BEGIN))); - __ Cmp(tempRegister, bitFieldRegister); + __ And(functionTypeRegister, bitFieldRegister.W(), LogicalImmediate::Create(0xFF, RegWSize)); + __ Mov(tempRegister.W(), Immediate(static_cast(JSType::JS_FUNCTION_BEGIN))); + __ Cmp(functionTypeRegister, tempRegister.W()); __ B(Condition::LO, ¬JSFunction); - __ Mov(tempRegister, Immediate(static_cast(JSType::JS_FUNCTION_END))); - __ Cmp(tempRegister, bitFieldRegister); + __ Mov(tempRegister.W(), Immediate(static_cast(JSType::JS_FUNCTION_END))); + __ Cmp(functionTypeRegister, tempRegister.W()); __ B(Condition::LS, &callJSFunctionEntry); __ Bind(¬JSFunction); { __ Tst(bitFieldRegister, LogicalImmediate::Create(static_cast(1ULL << JSHClass::CallableBit::START_BIT), RegXSize)); __ B(Condition::EQ, ¬Callable); - __ Mov(tempRegister, Immediate(static_cast(JSType::JS_PROXY))); - __ Cmp(tempRegister, bitFieldRegister); + __ Mov(tempRegister.W(), Immediate(static_cast(JSType::JS_PROXY))); + __ Cmp(functionTypeRegister, tempRegister.W()); __ B(Condition::EQ, &callJSProxyEntry); // bound function branch, default native __ Ldr(methodRegister, MemoryOperand(callTargetRegister, JSFunctionBase::METHOD_OFFSET)); @@ -752,6 +749,7 @@ void AssemblerStubs::JSCallDispatch(ExtendedAssembler *assembler) __ Cmp(declaredNumArgsRegister.W(), argcRegister); __ B(Condition::NE, &pushArgsSlowPath); // fast path + __ PushFpAndLr(); Register fpRegister(X10); __ Mov(fpRegister, Register(SP)); PushArgsFastPath(assembler, glueRegister, argcRegister, argvRegister, callTargetRegister, methodRegister, @@ -773,398 +771,300 @@ void AssemblerStubs::JSCallDispatch(ExtendedAssembler *assembler) } } +void AssemblerStubs::JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode mode, + const AssemblerClosure& fastEntry, + const AssemblerClosure& slowEntry) +{ + Register fpRegister = __ AvailableRegister1(); + Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD); + Register argcRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGC); + // save fp + __ Mov(fpRegister, Register(SP)); + + if (assembler->FromInterpreterHandler()) { + auto jumpSize = kungfu::AssemblerModule::GetJumpSizeFromJSCallMode(mode); + [[maybe_unused]] TempRegister1Scope scope1(assembler); + Register temp = __ TempRegister1(); + [[maybe_unused]] TempRegister2Scope scope2(assembler); + Register frameStateRegister = __ TempRegister2(); + __ Mov(temp, Immediate(static_cast(jumpSize))); + __ Sub(frameStateRegister, Register(FP), Immediate(AsmInterpretedFrame::GetSize(false))); + __ Str(temp, MemoryOperand(frameStateRegister, AsmInterpretedFrame::GetCallSizeOffset(false))); + } + + Register declaredNumArgsRegister = __ AvailableRegister2(); + GetDeclaredNumArgsFromCallField(assembler, callFieldRegister, declaredNumArgsRegister); + + Label slowPathEntry; + auto argc = kungfu::AssemblerModule::GetArgcFromJSCallMode(mode); + if (argc >= 0) { + __ Cmp(declaredNumArgsRegister, Immediate(argc)); + } else { + __ Cmp(declaredNumArgsRegister, argcRegister); + } + __ B(Condition::NE, &slowPathEntry); + fastEntry(assembler); + __ Bind(&slowPathEntry); + { + slowEntry(assembler); + } +} + // void PushCallArgsxAndDispatch(uintptr_t glue, uintptr_t sp, uint64_t callTarget, uintptr_t method, // uint64_t callField, ...) // GHC calling convention // Input1: for callarg0/1/2/3 Input2: for callrange // X19 - glue // X19 - glue -// X20 - sp // X20 - sp -// X21 - callTarget // X21 - callTarget -// X22 - method // X22 - method -// X23 - callField // X23 - callField -// X24 - arg0 // X24 - actualArgc -// X25 - arg1 // X25 - argv -// X26 - arg2 +// FP - sp // FP - sp +// X20 - callTarget // X20 - callTarget +// X21 - method // X21 - method +// X22 - callField // X22 - callField +// X23 - arg0 // X23 - actualArgc +// X24 - arg1 // X24 - argv +// X25 - arg2 void AssemblerStubs::PushCallIThisRangeAndDispatch(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(PushCallIThisRangeAndDispatch)); - - SaveFpAndJumpSize(assembler, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8))); - CallIThisRangeEntry(assembler); - __ Ret(); + JSCallCommonEntry(assembler, JSCallMode::CALL_THIS_WITH_ARGV, CallIThisRangeEntry, + PushCallIThisRangeAndDispatchSlowPath); } void AssemblerStubs::PushCallIRangeAndDispatch(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(PushCallIRangeAndDispatch)); - - SaveFpAndJumpSize(assembler, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8))); - CallIRangeEntry(assembler); - __ Ret(); + JSCallCommonEntry(assembler, JSCallMode::CALL_WITH_ARGV, CallIRangeEntry, PushCallIRangeAndDispatchSlowPath); } void AssemblerStubs::PushCallArgs3AndDispatch(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(PushCallArgs3AndDispatch)); - - SaveFpAndJumpSize(assembler, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8_V8_V8))); - Callargs3Entry(assembler); - __ Ret(); + JSCallCommonEntry(assembler, JSCallMode::CALL_ARG3, Callargs3Entry, PushCallArgs3AndDispatchSlowPath); } void AssemblerStubs::PushCallArgs2AndDispatch(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(PushCallArgs2AndDispatch)); - - SaveFpAndJumpSize(assembler, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8_V8))); - Callargs2Entry(assembler); - __ Ret(); + JSCallCommonEntry(assembler, JSCallMode::CALL_ARG2, Callargs2Entry, PushCallArgs2AndDispatchSlowPath); } void AssemblerStubs::PushCallArgs1AndDispatch(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(PushCallArgs1AndDispatch)); - - SaveFpAndJumpSize(assembler, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8))); - Callarg1Entry(assembler); - __ Ret(); + JSCallCommonEntry(assembler, JSCallMode::CALL_ARG1, Callarg1Entry, PushCallArgs1AndDispatchSlowPath); } void AssemblerStubs::PushCallArgs0AndDispatch(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(PushCallArgs0AndDispatch)); + JSCallCommonEntry(assembler, JSCallMode::CALL_ARG0, PushCallThisUndefined, // Callarg0Entry + PushCallArgs0AndDispatchSlowPath); +} - SaveFpAndJumpSize(assembler, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8))); - PushCallThisUndefined(assembler); // Callarg0Entry - __ Ret(); +void AssemblerStubs::JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode, + const AssemblerClosure& entry, + const AssemblerClosure& extraEntry) +{ + Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD); + Register argcRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGC); + + Label haveExtraEntry; + Label pushArgsNoExtraEntry; + Label pushArgsEntry; + + auto argc = kungfu::AssemblerModule::GetArgcFromJSCallMode(mode); + Register declaredNumArgsRegister = __ AvailableRegister2(); + __ Tbnz(callFieldRegister, JSMethod::HaveExtraBit::START_BIT, &haveExtraEntry); + { + if (argc == 0) { + { + [[maybe_unused]] TempRegister1Scope scope(assembler); + Register tempRegister = __ TempRegister1(); + PushUndefinedWithArgc(assembler, declaredNumArgsRegister, tempRegister, nullptr); + } + entry(assembler); + return; + } + [[maybe_unused]] TempRegister1Scope scope(assembler); + Register diffRegister = __ TempRegister1(); + if (argc >= 0) { + __ Sub(diffRegister.W(), declaredNumArgsRegister.W(), Immediate(argc)); + } else { + __ Sub(diffRegister.W(), declaredNumArgsRegister.W(), argcRegister.W()); + } + [[maybe_unused]] TempRegister2Scope scope2(assembler); + Register tempRegister = __ TempRegister2(); + PushUndefinedWithArgc(assembler, diffRegister, tempRegister, &pushArgsNoExtraEntry); + __ Bl(&pushArgsNoExtraEntry); + } + __ Bind(&haveExtraEntry); + { + if (argc == 0) { + [[maybe_unused]] TempRegister1Scope scope(assembler); + Register tempRegister = __ TempRegister1(); + __ PushArgc(argc, tempRegister); + PushUndefinedWithArgc(assembler, declaredNumArgsRegister, tempRegister, nullptr); + extraEntry(assembler); + return; + } + [[maybe_unused]] TempRegister1Scope scope2(assembler); + Register tempArgcRegister = __ TempRegister1(); + if (argc >= 0) { + __ PushArgc(argc, tempArgcRegister); + } else { + __ PushArgc(argcRegister, tempArgcRegister); + } + if (argc >= 0) { + __ Sub(tempArgcRegister.W(), declaredNumArgsRegister.W(), Immediate(argc)); + } else { + __ Sub(tempArgcRegister.W(), declaredNumArgsRegister.W(), argcRegister.W()); + } + [[maybe_unused]] TempRegister2Scope scope(assembler); + Register tempRegister = __ TempRegister2(); + PushUndefinedWithArgc(assembler, tempArgcRegister, tempRegister, &pushArgsEntry); + __ Bl(&pushArgsEntry); + } + __ Bind(&pushArgsNoExtraEntry); + { + entry(assembler); + } + __ Bind(&pushArgsEntry); + { + extraEntry(assembler); + } } // void PushCallArgsxAndDispatchSlowPath(uintptr_t glue, uintptr_t sp, uint64_t callTarget, uintptr_t method, // uint64_t callField, ...) // GHC calling convention -// Input1: for callarg0/1/2/3 Input2: for callrange +// Input1: for callarg0/1/2/3 Input2: for callrange // X19 - glue // X19 - glue -// X20 - sp // X20 - sp -// X21 - callTarget // X21 - callTarget -// X22 - method // X22 - method -// X23 - callField // X23 - callField -// X24 - arg0 // X24 - actualArgc -// X25 - arg1 // X25 - argv -// X26 - arg2 +// FP - sp // FP - sp +// X20 - callTarget // X20 - callTarget +// X21 - method // X21 - method +// X22 - callField // X22 - callField +// X23 - arg0 // X23 - actualArgc +// X24 - arg1 // X24 - argv +// X25 - arg2 void AssemblerStubs::PushCallIThisRangeAndDispatchSlowPath(ExtendedAssembler *assembler) { - Register callField(X23); - Register argc(X25); - - Label haveExtraEntry; - Label pushArgsNoExtraEntry; - Label pushArgsEntry; - - SaveFpAndJumpSize(assembler, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8))); - Register declaredNumArgs(X3); - Register diff(X4); - Register temp(X5); - GetDeclaredNumArgsFromCallField(assembler, callField, declaredNumArgs); - __ Sub(diff.W(), declaredNumArgs.W(), argc.W()); - __ Tbnz(callField, JSMethod::HaveExtraBit::START_BIT, &haveExtraEntry); - // fall through: no extra - PushUndefinedWithArgc(assembler, diff, temp, &pushArgsNoExtraEntry); - __ Bl(&pushArgsNoExtraEntry); - - __ Bind(&haveExtraEntry); - { - __ PushArgc(argc, temp); - PushUndefinedWithArgc(assembler, diff, temp, &pushArgsEntry); - __ Bl(&pushArgsEntry); - } - - __ Bind(&pushArgsNoExtraEntry); - { - CallIThisRangeNoExtraEntry(assembler, declaredNumArgs); - } - __ Bind(&pushArgsEntry); - { - CallIThisRangeEntry(assembler); - } - __ Ret(); + JSCallCommonSlowPath(assembler, JSCallMode::CALL_THIS_WITH_ARGV, CallIThisRangeNoExtraEntry, CallIThisRangeEntry); } void AssemblerStubs::PushCallIRangeAndDispatchSlowPath(ExtendedAssembler *assembler) { - Register callField(X23); - Register argc(X25); - - Label haveExtraEntry; - Label pushArgsNoExtraEntry; - Label pushArgsEntry; - - SaveFpAndJumpSize(assembler, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8))); - Register declaredNumArgs(X3); - Register diff(X4); - Register temp(X5); - GetDeclaredNumArgsFromCallField(assembler, callField, declaredNumArgs); - __ Sub(diff.W(), declaredNumArgs.W(), argc.W()); - __ Tbnz(callField, JSMethod::HaveExtraBit::START_BIT, &haveExtraEntry); - // fall through: no extra - PushUndefinedWithArgc(assembler, diff, temp, &pushArgsNoExtraEntry); - __ Bl(&pushArgsNoExtraEntry); - - __ Bind(&haveExtraEntry); - { - __ PushArgc(argc, temp); - PushUndefinedWithArgc(assembler, diff, temp, &pushArgsEntry); - __ Bl(&pushArgsEntry); - } - - __ Bind(&pushArgsNoExtraEntry); - { - CallIRangeNoExtraEntry(assembler, declaredNumArgs); - } - __ Bind(&pushArgsEntry); - { - CallIRangeEntry(assembler); - } - __ Ret(); + JSCallCommonSlowPath(assembler, JSCallMode::CALL_WITH_ARGV, CallIRangeNoExtraEntry, CallIRangeEntry); } void AssemblerStubs::PushCallArgs3AndDispatchSlowPath(ExtendedAssembler *assembler) { - Register callField(X23); - constexpr int32_t argc = 3; - - Label haveExtraEntry; - Label pushArgsNoExtraEntry; - Label pushArgsEntry; - - SaveFpAndJumpSize(assembler, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8_V8_V8))); - Register declaredNumArgs(X3); - Register diff(X4); - Register temp(X5); - GetDeclaredNumArgsFromCallField(assembler, callField, declaredNumArgs); - __ Subs(diff.W(), declaredNumArgs.W(), Immediate(argc)); - __ Tbnz(callField, JSMethod::HaveExtraBit::START_BIT, &haveExtraEntry); - // fall through: no extra - PushUndefinedWithArgc(assembler, diff, temp, &pushArgsNoExtraEntry); - __ Bl(&pushArgsNoExtraEntry); - - __ Bind(&haveExtraEntry); - { - __ PushArgc(argc, temp); - PushUndefinedWithArgc(assembler, diff, temp, &pushArgsEntry); - __ Bl(&pushArgsEntry); - } - - __ Bind(&pushArgsNoExtraEntry); - { - Callargs3NoExtraEntry(assembler, declaredNumArgs); - } - __ Bind(&pushArgsEntry); - { - Callargs3Entry(assembler); - } - __ Ret(); + JSCallCommonSlowPath(assembler, JSCallMode::CALL_ARG3, Callargs3NoExtraEntry, Callargs3Entry); } void AssemblerStubs::PushCallArgs2AndDispatchSlowPath(ExtendedAssembler *assembler) { - Register callField(X23); - constexpr int32_t argc = 2; - - Label haveExtraEntry; - Label pushArgsNoExtraEntry; - Label pushArgsEntry; - - SaveFpAndJumpSize(assembler, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8_V8))); - Register declaredNumArgs(X3); - Register diff(X4); - Register temp(X5); - GetDeclaredNumArgsFromCallField(assembler, callField, declaredNumArgs); - __ Subs(diff.W(), declaredNumArgs.W(), Immediate(argc)); - __ Tbnz(callField, JSMethod::HaveExtraBit::START_BIT, &haveExtraEntry); - // fall through: no extra - PushUndefinedWithArgc(assembler, diff, temp, &pushArgsNoExtraEntry); - __ Bl(&pushArgsNoExtraEntry); - - __ Bind(&haveExtraEntry); - { - __ PushArgc(argc, temp); - PushUndefinedWithArgc(assembler, diff, temp, &pushArgsEntry); - __ Bl(&pushArgsEntry); - } - - __ Bind(&pushArgsNoExtraEntry); - { - Callargs2NoExtraEntry(assembler, declaredNumArgs); - } - __ Bind(&pushArgsEntry); - { - Callargs2Entry(assembler); - } - __ Ret(); + JSCallCommonSlowPath(assembler, JSCallMode::CALL_ARG2, Callargs2NoExtraEntry, Callargs2Entry); } void AssemblerStubs::PushCallArgs1AndDispatchSlowPath(ExtendedAssembler *assembler) { - Register callField(X23); - constexpr int32_t argc = 1; - - Label haveExtraEntry; - Label pushArgsNoExtraEntry; - Label pushArgsEntry; - - SaveFpAndJumpSize(assembler, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8))); - Register declaredNumArgs(X3); - Register diff(X4); - Register temp(X5); - GetDeclaredNumArgsFromCallField(assembler, callField, declaredNumArgs); - __ Subs(diff.W(), declaredNumArgs.W(), Immediate(argc)); - __ Tbnz(callField, JSMethod::HaveExtraBit::START_BIT, &haveExtraEntry); - // fall through: no extra - PushUndefinedWithArgc(assembler, diff, temp, &pushArgsNoExtraEntry); - __ Bl(&pushArgsNoExtraEntry); - - __ Bind(&haveExtraEntry); - { - __ PushArgc(argc, temp); - PushUndefinedWithArgc(assembler, diff, temp, &pushArgsEntry); - __ Bl(&pushArgsEntry); - } - - __ Bind(&pushArgsNoExtraEntry); - { - Callargs1NoExtraEntry(assembler, declaredNumArgs); - } - __ Bind(&pushArgsEntry); - { - Callarg1Entry(assembler); - } - __ Ret(); + JSCallCommonSlowPath(assembler, JSCallMode::CALL_ARG1, Callargs1NoExtraEntry, Callarg1Entry); } void AssemblerStubs::PushCallArgs0AndDispatchSlowPath(ExtendedAssembler *assembler) { - Register callField(X23); - constexpr int32_t argc = 0; - - Label haveExtraEntry; - Label pushArgsNoExtraEntry; - Label pushArgsEntry; - - SaveFpAndJumpSize(assembler, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8))); - Register declaredNumArgs(X3); - Register diff(X4); - Register temp(X5); - GetDeclaredNumArgsFromCallField(assembler, callField, declaredNumArgs); - __ Subs(diff.W(), declaredNumArgs.W(), Immediate(argc)); - __ Tbnz(callField, JSMethod::HaveExtraBit::START_BIT, &haveExtraEntry); - // fall through: no extra - PushUndefinedWithArgc(assembler, diff, temp, &pushArgsNoExtraEntry); - __ Bl(&pushArgsNoExtraEntry); - - __ Bind(&haveExtraEntry); - { - __ PushArgc(argc, temp); - PushUndefinedWithArgc(assembler, diff, temp, &pushArgsEntry); - __ Bl(&pushArgsEntry); - } - - __ Bind(&pushArgsNoExtraEntry); - { - Callargs0NoExtraEntry(assembler); - } - __ Bind(&pushArgsEntry); - { - PushCallThisUndefined(assembler); - } - __ Ret(); + JSCallCommonSlowPath(assembler, JSCallMode::CALL_ARG0, PushCallThisUndefined, PushCallThisUndefined); } -// Input: X24 - actualArgc -// X25 - argv -void AssemblerStubs::CallIThisRangeNoExtraEntry(ExtendedAssembler *assembler, Register declaredNumArgs) +void AssemblerStubs::CallIThisRangeNoExtraEntry(ExtendedAssembler *assembler) { - Register argc(X24); - Register argv(X25); - Register op(X5); - Register opArgv(X6); + Register argcRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGC); + Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGV); + + Register declaredNumArgsRegister = __ AvailableRegister2(); Label pushCallThis; - Register numRegister = declaredNumArgs; - __ Cmp(declaredNumArgs.W(), argc.W()); - __ CMov(numRegister.W(), declaredNumArgs.W(), argc.W(), Condition::LO); - __ Mov(opArgv, argv); - __ PushArgsWithArgv(numRegister, opArgv, op, &pushCallThis); + Register numRegister = declaredNumArgsRegister; + __ Cmp(declaredNumArgsRegister.W(), argcRegister.W()); + __ CMov(numRegister.W(), declaredNumArgsRegister.W(), argcRegister.W(), Condition::LO); + { + [[maybe_unused]] TempRegister1Scope scope1(assembler); + Register opArgvRegister = __ TempRegister1(); + [[maybe_unused]] TempRegister2Scope scope2(assembler); + Register opRegister = __ TempRegister2(); + __ Mov(opArgvRegister, argvRegister); + __ PushArgsWithArgv(numRegister, opArgvRegister, opRegister, &pushCallThis); + } __ Bind(&pushCallThis); { - PushCallThis(assembler); + Register thisRegister = __ AvailableRegister2(); + __ Ldr(thisRegister, MemoryOperand(argvRegister, -8)); // 8: this is just before the argv list + PushCallThis(assembler, thisRegister, false); } } -// Input: X24 - actualArgc -// X25 - argv -void AssemblerStubs::CallIRangeNoExtraEntry(ExtendedAssembler *assembler, Register declaredNumArgs) +void AssemblerStubs::CallIRangeNoExtraEntry(ExtendedAssembler *assembler) { - Register argc(X24); - Register argv(X25); - Register op(X5); - Register opArgv(X6); + Register argcRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGC); + Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGV); + Register declaredNumArgsRegister = __ AvailableRegister2(); Label pushCallThisUndefined; - Register numRegister = declaredNumArgs; - __ Cmp(declaredNumArgs.W(), argc.W()); - __ CMov(numRegister.W(), declaredNumArgs.W(), argc.W(), Condition::LO); - __ Mov(opArgv, argv); - __ PushArgsWithArgv(numRegister, opArgv, op, &pushCallThisUndefined); + Register numRegister = declaredNumArgsRegister; + __ Cmp(declaredNumArgsRegister.W(), argcRegister.W()); + __ CMov(numRegister.W(), declaredNumArgsRegister.W(), argcRegister.W(), Condition::LO); + { + [[maybe_unused]] TempRegister1Scope scope1(assembler); + Register opArgvRegister = __ TempRegister1(); + [[maybe_unused]] TempRegister2Scope scope2(assembler); + Register opRegister = __ TempRegister2(); + __ Mov(opArgvRegister, argvRegister); + __ PushArgsWithArgv(numRegister, opArgvRegister, opRegister, &pushCallThisUndefined); + } __ Bind(&pushCallThisUndefined); { PushCallThisUndefined(assembler); } } -// Input: X24 - arg0 -// X25 - arg1 -// X26 - arg2 -void AssemblerStubs::Callargs3NoExtraEntry(ExtendedAssembler *assembler, Register declaredNumArgs) +void AssemblerStubs::Callargs3NoExtraEntry(ExtendedAssembler *assembler) { constexpr int32_t argc = 3; + Register arg2Register = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG2); + Register declaredNumArgsRegister = __ AvailableRegister2(); Label callargs2NoExtraEntry; - __ Cmp(declaredNumArgs, Immediate(argc)); + __ Cmp(declaredNumArgsRegister, Immediate(argc)); __ B(Condition::LO, &callargs2NoExtraEntry); - __ Str(Register(X26), MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // arg2 + __ Str(arg2Register, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // fall through __ Bind(&callargs2NoExtraEntry); - Callargs2NoExtraEntry(assembler, declaredNumArgs); + Callargs2NoExtraEntry(assembler); } -// Input: X24 - arg0 -// X25 - arg1 -void AssemblerStubs::Callargs2NoExtraEntry(ExtendedAssembler *assembler, Register declaredNumArgs) +void AssemblerStubs::Callargs2NoExtraEntry(ExtendedAssembler *assembler) { constexpr int32_t argc = 2; + Register arg1Register = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1); + Register declaredNumArgsRegister = __ AvailableRegister2(); Label callargs1NoExtraEntry; - __ Cmp(declaredNumArgs, Immediate(argc)); + __ Cmp(declaredNumArgsRegister, Immediate(argc)); __ B(Condition::LO, &callargs1NoExtraEntry); - __ Str(Register(X25), MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // arg1 + __ Str(arg1Register, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // fall through __ Bind(&callargs1NoExtraEntry); - Callargs1NoExtraEntry(assembler, declaredNumArgs); + Callargs1NoExtraEntry(assembler); } -// Input: X24 - arg0 -void AssemblerStubs::Callargs1NoExtraEntry(ExtendedAssembler *assembler, Register declaredNumArgs) +void AssemblerStubs::Callargs1NoExtraEntry(ExtendedAssembler *assembler) { constexpr int32_t argc = 1; + Register arg0Register = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0); + Register declaredNumArgsRegister = __ AvailableRegister2(); Label callargs0NoExtraEntry; - __ Cmp(declaredNumArgs, Immediate(argc)); + __ Cmp(declaredNumArgsRegister, Immediate(argc)); __ B(Condition::LO, &callargs0NoExtraEntry); - __ Str(Register(X24), MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // arg0 + __ Str(arg0Register, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // arg0 // fall through __ Bind(&callargs0NoExtraEntry); - Callargs0NoExtraEntry(assembler); -} - -void AssemblerStubs::Callargs0NoExtraEntry(ExtendedAssembler *assembler) -{ PushCallThisUndefined(assembler); } @@ -1241,11 +1141,11 @@ void AssemblerStubs::PushCallArgsAndDispatchNative(ExtendedAssembler *assembler) __ BindAssemblerStub(RTSTUB_ID(PushCallArgsAndDispatchNative)); Register glue(X0); - Register nativeCode(X1); + Register nativeCode = __ AvailableRegister1(); Register argc(X4); Register argv(X5); Register temp(X6); - Register fp(X20); + Register fp(FP); PushBuiltinFrame(assembler, glue, FrameType::BUILTIN_FRAME, temp); @@ -1259,10 +1159,8 @@ void AssemblerStubs::PushCallArgsAndDispatchNative(ExtendedAssembler *assembler) void AssemblerStubs::PushBuiltinFrame(ExtendedAssembler *assembler, Register glue, FrameType type, Register op) { - Register sp(X20); - __ Str(sp, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - __ Mov(sp, Register(SP)); - __ Str(sp, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); + __ SaveFpAndLr(); + __ Str(Register(FP), MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); __ Mov(op, Immediate(static_cast(type))); __ Str(op, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); } @@ -1277,40 +1175,41 @@ void AssemblerStubs::CallNativeInternal(ExtendedAssembler *assembler, Register g __ Mov(Register(X0), Register(SP)); __ Blr(nativeCode); // resume rsp - __ Mov(Register(SP), Register(X20)); - __ Ldr(Register(X20), MemoryOperand(Register(SP), FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); + __ Mov(Register(SP), Register(FP)); + __ RestoreFpAndLr(); } // ResumeRspAndDispatch(uintptr_t glue, uintptr_t sp, uintptr_t pc, uintptr_t constantPool, // uint64_t profileTypeInfo, uint64_t acc, uint32_t hotnessCounter, size_t jumpSize) // GHC calling convention // X19 - glue -// X20 - sp -// X21 - pc -// X22 - constantPool -// X23 - profileTypeInfo -// X24 - acc -// X25 - hotnessCounter -// X26 - jumpSizeAfterCall +// FP - sp +// X20 - pc +// X21 - constantPool +// X22 - profileTypeInfo +// X23 - acc +// X24 - hotnessCounter +// X25 - jumpSizeAfterCall void AssemblerStubs::ResumeRspAndDispatch(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(ResumeRspAndDispatch)); - Register glue(X19); - Register sp(X20); - Register pc(X21); - Register jumpSize(X26); - Register frameState(X5); + Register glueRegister = __ GlueRegister(); + Register sp(FP); + Register pc(X20); + Register jumpSize(X25); + Register opcode(X6, W); Register bcStub(X7); + Register frameStateRegister(X16); - __ Sub(frameState, sp, Immediate(sizeof(AsmInterpretedFrame))); - __ Ldr(Register(SP), MemoryOperand(frameState, AsmInterpretedFrame::GetFpOffset(false))); // resume rsp - __ Ldr(sp, MemoryOperand(frameState, AsmInterpretedFrame::GetBaseOffset(false))); // update sp + __ Sub(frameStateRegister, sp, Immediate(AsmInterpretedFrame::GetSize(false))); + __ Ldr(Register(SP), MemoryOperand(frameStateRegister, AsmInterpretedFrame::GetFpOffset(false))); // resume rsp + __ Ldr(sp, MemoryOperand(frameStateRegister, AsmInterpretedFrame::GetBaseOffset(false))); // update sp __ Add(pc, pc, Operand(jumpSize, LSL, 0)); __ Ldrb(opcode, MemoryOperand(pc, 0)); - __ Add(bcStub, glue, Operand(opcode, LSL, 3)); // 3: bc * 8 + __ Add(bcStub, glueRegister, Operand(opcode, UXTW, 3)); // 3: bc * 8 __ Ldr(bcStub, MemoryOperand(bcStub, JSThread::GlueData::GetBCStubEntriesOffset(false))); __ Br(bcStub); } @@ -1320,27 +1219,39 @@ void AssemblerStubs::ResumeRspAndReturn([[maybe_unused]] ExtendedAssembler *asse __ BindAssemblerStub(RTSTUB_ID(ResumeRspAndReturn)); Register sp(SP); Register lr(X30); - // 2 :2 means stack frame slot size - __ Ldr(lr, MemoryOperand(sp, FRAME_SLOT_SIZE * 2, AddrMode::POSTINDEX)); - __ Ret(); + + [[maybe_unused]] TempRegister1Scope scope1(assembler); + Register fpRegister = __ TempRegister1(); + [[maybe_unused]] TempRegister2Scope scope2(assembler); + Register frameStateRegister = __ TempRegister2(); + __ Sub(frameStateRegister, Register(FP), Immediate(AsmInterpretedFrame::GetSize(false))); + __ Ldr(fpRegister, MemoryOperand(frameStateRegister, AsmInterpretedFrame::GetFpOffset(false))); + __ Mov(sp, fpRegister); + + // return + { + __ RestoreFpAndLr(); + __ Mov(Register(X0), Register(X19)); + __ Ret(); + } } // ResumeCaughtFrameAndDispatch(uintptr_t glue, uintptr_t sp, uintptr_t pc, uintptr_t constantPool, // uint64_t profileTypeInfo, uint64_t acc, uint32_t hotnessCounter) // GHC calling convention // X19 - glue -// X20 - sp -// X21 - pc -// X22 - constantPool -// X23 - profileTypeInfo -// X24 - acc -// X25 - hotnessCounter +// FP - sp +// X20 - pc +// X21 - constantPool +// X22 - profileTypeInfo +// X23 - acc +// X24 - hotnessCounter void AssemblerStubs::ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(ResumeCaughtFrameAndDispatch)); Register glue(X19); - Register pc(X21); + Register pc(X20); Register fp(X5); Register opcode(X6, W); Register bcStub(X7); @@ -1352,7 +1263,7 @@ void AssemblerStubs::ResumeCaughtFrameAndDispatch(ExtendedAssembler *assembler) __ Bind(&dispatch); { __ Ldrb(opcode, MemoryOperand(pc, 0)); - __ Add(bcStub, glue, Operand(opcode, LSL, 3)); // 3: bc * 8 + __ Add(bcStub, glue, Operand(opcode, UXTW, 3)); // 3: bc * 8 __ Ldr(bcStub, MemoryOperand(bcStub, JSThread::GlueData::GetBCStubEntriesOffset(false))); __ Br(bcStub); } @@ -1409,7 +1320,7 @@ void AssemblerStubs::GeneratorReEnterAsmInterp(ExtendedAssembler *assembler) Register pc(X21); PushAsmInterpEntryFrame(assembler, frameTypeRegister, prevFrameRegister, pc); - Register prevSpRegister(X29); + Register prevSpRegister(FP); Register callTarget(X4); Register method(X5); Register temp(X6); // can not be used to store any variable @@ -1433,7 +1344,7 @@ void AssemblerStubs::GeneratorReEnterAsmInterp(ExtendedAssembler *assembler) method, contextRegister, pc, temp); // call bc stub - CallBCStub(assembler, newSp, glue, callTarget, method, pc, temp, false); + CallBCStub(assembler, newSp, glue, callTarget, method, pc, temp); PopAsmInterpEntryFrame(assembler, prevFrameRegister); __ Ldr(glue, MemoryOperand(spRegister, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); @@ -1442,42 +1353,47 @@ void AssemblerStubs::GeneratorReEnterAsmInterp(ExtendedAssembler *assembler) __ Ret(); } -// Input: X24 - actualArgc -// X25 - argv void AssemblerStubs::CallIThisRangeEntry(ExtendedAssembler *assembler) { - Register argc(X24); - Register argv(X25); - Register opArgc(X3); - Register opArgv(X4); - Register op(X5); + Register argcRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGC); + Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGV); + Label pushCallThis; - __ Mov(opArgc, argc); - __ Mov(opArgv, argv); - __ PushArgsWithArgv(opArgc, opArgv, op, &pushCallThis); + Register numRegister = __ AvailableRegister2(); + { + __ Mov(numRegister, argcRegister); + [[maybe_unused]] TempRegister1Scope scope1(assembler); + Register opArgvRegister = __ TempRegister1(); + [[maybe_unused]] TempRegister2Scope scope2(assembler); + Register opRegister = __ TempRegister2(); + __ Mov(opArgvRegister, argvRegister); + __ PushArgsWithArgv(numRegister, opArgvRegister, opRegister, &pushCallThis); + } __ Bind(&pushCallThis); - PushCallThis(assembler); + Register thisRegister = __ AvailableRegister2(); + __ Ldr(thisRegister, MemoryOperand(argvRegister, -8)); // 8: this is just before the argv list + PushCallThis(assembler, thisRegister, false); } -// Input: X23 - callField -// X25 - argv -void AssemblerStubs::PushCallThis(ExtendedAssembler *assembler) +void AssemblerStubs::PushCallThis(ExtendedAssembler *assembler, Register thisRegister, bool isUndefined) { - Register callField(X23); - Register argv(X25); + Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD); Register sp(SP); - Register thisObj(X5); Label pushVregs; Label pushNewTarget; - __ Tst(callField, LogicalImmediate::Create(CALL_TYPE_MASK, RegXSize)); + __ Tst(callFieldRegister, LogicalImmediate::Create(CALL_TYPE_MASK, RegXSize)); __ B(Condition::EQ, &pushVregs); // fall through - __ Tbz(callField, JSMethod::HaveThisBit::START_BIT, &pushNewTarget); - // 8: this is just before the argv list - __ Ldr(thisObj, MemoryOperand(argv, -8)); - __ Str(thisObj, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + __ Tbz(callFieldRegister, JSMethod::HaveThisBit::START_BIT, &pushNewTarget); + if (isUndefined) { + [[maybe_unused]] TempRegister1Scope scope1(assembler); + Register tempRegister = __ TempRegister1(); + __ Mov(tempRegister, Immediate(JSTaggedValue::VALUE_UNDEFINED)); + } else { + __ Str(thisRegister, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + } // fall through __ Bind(&pushNewTarget); { @@ -1489,174 +1405,142 @@ void AssemblerStubs::PushCallThis(ExtendedAssembler *assembler) } } -// Input: X24 - actualArgc -// X25 - argv void AssemblerStubs::CallIRangeEntry(ExtendedAssembler *assembler) { - Register argc(X24); - Register argv(X25); - Register opArgc(X3); - Register opArgv(X4); - Register op(X5); + Register argcRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGC); + Register argvRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARGV); + Label pushCallThisUndefined; - __ Mov(opArgc, argc); - __ Mov(opArgv, argv); - __ PushArgsWithArgv(opArgc, opArgv, op, &pushCallThisUndefined); + Register numRegister = __ AvailableRegister2(); + { + __ Mov(numRegister, argcRegister); + [[maybe_unused]] TempRegister1Scope scope1(assembler); + Register opArgvRegister = __ TempRegister1(); + [[maybe_unused]] TempRegister2Scope scope2(assembler); + Register opRegister = __ TempRegister2(); + __ Mov(opArgvRegister, argvRegister); + __ PushArgsWithArgv(numRegister, opArgvRegister, opRegister, &pushCallThisUndefined); + } __ Bind(&pushCallThisUndefined); PushCallThisUndefined(assembler); } -// Input: X24 - arg0 -// X25 - arg1 -// X26 - arg2 void AssemblerStubs::Callargs3Entry(ExtendedAssembler *assembler) { - __ Str(Register(X26), MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // arg2 + Register arg2Register = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG2); + __ Str(arg2Register, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); Callargs2Entry(assembler); } -// Input: X24 - arg0 -// X25 - arg1 void AssemblerStubs::Callargs2Entry(ExtendedAssembler *assembler) { - __ Str(Register(X25), MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // arg1 + Register arg1Register = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1); + __ Str(arg1Register, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); Callarg1Entry(assembler); } -// Input: X24 - arg0 void AssemblerStubs::Callarg1Entry(ExtendedAssembler *assembler) { - __ Str(Register(X24), MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // arg0 + Register arg0Register = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0); + __ Str(arg0Register, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); PushCallThisUndefined(assembler); } -// Input: X23 - callField void AssemblerStubs::PushCallThisUndefined(ExtendedAssembler *assembler) { - Register callField(X23); - Register thisObj(X3); - - Label pushVregs; - Label pushNewTarget; - __ Tst(callField, LogicalImmediate::Create(CALL_TYPE_MASK, RegXSize)); - __ B(Condition::EQ, &pushVregs); - // fall through - __ Tbz(callField, JSMethod::HaveThisBit::START_BIT, &pushNewTarget); - // push undefined - __ Mov(thisObj, Immediate(JSTaggedValue::VALUE_UNDEFINED)); - __ Str(thisObj, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - // fall through - __ Bind(&pushNewTarget); - { - PushNewTarget(assembler); - } - __ Bind(&pushVregs); - { - PushVregs(assembler); - } + PushCallThis(assembler, INVALID_REG, true); } -// Input: X23 - callField void AssemblerStubs::PushNewTarget(ExtendedAssembler *assembler) { - Register callField(X23); - Register newTarget(X6); + Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD); Label pushCallTarget; - __ Tbz(callField, JSMethod::HaveNewTargetBit::START_BIT, &pushCallTarget); + __ Tbz(callFieldRegister, JSMethod::HaveNewTargetBit::START_BIT, &pushCallTarget); // push undefined - __ Mov(newTarget, Immediate(JSTaggedValue::VALUE_UNDEFINED)); - __ Str(newTarget, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + { + [[maybe_unused]] TempRegister1Scope scope1(assembler); + Register newTarget = __ TempRegister1(); + __ Mov(newTarget, Immediate(JSTaggedValue::VALUE_UNDEFINED)); + __ Str(newTarget, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + } __ Bind(&pushCallTarget); PushCallTarget(assembler); } -// Input: X21 - callTarget -// X23 - callField void AssemblerStubs::PushCallTarget(ExtendedAssembler *assembler) { - Register callTarget(X21); - Register callField(X23); + Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET); + Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD); Label pushVregs; - __ Tbz(callField, JSMethod::HaveFuncBit::START_BIT, &pushVregs); - // push undefined - __ Str(callTarget, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + __ Tbz(callFieldRegister, JSMethod::HaveFuncBit::START_BIT, &pushVregs); + __ Str(callTargetRegister, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // fall through __ Bind(&pushVregs); PushVregs(assembler); } -// Input: X20 - sp -// X21 - callTarget -// X22 - method -// X23 - callField -// X1 - jumpSizeAfterCall -// X2 - fp void AssemblerStubs::PushVregs(ExtendedAssembler *assembler) { - Register prevSp(X20); - Register callTarget(X21); - Register method(X22); - Register callField(X23); - Register jumpSize(X1); - Register fp(X2); - Register pc(X6); - Register newSp(X7); - Register numVregs(X8); - Register temp(X9); + Register prevSpRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::SP); + Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET); + Register methodRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::METHOD); + Register callFieldRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_FIELD); + Register fpRegister = __ AvailableRegister1(); - Label pushFrameState; - Label dispatchCall; - GetNumVregsFromCallField(assembler, callField, numVregs); - PushUndefinedWithArgc(assembler, numVregs, temp, &pushFrameState); + Label pushFrameStateAndCall; + [[maybe_unused]] TempRegister1Scope scope1(assembler); + Register tempRegister = __ TempRegister1(); + // args register can be reused now. + Register numVregsRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0); + GetNumVregsFromCallField(assembler, callFieldRegister, numVregsRegister); + PushUndefinedWithArgc(assembler, numVregsRegister, tempRegister, &pushFrameStateAndCall); // fall through - __ Bind(&pushFrameState); + __ Bind(&pushFrameStateAndCall); { - __ Mov(newSp, Register(SP)); + Register newSpRegister = __ AvailableRegister2(); + __ Mov(newSpRegister, Register(SP)); StackOverflowCheck(assembler); - __ Sub(temp, prevSp, Immediate(sizeof(AsmInterpretedFrame))); - __ Str(jumpSize, MemoryOperand(temp, AsmInterpretedFrame::GetCallSizeOffset(false))); - PushFrameState(assembler, prevSp, fp, callTarget, method, pc, temp); - // fall through - } - __ Bind(&dispatchCall); - { - DispatchCall(assembler, pc, newSp); + [[maybe_unused]] TempRegister2Scope scope2(assembler); + Register pcRegister = __ TempRegister2(); + PushFrameState(assembler, prevSpRegister, fpRegister, callTargetRegister, methodRegister, pcRegister, + tempRegister); + + DispatchCall(assembler, pcRegister, newSpRegister); } } -// Input: X19 - glue -// X20 - sp -// X21 - callTarget -// X22 - method -void AssemblerStubs::DispatchCall(ExtendedAssembler *assembler, Register pc, Register newSp) +// Input: +// X19 - glue +// FP - sp +// X20 - callTarget +// X21 - method +void AssemblerStubs::DispatchCall(ExtendedAssembler *assembler, Register pcRegister, Register newSpRegister) { - Register glue(X19); - Register callTarget(X21); - Register method(X22); + Register glueRegister = __ GlueRegister(); + Register callTargetRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::CALL_TARGET); + Register methodRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::METHOD); - Register constantPool(X22); - Register profileTypeInfo(X23); - Register acc(X24); - Register hotnessCounter(X25, W); + if (glueRegister.GetId() != X19) { + __ Mov(Register(X19), glueRegister); + } + __ Ldrh(Register(X24, W), MemoryOperand(methodRegister, JSMethod::GetHotnessCounterOffset(false))); + __ Mov(Register(X23), Immediate(JSTaggedValue::VALUE_HOLE)); + __ Ldr(Register(X22), MemoryOperand(callTargetRegister, JSFunction::PROFILE_TYPE_INFO_OFFSET)); + __ Ldr(Register(X21), MemoryOperand(callTargetRegister, JSFunction::CONSTANT_POOL_OFFSET)); + __ Mov(Register(X20), pcRegister); + __ Mov(Register(FP), newSpRegister); - __ Ldrh(hotnessCounter, MemoryOperand(method, JSMethod::GetHotnessCounterOffset(false))); - __ Mov(acc, Immediate(JSTaggedValue::VALUE_HOLE)); - __ Ldr(profileTypeInfo, MemoryOperand(callTarget, JSFunction::PROFILE_TYPE_INFO_OFFSET)); - __ Ldr(constantPool, MemoryOperand(callTarget, JSFunction::CONSTANT_POOL_OFFSET)); - __ Mov(Register(X21), pc); - __ Mov(Register(X20), newSp); - - Register bcIndex(X9, W); - Register temp(X10); - __ Ldrb(bcIndex, MemoryOperand(pc, 0)); - __ Add(temp, glue, Operand(bcIndex, LSL, 3)); // 3: bc * 8 - __ Ldr(temp, MemoryOperand(temp, JSThread::GlueData::GetBCStubEntriesOffset(false))); - __ Br(temp); + Register bcIndexRegister = __ AvailableRegister1(); + Register tempRegister = __ AvailableRegister2(); + __ Ldrb(bcIndexRegister.W(), MemoryOperand(pcRegister, 0)); + __ Add(tempRegister, glueRegister, Operand(bcIndexRegister.W(), UXTW, 3)); // 3: bc * 8 + __ Ldr(tempRegister, MemoryOperand(tempRegister, JSThread::GlueData::GetBCStubEntriesOffset(false))); + __ Br(tempRegister); } void AssemblerStubs::PushFrameState(ExtendedAssembler *assembler, Register prevSp, Register fp, @@ -1693,8 +1577,10 @@ void AssemblerStubs::GetDeclaredNumArgsFromCallField(ExtendedAssembler *assemble void AssemblerStubs::PushUndefinedWithArgc(ExtendedAssembler *assembler, Register argc, Register temp, panda::ecmascript::Label *next) { - __ Cmp(argc.W(), Immediate(0)); - __ B(Condition::LE, next); + if (next != nullptr) { + __ Cmp(argc.W(), Immediate(0)); + __ B(Condition::LE, next); + } Label loopBeginning; __ Mov(temp, Immediate(JSTaggedValue::VALUE_UNDEFINED)); __ Bind(&loopBeginning); @@ -1703,12 +1589,6 @@ void AssemblerStubs::PushUndefinedWithArgc(ExtendedAssembler *assembler, Registe __ Cbnz(argc.W(), &loopBeginning); } -void AssemblerStubs::SaveFpAndJumpSize(ExtendedAssembler *assembler, Immediate jumpSize) -{ - __ Mov(Register(X1), jumpSize); - __ Mov(Register(X2), Register(SP)); -} - void AssemblerStubs::GlueToThread(ExtendedAssembler *assembler, Register glue, Register thread) { __ Sub(thread, glue, Immediate(JSThread::GetGlueDataOffset())); @@ -1784,39 +1664,26 @@ void AssemblerStubs::PushGeneratorFrameState(ExtendedAssembler *assembler, Regis } void AssemblerStubs::CallBCStub(ExtendedAssembler *assembler, Register &newSp, Register &glue, - Register &callTarget, Register &method, Register &pc, Register &temp, bool isReturn) + Register &callTarget, Register &method, Register &pc, Register &temp) { - Label returnOfCallBCStub; Register sp(SP); // caller save newSp register to restore rsp after call __ Str(newSp, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // prepare call entry - __ Mov(Register(X19), glue); // %X19 - glue - __ Mov(Register(X20), newSp); // %X20 - sp - // %X21 - pc - __ Ldr(Register(X22), MemoryOperand(callTarget, JSFunction::CONSTANT_POOL_OFFSET)); // %X22 - constantpool - __ Ldr(Register(X23), MemoryOperand(callTarget, JSFunction::PROFILE_TYPE_INFO_OFFSET)); // %X23 - profileTypeInfo - __ Mov(Register(X24), Immediate(JSTaggedValue::Hole().GetRawData())); // %X24 - acc - __ Ldr(Register(X25), MemoryOperand(method, JSMethod::GetHotnessCounterOffset(false))); // %X25 - hotnessCounter + __ Mov(Register(X19), glue); // X19 - glue + __ Mov(Register(FP), newSp); // FP - sp + __ Mov(Register(X20), pc); // X20 - pc + __ Ldr(Register(X21), MemoryOperand(callTarget, JSFunction::CONSTANT_POOL_OFFSET)); // X21 - constantpool + __ Ldr(Register(X22), MemoryOperand(callTarget, JSFunction::PROFILE_TYPE_INFO_OFFSET)); // X22 - profileTypeInfo + __ Mov(Register(X23), Immediate(JSTaggedValue::Hole().GetRawData())); // X23 - acc + __ Ldr(Register(X24), MemoryOperand(method, JSMethod::GetHotnessCounterOffset(false))); // X24 - hotnessCounter // call the first bytecode handler - __ Ldr(temp, MemoryOperand(pc, 0)); + __ Ldrb(temp.W(), MemoryOperand(pc, 0)); // 3 : 3 means *8 - __ Add(temp, glue, Operand(temp, LSL, 3)); + __ Add(temp, glue, Operand(temp.W(), UXTW, 3)); __ Ldr(temp, MemoryOperand(temp, JSThread::GlueData::GetBCStubEntriesOffset(false))); - __ Blr(temp); - - // return - __ Bind(&returnOfCallBCStub); - { - __ Ldr(temp, MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); - __ Sub(temp, temp, Immediate(sizeof(AsmInterpretedFrame))); - __ Ldr(sp, MemoryOperand(temp, AsmInterpretedFrame::GetFpOffset(false))); - if (isReturn) { - __ Ldr(Register(X0), MemoryOperand(temp, AsmInterpretedFrame::GetAccOffset(false))); - __ Ret(); - } - } + __ Br(temp); } void AssemblerStubs::CallNativeEntry(ExtendedAssembler *assembler) @@ -1862,8 +1729,6 @@ void AssemblerStubs::PushArgsFastPath(ExtendedAssembler *assembler, Label pushFrameState; Register sp(SP); - __ Cmp(argc.W(), Immediate(0)); - __ B(Condition::LS, &pushCallThis); // skip push args Register argvOnlyHaveArgs(X11); __ Add(argvOnlyHaveArgs, argv, Immediate(BuiltinFrame::RESERVED_CALL_ARGCOUNT * JSTaggedValue::TaggedTypeSize())); Register tempRegister(X12); @@ -1904,7 +1769,7 @@ void AssemblerStubs::PushArgsFastPath(ExtendedAssembler *assembler, Register pcRegister(X11); PushFrameState(assembler, prevSp, fp, callTarget, method, pcRegister, tempRegister); - CallBCStub(assembler, newSpRegister, glue, callTarget, method, pcRegister, tempRegister, true); + CallBCStub(assembler, newSpRegister, glue, callTarget, method, pcRegister, tempRegister); } // Input: glueRegister - %X0 @@ -1925,6 +1790,7 @@ void AssemblerStubs::PushArgsSlowPath(ExtendedAssembler *assembler, Register &gl Register fpRegister(X11); Register tempRegister(X12); + __ PushFpAndLr(); __ Mov(fpRegister, Register(SP)); __ Tst(callFieldRegister, LogicalImmediate::Create(JSMethod::HaveExtraBit::Mask(), RegXSize)); __ B(Condition::NE, &haveExtra); diff --git a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h index 5d82038abe..11d09bd59b 100644 --- a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h +++ b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h @@ -75,18 +75,6 @@ public: static void PushCallArgs0AndDispatch(ExtendedAssembler *assembler); - static void PushCallIThisRangeAndDispatchSlowPath(ExtendedAssembler *assembler); - - static void PushCallIRangeAndDispatchSlowPath(ExtendedAssembler *assembler); - - static void PushCallArgs3AndDispatchSlowPath(ExtendedAssembler *assembler); - - static void PushCallArgs2AndDispatchSlowPath(ExtendedAssembler *assembler); - - static void PushCallArgs1AndDispatchSlowPath(ExtendedAssembler *assembler); - - static void PushCallArgs0AndDispatchSlowPath(ExtendedAssembler *assembler); - static void PushCallIThisRangeAndDispatchNative(ExtendedAssembler *assembler); static void PushCallIRangeAndDispatchNative(ExtendedAssembler *assembler); @@ -108,21 +96,21 @@ public: private: static void JSCallBody(ExtendedAssembler *assembler, Register jsfunc); - static void CallIThisRangeNoExtraEntry(ExtendedAssembler *assembler, Register declaredNumArgs); + static void CallIThisRangeNoExtraEntry(ExtendedAssembler *assembler); - static void CallIRangeNoExtraEntry(ExtendedAssembler *assembler, Register declaredNumArgs); + static void CallIRangeNoExtraEntry(ExtendedAssembler *assembler); - static void Callargs3NoExtraEntry(ExtendedAssembler *assembler, Register declaredNumArgs); + static void Callargs3NoExtraEntry(ExtendedAssembler *assembler); - static void Callargs2NoExtraEntry(ExtendedAssembler *assembler, Register declaredNumArgs); + static void Callargs2NoExtraEntry(ExtendedAssembler *assembler); - static void Callargs1NoExtraEntry(ExtendedAssembler *assembler, Register declaredNumArgs); + static void Callargs1NoExtraEntry(ExtendedAssembler *assembler); static void Callargs0NoExtraEntry(ExtendedAssembler *assembler); static void CallIThisRangeEntry(ExtendedAssembler *assembler); - static void PushCallThis(ExtendedAssembler *assembler); + static void PushCallThis(ExtendedAssembler *assembler, Register thisRegister, bool isUndefined); static void CallIRangeEntry(ExtendedAssembler *assembler); @@ -150,6 +138,19 @@ private: static void PushFrameState(ExtendedAssembler *assembler, Register prevSp, Register fp, Register callTarget, Register method, Register pc, Register op); + using AssemblerClosure = std::function; + static void JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode mode, + const AssemblerClosure& fastEntry, const AssemblerClosure& slowEntry); + static void JSCallCommonSlowPath(ExtendedAssembler *assembler, JSCallMode mode, + const AssemblerClosure& entry, + const AssemblerClosure& extraEntry); + static void PushCallIThisRangeAndDispatchSlowPath(ExtendedAssembler *assembler); + static void PushCallIRangeAndDispatchSlowPath(ExtendedAssembler *assembler); + static void PushCallArgs3AndDispatchSlowPath(ExtendedAssembler *assembler); + static void PushCallArgs2AndDispatchSlowPath(ExtendedAssembler *assembler); + static void PushCallArgs1AndDispatchSlowPath(ExtendedAssembler *assembler); + static void PushCallArgs0AndDispatchSlowPath(ExtendedAssembler *assembler); + static void GetNumVregsFromCallField(ExtendedAssembler *assembler, Register callField, Register numVregs); static void GetDeclaredNumArgsFromCallField(ExtendedAssembler *assembler, Register callField, @@ -177,7 +178,7 @@ private: Register &contextRegister, Register &pcRegister, Register &operatorRegister); static void CallBCStub(ExtendedAssembler *assembler, Register &newSp, Register &glue, - Register &callTarget, Register &method, Register &pc, Register &temp, bool isReturn); + Register &callTarget, Register &method, Register &pc, Register &temp); static void CallNativeEntry(ExtendedAssembler *assembler); From bcb295806b518f8e05e36da807a4a680dc4a6c57 Mon Sep 17 00:00:00 2001 From: xliu Date: Sun, 5 Jun 2022 17:39:02 +0800 Subject: [PATCH 13/35] [Optimization] String Trim Description 1. String trim interface optimization. 2. Change the implementation of using regular to a simpler and more efficient way. Issue: #I5AH4Z:[Optimization] String Trim Signed-off-by: xliu Change-Id: I9dd0d923344ebd3c571ff8cd6cb244d9c01444fa --- ecmascript/base/number_helper.cpp | 18 ++--------- ecmascript/base/number_helper.h | 7 ----- ecmascript/base/string_helper.cpp | 25 --------------- ecmascript/base/string_helper.h | 41 +++++++++++++++++++++++++ ecmascript/builtins/builtins_string.cpp | 23 +++++++++----- ecmascript/ecma_string-inl.h | 35 ++++++++++++++++++++- ecmascript/ecma_string.cpp | 27 ++-------------- ecmascript/ecma_string.h | 4 +++ 8 files changed, 99 insertions(+), 81 deletions(-) diff --git a/ecmascript/base/number_helper.cpp b/ecmascript/base/number_helper.cpp index e4658bf340..a7abef1bd2 100644 --- a/ecmascript/base/number_helper.cpp +++ b/ecmascript/base/number_helper.cpp @@ -20,6 +20,7 @@ #include #include #include "ecmascript/base/builtins_base.h" +#include "ecmascript/base/string_helper.h" #include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/object_factory.h" @@ -49,21 +50,6 @@ static inline uint8_t ToDigit(uint8_t c) return '$'; } -bool NumberHelper::IsNonspace(uint16_t c) -{ - int i; - int len = sizeof(SPACE_OR_LINE_TERMINAL) / sizeof(SPACE_OR_LINE_TERMINAL[0]); - for (i = 0; i < len; i++) { - if (c == SPACE_OR_LINE_TERMINAL[i]) { - return false; - } - if (c < SPACE_OR_LINE_TERMINAL[i]) { - return true; - } - } - return true; -} - bool NumberHelper::GotoNonspace(uint8_t **ptr, const uint8_t *end) { while (*ptr < end) { @@ -80,7 +66,7 @@ bool NumberHelper::GotoNonspace(uint8_t **ptr, const uint8_t *end) return true; } } - if (IsNonspace(c)) { + if (!StringHelper::IsNonspace(c)) { return true; } *ptr += size; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) diff --git a/ecmascript/base/number_helper.h b/ecmascript/base/number_helper.h index 1cd8de235a..72b9e9ebeb 100644 --- a/ecmascript/base/number_helper.h +++ b/ecmascript/base/number_helper.h @@ -22,12 +22,6 @@ #include "ecmascript/js_tagged_value.h" namespace panda::ecmascript::base { -// NOLINTNEXTLINE(modernize-avoid-c-arrays) -static constexpr uint16_t SPACE_OR_LINE_TERMINAL[] = { - 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x0020, 0x00A0, 0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, - 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x2028, 0x2029, 0x202F, 0x205F, 0x3000, 0xFEFF, -}; - constexpr double MIN_RADIX = 2; constexpr double MAX_RADIX = 36; constexpr double MIN_FRACTION = 0; @@ -107,7 +101,6 @@ private: static char Carry(char current, int radix); static double Strtod(const char *str, int exponent, uint8_t radix); static CString DecimalsToString(double *numberInteger, double fraction, int radix, double delta); - static bool IsNonspace(uint16_t c); static bool GotoNonspace(uint8_t **ptr, const uint8_t *end); static void GetBase(double d, int digits, int *decpt, char *buf, char *bufTmp, int size); static int GetMinmumDigits(double d, int *decpt, char *buf); diff --git a/ecmascript/base/string_helper.cpp b/ecmascript/base/string_helper.cpp index 0614210d67..df8347481b 100644 --- a/ecmascript/base/string_helper.cpp +++ b/ecmascript/base/string_helper.cpp @@ -59,29 +59,4 @@ EcmaString *StringHelper::Repeat(JSThread *thread, const std::u16string &thisStr return canBeCompress ? *factory->NewFromUtf16Compress(uint16tData, length) : *factory->NewFromUtf16NotCompress(uint16tData, length); } - -EcmaString *StringHelper::Trim(JSThread *thread, const std::u16string &thisStr) -{ - ecmascript::ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - std::u16string tmpStr = thisStr; - if (tmpStr.empty()) { - return *factory->GetEmptyString(); - } - std::string str = U16stringToString(tmpStr); - std::wstring wstr = StringToWstring(str); - std::wregex r( - L"^[" - L"\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007" - L"\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+|[" - L"\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007" - L"\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+$"); - wstr = regex_replace(wstr, r, L""); - str = WstringToString(wstr); - tmpStr = StringToU16string(str); - const char16_t *constChar16tData = tmpStr.data(); - auto *char16tData = const_cast(constChar16tData); - auto *uint16tData = reinterpret_cast(char16tData); - uint32_t length = tmpStr.size(); - return *factory->NewFromUtf16(uint16tData, length); -} } // namespace panda::ecmascript::base diff --git a/ecmascript/base/string_helper.h b/ecmascript/base/string_helper.h index 1f41c0d160..bee9d4e73e 100644 --- a/ecmascript/base/string_helper.h +++ b/ecmascript/base/string_helper.h @@ -34,6 +34,13 @@ #include "unicode/unistr.h" namespace panda::ecmascript::base { +// White Space Code Points and Line Terminators Code Point +// NOLINTNEXTLINE(modernize-avoid-c-arrays) +static constexpr uint16_t SPACE_OR_LINE_TERMINAL[] = { + 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x0020, 0x00A0, 0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, + 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x2028, 0x2029, 0x202F, 0x205F, 0x3000, 0xFEFF, +}; + class StringHelper { public: static std::string ToStdString(EcmaString *string); @@ -209,6 +216,40 @@ public: } return lineStr; } + + static inline bool IsNonspace(uint16_t c) + { + uint32_t len = sizeof(SPACE_OR_LINE_TERMINAL) / sizeof(SPACE_OR_LINE_TERMINAL[0]); + for (uint32_t i = 0; i < len; i++) { + if (c == SPACE_OR_LINE_TERMINAL[i]) { + return true; + } + if (c < SPACE_OR_LINE_TERMINAL[i]) { + return false; + } + } + return false; + } + + template + static inline uint32_t GetStart(Span &data, uint32_t length) + { + uint32_t start = 0; + while (start < length && IsNonspace(data[start])) { + start++; + } + return start; + } + + template + static inline uint32_t GetEnd(Span &data, uint32_t start, uint32_t length) + { + uint32_t end = length - 1; + while (end >= start && IsNonspace(data[end])) { + end--; + } + return end; + } }; } // namespace panda::ecmascript::base #endif // ECMASCRIPT_BASE_STRING_HELP_H diff --git a/ecmascript/builtins/builtins_string.cpp b/ecmascript/builtins/builtins_string.cpp index f2f0992525..97c055f851 100644 --- a/ecmascript/builtins/builtins_string.cpp +++ b/ecmascript/builtins/builtins_string.cpp @@ -1535,16 +1535,23 @@ JSTaggedValue BuiltinsString::Trim(EcmaRuntimeCallInfo *argv) JSHandle thisHandle = JSTaggedValue::ToString(thread, thisTag); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); uint32_t thisLen = thisHandle->GetLength(); - std::u16string u16strThis; - if (thisHandle->IsUtf16()) { - u16strThis = base::StringHelper::Utf16ToU16String(thisHandle->GetDataUtf16(), thisLen); - } else { - const uint8_t *uint8This = thisHandle->GetDataUtf8(); - u16strThis = base::StringHelper::Utf8ToU16String(uint8This, thisLen); + if (UNLIKELY(thisLen == 0)) { + return thread->GlobalConstants()->GetEmptyString(); } - EcmaString *str = base::StringHelper::Trim(thread, u16strThis); - return JSTaggedValue(str); + if (thisHandle->IsUtf8()) { + Span data(reinterpret_cast(thisHandle->GetData()), thisLen); + uint32_t start = base::StringHelper::GetStart(data, thisLen); + uint32_t end = base::StringHelper::GetEnd(data, start, thisLen); + EcmaString *res = EcmaString::FastSubUtf8String(thread->GetEcmaVM(), thisHandle, start, end - start + 1); + return JSTaggedValue(res); + } + + Span data(thisHandle->GetData(), thisLen); + uint32_t start = base::StringHelper::GetStart(data, thisLen); + uint32_t end = base::StringHelper::GetEnd(data, start, thisLen); + EcmaString *res = EcmaString::FastSubUtf16String(thread->GetEcmaVM(), thisHandle, start, end - start + 1); + return JSTaggedValue(res); } // 21.1.3.26 diff --git a/ecmascript/ecma_string-inl.h b/ecmascript/ecma_string-inl.h index 2be48ffcd7..faffbca895 100644 --- a/ecmascript/ecma_string-inl.h +++ b/ecmascript/ecma_string-inl.h @@ -189,6 +189,39 @@ void EcmaString::WriteData(char src, uint32_t start) *(GetDataUtf16Writable() + start) = src; } } -} // namespace panda::ecmascript +/* static */ +EcmaString *EcmaString::FastSubUtf8String(const EcmaVM *vm, const JSHandle &src, uint32_t start, + uint32_t utf16Len) +{ + auto string = AllocStringObject(utf16Len, true, vm); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + Span dst(string->GetDataUtf8Writable(), utf16Len); + Span source(src->GetDataUtf8() + start, utf16Len); + EcmaString::StringCopy(dst, utf16Len, source, utf16Len); + + ASSERT_PRINT(CanBeCompressed(string), "canBeCompresse does not match the real value!"); + return string; +} + +/* static */ +EcmaString *EcmaString::FastSubUtf16String(const EcmaVM *vm, const JSHandle &src, uint32_t start, + uint32_t utf16Len) +{ + bool canBeCompressed = CanBeCompressed(src->GetDataUtf16() + start, utf16Len); + auto string = AllocStringObject(utf16Len, canBeCompressed, vm); + if (canBeCompressed) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + CopyUtf16AsUtf8(src->GetDataUtf16() + start, string->GetDataUtf8Writable(), utf16Len); + } else { + uint32_t len = utf16Len * (sizeof(uint16_t) / sizeof(uint8_t)); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + Span dst(string->GetDataUtf16Writable(), utf16Len); + Span source(src->GetDataUtf16() + start, utf16Len); + EcmaString::StringCopy(dst, len, source, len); + } + ASSERT_PRINT(canBeCompressed == CanBeCompressed(string), "canBeCompresse does not match the real value!"); + return string; +} +} // namespace panda::ecmascript #endif diff --git a/ecmascript/ecma_string.cpp b/ecmascript/ecma_string.cpp index 7023241fa2..1f116a8d4d 100644 --- a/ecmascript/ecma_string.cpp +++ b/ecmascript/ecma_string.cpp @@ -83,32 +83,11 @@ EcmaString *EcmaString::FastSubString(const JSHandle &src, uint32_t if (utf16Len == 0) { return vm->GetFactory()->GetEmptyString().GetObject(); } - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - bool canBeCompressed = src->IsUtf8() ? true : CanBeCompressed(src->GetDataUtf16() + start, utf16Len); - // allocator may trig gc and move src, need to hold it - auto string = AllocStringObject(utf16Len, canBeCompressed, vm); - - if (src->IsUtf16()) { - if (canBeCompressed) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - CopyUtf16AsUtf8(src->GetDataUtf16() + start, string->GetDataUtf8Writable(), utf16Len); - } else { - uint32_t len = utf16Len * (sizeof(uint16_t) / sizeof(uint8_t)); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - Span dst(string->GetDataUtf16Writable(), utf16Len); - Span source(src->GetDataUtf16() + start, utf16Len); - EcmaString::StringCopy(dst, len, source, len); - } - } else { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - Span dst(string->GetDataUtf8Writable(), utf16Len); - Span source(src->GetDataUtf8() + start, utf16Len); - EcmaString::StringCopy(dst, utf16Len, source, utf16Len); + if (src->IsUtf8()) { + return FastSubUtf8String(vm, src, start, utf16Len); } - - ASSERT_PRINT(canBeCompressed == CanBeCompressed(string), "canBeCompresse does not match the real value!"); - return string; + return FastSubUtf16String(vm, src, start, utf16Len); } template diff --git a/ecmascript/ecma_string.h b/ecmascript/ecma_string.h index b04ec99e65..8ec521fb8b 100644 --- a/ecmascript/ecma_string.h +++ b/ecmascript/ecma_string.h @@ -314,6 +314,10 @@ public: // Data can be stored in utf8 or utf16 form according to compressed bit. static constexpr size_t DATA_OFFSET = SIZE; // DATA_OFFSET equal to Empty String size + static inline EcmaString *FastSubUtf8String(const EcmaVM *vm, const JSHandle &src, uint32_t start, + uint32_t utf16Len); + static inline EcmaString *FastSubUtf16String(const EcmaVM *vm, const JSHandle &src, uint32_t start, + uint32_t utf16Len); private: void SetLength(uint32_t length, bool compressed = false) { From 8567586730981d96cc1423d2cd9e38744b8dbb16 Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Mon, 6 Jun 2022 00:26:32 +0800 Subject: [PATCH 14/35] add json utils for debugger add json util of cJSON issue: https://gitee.com/openharmony/ark_js_runtime/issues/I5AQMM Signed-off-by: wengchangcheng Change-Id: Ie582ceb8ee3c5b9bd8024c25063a9b4a645792ac --- ecmascript/tooling/BUILD.gn | 6 +- ecmascript/tooling/base/pt_json.cpp | 401 +++++++++++++++++++++++ ecmascript/tooling/base/pt_json.h | 102 ++++++ ecmascript/tooling/test/BUILD.gn | 1 + ecmascript/tooling/test/pt_json_test.cpp | 163 +++++++++ 5 files changed, 672 insertions(+), 1 deletion(-) create mode 100644 ecmascript/tooling/base/pt_json.cpp create mode 100644 ecmascript/tooling/base/pt_json.h create mode 100644 ecmascript/tooling/test/pt_json_test.cpp diff --git a/ecmascript/tooling/BUILD.gn b/ecmascript/tooling/BUILD.gn index f829fc4f63..01fb896b0e 100644 --- a/ecmascript/tooling/BUILD.gn +++ b/ecmascript/tooling/BUILD.gn @@ -21,8 +21,9 @@ config("ark_ecma_debugger_config") { ] include_dirs = [ - "//ark/js_runtime/ecmascript/tooling", + ".", "//third_party/boost", + "//third_party/cJSON", ] } @@ -35,6 +36,7 @@ debugger_sources = [ "backend/js_pt_extractor.cpp", "backend/js_pt_hooks.cpp", "base/pt_events.cpp", + "base/pt_json.cpp", "base/pt_params.cpp", "base/pt_returns.cpp", "base/pt_script.cpp", @@ -52,6 +54,7 @@ source_set("libark_ecma_debugger_set") { deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", + "//third_party/cJSON:cjson_static", ] cflags_cc = [ "-fvisibility=hidden" ] @@ -83,6 +86,7 @@ source_set("libark_ecma_debugger_test_set") { deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", + "//third_party/cJSON:cjson_static", ] } diff --git a/ecmascript/tooling/base/pt_json.cpp b/ecmascript/tooling/base/pt_json.cpp new file mode 100644 index 0000000000..b790854142 --- /dev/null +++ b/ecmascript/tooling/base/pt_json.cpp @@ -0,0 +1,401 @@ +/* + * 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. + */ + +#include "ecmascript/tooling/base/pt_json.h" + +#include "libpandabase/macros.h" + +namespace panda::ecmascript::tooling { +std::unique_ptr PtJson::CreateObject() +{ + return std::make_unique(cJSON_CreateObject()); +} + +std::unique_ptr PtJson::CreateArray() +{ + return std::make_unique(cJSON_CreateArray()); +} + +void PtJson::ReleaseRoot() +{ + if (object_ != nullptr) { + cJSON_Delete(object_); + object_ = nullptr; + } +} + +std::unique_ptr PtJson::Parse(const char *data) +{ + cJSON *value = cJSON_ParseWithOpts(data, nullptr, true); + return std::make_unique(value); +} + +std::string PtJson::Stringify() const +{ + if (object_ == nullptr) { + return ""; + } + + char *str = cJSON_PrintUnformatted(object_); + if (str == nullptr) { + return ""; + } + + std::string result(str); + cJSON_free(str); + return result; +} + +bool PtJson::Add(const char *key, bool value) const +{ + ASSERT(key != nullptr && !Contains(key)); + + cJSON *node = cJSON_CreateBool(value); + if (node == nullptr) { + return false; + } + + cJSON_bool ret = cJSON_AddItemToObject(object_, key, node); + if (ret == 0) { + cJSON_Delete(node); + return false; + } + + return true; +} + +bool PtJson::Add(const char *key, int32_t value) const +{ + return Add(key, static_cast(value)); +} + +bool PtJson::Add(const char *key, int64_t value) const +{ + return Add(key, static_cast(value)); +} + +bool PtJson::Add(const char *key, double value) const +{ + ASSERT(key != nullptr && !Contains(key)); + + cJSON *node = cJSON_CreateNumber(value); + if (node == nullptr) { + return false; + } + + cJSON_bool ret = cJSON_AddItemToObject(object_, key, node); + if (ret == 0) { + cJSON_Delete(node); + return false; + } + + return true; +} + +bool PtJson::Add(const char *key, const char *value) const +{ + ASSERT(key != nullptr && !Contains(key)); + + cJSON *node = cJSON_CreateString(value); + if (node == nullptr) { + return false; + } + + cJSON_bool ret = cJSON_AddItemToObject(object_, key, node); + if (ret == 0) { + cJSON_Delete(node); + return false; + } + + return true; +} + +bool PtJson::Add(const char *key, const std::unique_ptr &value) const +{ + ASSERT(key != nullptr && !Contains(key)); + + cJSON *node = value->GetJson(); + if (node == nullptr) { + return false; + } + + cJSON_bool ret = cJSON_AddItemToObject(object_, key, node); + if (ret == 0) { + return false; + } + + return true; +} + +bool PtJson::Push(bool value) const +{ + cJSON *node = cJSON_CreateBool(value); + if (node == nullptr) { + return false; + } + + cJSON_bool ret = cJSON_AddItemToArray(object_, node); + if (ret == 0) { + cJSON_Delete(node); + return false; + } + + return true; +} + +bool PtJson::Push(int32_t value) const +{ + return Push(static_cast(value)); +} + +bool PtJson::Push(int64_t value) const +{ + return Push(static_cast(value)); +} + +bool PtJson::Push(double value) const +{ + cJSON *node = cJSON_CreateNumber(value); + if (node == nullptr) { + return false; + } + + cJSON_bool ret = cJSON_AddItemToArray(object_, node); + if (ret == 0) { + cJSON_Delete(node); + return false; + } + + return true; +} + +bool PtJson::Push(const char *value) const +{ + cJSON *node = cJSON_CreateString(value); + if (node == nullptr) { + return false; + } + + cJSON_bool ret = cJSON_AddItemToArray(object_, node); + if (ret == 0) { + cJSON_Delete(node); + return false; + } + + return true; +} + +bool PtJson::Push(const std::unique_ptr &value) const +{ + if (value == nullptr) { + return false; + } + + cJSON *node = value->GetJson(); + if (node == nullptr) { + return false; + } + + cJSON_bool ret = cJSON_AddItemToArray(object_, node); + if (ret == 0) { + return false; + } + + return true; +} + +bool PtJson::Remove(const char *key) const +{ + ASSERT(key != nullptr && Contains(key)); + + cJSON_DeleteItemFromObject(object_, key); + return true; +} + +bool PtJson::Contains(const char *key) const +{ + cJSON *node = cJSON_GetObjectItemCaseSensitive(object_, key); + return node != nullptr; +} + +std::string PtJson::GetKey() const +{ + if (object_ == nullptr || object_->string == nullptr) { + return ""; + } + + return std::string(object_->string); +} + +cJSON *PtJson::GetJson() const +{ + return object_; +} + +bool PtJson::IsBool() const +{ + return cJSON_IsBool(object_) != 0; +} + +bool PtJson::IsNumber() const +{ + return cJSON_IsNumber(object_) != 0; +} + +bool PtJson::IsString() const +{ + return cJSON_IsString(object_) != 0; +} + +bool PtJson::IsObject() const +{ + return cJSON_IsObject(object_) != 0; +} + +bool PtJson::IsArray() const +{ + return cJSON_IsArray(object_) != 0; +} + +bool PtJson::IsNull() const +{ + return cJSON_IsNull(object_) != 0; +} + +bool PtJson::GetBool(bool defaultValue) const +{ + if (!IsBool()) { + return defaultValue; + } + + return cJSON_IsTrue(object_) != 0; +} + +int32_t PtJson::GetInt(int32_t defaultValue) const +{ + if (!IsNumber()) { + return defaultValue; + } + + return static_cast(object_->valuedouble); +} + +int64_t PtJson::GetInt64(int64_t defaultValue) const +{ + if (!IsNumber()) { + return defaultValue; + } + + return static_cast(object_->valuedouble); +} + +double PtJson::GetDouble(double defaultValue) const +{ + if (!IsNumber()) { + return defaultValue; + } + + return object_->valuedouble; +} + +std::string PtJson::GetString() const +{ + if (!IsString()) { + return ""; + } + + return std::string(object_->valuestring); +} + +int32_t PtJson::GetSize() const +{ + return cJSON_GetArraySize(object_); +} + +std::unique_ptr PtJson::Get(int32_t index) const +{ + return std::make_unique(cJSON_GetArrayItem(object_, index)); +} + +bool PtJson::GetBool(const char *key, bool defaultValue) const +{ + cJSON *value = cJSON_GetObjectItem(object_, key); + if (value == nullptr || cJSON_IsBool(value) == 0) { + return defaultValue; + } + + return cJSON_IsTrue(value) != 0; +} + +int32_t PtJson::GetInt(const char *key, int32_t defaultValue) const +{ + cJSON *value = cJSON_GetObjectItem(object_, key); + if (value == nullptr || cJSON_IsNumber(value) == 0) { + return defaultValue; + } + + return static_cast(value->valuedouble); +} + +int64_t PtJson::GetInt64(const char *key, int64_t defaultValue) const +{ + cJSON *value = cJSON_GetObjectItem(object_, key); + if (value == nullptr || cJSON_IsNumber(value) == 0) { + return defaultValue; + } + + return static_cast(value->valuedouble); +} + +double PtJson::GetDouble(const char *key, double defaultValue) const +{ + cJSON *value = cJSON_GetObjectItem(object_, key); + if (value == nullptr || cJSON_IsNumber(value) == 0) { + return defaultValue; + } + + return value->valuedouble; +} + +std::string PtJson::GetString(const char *key, std::string defaultValue) const +{ + cJSON *value = cJSON_GetObjectItem(object_, key); + if (value == nullptr || cJSON_IsString(value) == 0) { + return defaultValue; + } + + return value->valuestring; +} + +std::unique_ptr PtJson::GetObject(const char *key) const +{ + cJSON *value = cJSON_GetObjectItem(object_, key); + if (value == nullptr || cJSON_IsObject(value) == 0) { + return std::make_unique(); + } + + return std::make_unique(value); +} + +std::unique_ptr PtJson::GetArray(const char *key) const +{ + cJSON *value = cJSON_GetObjectItem(object_, key); + if (value == nullptr || cJSON_IsArray(value) == 0) { + return std::make_unique(); + } + + return std::make_unique(value); +} +} // namespace panda::ecmascript diff --git a/ecmascript/tooling/base/pt_json.h b/ecmascript/tooling/base/pt_json.h new file mode 100644 index 0000000000..7b376ea194 --- /dev/null +++ b/ecmascript/tooling/base/pt_json.h @@ -0,0 +1,102 @@ +/* + * 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. + */ + +#ifndef ECMASCRIPT_TOOLING_BASE_PT_JSON_H +#define ECMASCRIPT_TOOLING_BASE_PT_JSON_H + +#include +#include + +#include "cJSON.h" + +namespace panda::ecmascript::tooling { +class PtJson { +public: + PtJson() = default; + explicit PtJson(cJSON *object) : object_(object) {} + ~PtJson() = default; + + // Create empty json object + static std::unique_ptr CreateObject(); + static std::unique_ptr CreateArray(); + + // Release cJSON object memory + void ReleaseRoot(); + + // String parse to json + static std::unique_ptr Parse(const char *data); + + // To string + std::string Stringify() const; + + // Add Json child + bool Add(const char *key, bool value) const; + bool Add(const char *key, int32_t value) const; + bool Add(const char *key, int64_t value) const; + bool Add(const char *key, double value) const; + bool Add(const char *key, const char *value) const; + bool Add(const char *key, const std::unique_ptr &value) const; + + // Push back to array + bool Push(bool value) const; + bool Push(int32_t value) const; + bool Push(int64_t value) const; + bool Push(double value) const; + bool Push(const char *value) const; + bool Push(const std::unique_ptr &value) const; + + // Remove Json child + bool Remove(const char *key) const; + + bool Contains(const char *key) const; + + std::string GetKey() const; + + cJSON *GetJson() const; + + // Type check + bool IsBool() const; + bool IsNumber() const; + bool IsString() const; + bool IsObject() const; + bool IsArray() const; + bool IsNull() const; + + // Object accessor + bool GetBool(bool defaultValue = false) const; + int32_t GetInt(int32_t defaultValue = 0) const; + int64_t GetInt64(int64_t defaultValue = 0) const; + double GetDouble(double defaultValue = 0.0) const; + std::string GetString() const; + + // Array accessor + int32_t GetSize() const; + std::unique_ptr Get(int32_t index) const; + + // Child item accessor + bool GetBool(const char *key, bool defaultValue = false) const; + int32_t GetInt(const char *key, int32_t defaultValue = 0) const; + int64_t GetInt64(const char *key, int64_t defaultValue = 0) const; + double GetDouble(const char *key, double defaultValue = 0.0) const; + std::string GetString(const char *key, std::string defaultValue = "") const; + std::unique_ptr GetObject(const char *key) const; + std::unique_ptr GetArray(const char *key) const; + +private: + cJSON *object_ = nullptr; +}; +} // namespace panda::ecmascript + +#endif // ECMASCRIPT_TOOLING_BASE_PT_JSON_H diff --git a/ecmascript/tooling/test/BUILD.gn b/ecmascript/tooling/test/BUILD.gn index ce45a1e016..356de4942c 100644 --- a/ecmascript/tooling/test/BUILD.gn +++ b/ecmascript/tooling/test/BUILD.gn @@ -181,6 +181,7 @@ host_unittest_action("DebuggerTest") { "debugger_script_test.cpp", "debugger_types_test.cpp", "js_pt_hooks_test.cpp", + "pt_json_test.cpp", ] configs = [ "//ark/js_runtime:ecma_test_config" ] diff --git a/ecmascript/tooling/test/pt_json_test.cpp b/ecmascript/tooling/test/pt_json_test.cpp new file mode 100644 index 0000000000..0698a1653a --- /dev/null +++ b/ecmascript/tooling/test/pt_json_test.cpp @@ -0,0 +1,163 @@ +/* + * 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. + */ + +#include "ecmascript/tests/test_helper.h" +#include "ecmascript/tooling/base/pt_json.h" + +using namespace panda::ecmascript::tooling; + +namespace panda::test { +class PtJsonTest : public testing::Test { +public: + static void SetUpTestCase() + { + GTEST_LOG_(INFO) << "SetUpTestCase"; + } + + static void TearDownTestCase() + { + GTEST_LOG_(INFO) << "TearDownCase"; + } + + void SetUp() override + { + } + + void TearDown() override + { + } +}; + +HWTEST_F_L0(PtJsonTest, FalseTest) +{ + std::string str = "false"; + std::unique_ptr json = PtJson::Parse(str.c_str()); + ASSERT_TRUE(json->IsBool()); + EXPECT_FALSE(json->GetBool()); + EXPECT_EQ(json->Stringify(), str); + json->ReleaseRoot(); +} + +HWTEST_F_L0(PtJsonTest, TrueTest) +{ + std::string str = "true"; + std::unique_ptr json = PtJson::Parse(str.c_str()); + ASSERT_TRUE(json->IsBool()); + EXPECT_TRUE(json->GetBool()); + EXPECT_EQ(json->Stringify(), str); + json->ReleaseRoot(); +} + +HWTEST_F_L0(PtJsonTest, IntTest) +{ + std::string str = "100"; + std::unique_ptr json = PtJson::Parse(str.c_str()); + ASSERT_TRUE(json->IsNumber()); + EXPECT_EQ(json->GetInt(), 100); + EXPECT_EQ(json->Stringify(), str); + json->ReleaseRoot(); +} + +HWTEST_F_L0(PtJsonTest, Int64Test) +{ + std::string str = "123456789012345"; + std::unique_ptr json = PtJson::Parse(str.c_str()); + ASSERT_TRUE(json->IsNumber()); + EXPECT_EQ(json->GetInt64(), 123456789012345); + EXPECT_EQ(json->Stringify(), str); + json->ReleaseRoot(); +} + +HWTEST_F_L0(PtJsonTest, DoubleTest) +{ + std::string str = "12345.6789"; + std::unique_ptr json = PtJson::Parse(str.c_str()); + ASSERT_TRUE(json->IsNumber()); + EXPECT_EQ(json->GetDouble(), 12345.6789); + EXPECT_EQ(json->Stringify(), str); + json->ReleaseRoot(); +} + +HWTEST_F_L0(PtJsonTest, StringTest) +{ + std::string str = "\"abcdefg\""; + std::unique_ptr json = PtJson::Parse(str.c_str()); + ASSERT_TRUE(json->IsString()); + EXPECT_EQ(json->GetString(), "abcdefg"); + EXPECT_EQ(json->Stringify(), str); + json->ReleaseRoot(); +} + +HWTEST_F_L0(PtJsonTest, ArrayTest) +{ + std::string str = "[\"a\",\"b\",200]"; + std::unique_ptr json = PtJson::Parse(str.c_str()); + ASSERT_TRUE(json->IsArray()); + EXPECT_EQ(json->GetSize(), 3); + EXPECT_EQ(json->Get(0)->GetString(), "a"); + EXPECT_EQ(json->Get(1)->GetString(), "b"); + EXPECT_EQ(json->Get(2)->GetInt(), 200); + EXPECT_EQ(json->Stringify(), str); + json->ReleaseRoot(); +} + +HWTEST_F_L0(PtJsonTest, ObjectTest) +{ + auto child1 = PtJson::CreateObject(); + child1->Add("ch", "child_1"); + ASSERT_TRUE(child1->Contains("ch")); + + auto child2 = PtJson::CreateObject(); + child2->Add("ch", "child_2"); + ASSERT_TRUE(child2->Contains("ch")); + + auto arr = PtJson::CreateArray(); + arr->Push(false); + arr->Push(100); + arr->Push(100.2); + arr->Push(static_cast(200)); + arr->Push("abc"); + arr->Push(child1); + EXPECT_EQ(arr->GetSize(), 6); + + auto root = PtJson::CreateObject(); + root->Add("a", false); + root->Add("b", 100); + root->Add("c", 100.2); + root->Add("d", static_cast(200)); + root->Add("e", "abc"); + root->Add("f", child2); + root->Add("g", arr); + + EXPECT_FALSE(root->GetBool("a")); + EXPECT_EQ(root->GetInt("b"), 100); + EXPECT_EQ(root->GetDouble("c"), 100.2); + EXPECT_EQ(root->GetInt64("d"), static_cast(200)); + EXPECT_EQ(root->GetString("e"), "abc"); + EXPECT_EQ(root->GetObject("f")->GetString("ch"), "child_2"); + ASSERT_TRUE(root->GetArray("g")->IsArray()); + EXPECT_FALSE(root->GetArray("g")->Get(0)->GetBool()); + EXPECT_EQ(root->GetArray("g")->Get(1)->GetInt(), 100); + EXPECT_EQ(root->GetArray("g")->Get(2)->GetDouble(), 100.2); + EXPECT_EQ(root->GetArray("g")->Get(3)->GetInt64(), static_cast(200)); + EXPECT_EQ(root->GetArray("g")->Get(4)->GetString(), "abc"); + EXPECT_EQ(root->GetArray("g")->Get(5)->GetString("ch"), "child_1"); + + EXPECT_EQ(root->Stringify(), + "{\"a\":false,\"b\":100,\"c\":100.2,\"d\":200,\"e\":\"abc\",\"f\":{\"ch\":\"child_2\"}," + "\"g\":[false,100,100.2,200,\"abc\",{\"ch\":\"child_1\"}]}"); + root->ReleaseRoot(); +} +} \ No newline at end of file From c9488ca3a73510d582144be9edc828dcdacad535 Mon Sep 17 00:00:00 2001 From: hjzhangcm Date: Mon, 6 Jun 2022 09:03:52 +0800 Subject: [PATCH 15/35] Modify script directory Signed-off-by: hjzhangcm --- test/run_test262.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/run_test262.sh b/test/run_test262.sh index cd9c63e099..a20e831eec 100644 --- a/test/run_test262.sh +++ b/test/run_test262.sh @@ -26,12 +26,12 @@ pushd ark/ts2abc pushd ../../ if [ -d out/rk3568 ];then pushd ark/ts2abc - python3 test262/run_test262.py --es2015 all --threads=16 --libs-dir ../../out/rk3568/clang_x64/ark/ark:../../out/rk3568/clang_x64/ark/ark_js_runtime:../../out/rk3568/clang_x64/thirdparty/icu:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib --ark-tool=../../out/rk/clang_x64/ark/ark_js_runtime/ark_js_vm --ark-frontend-tool=../../out/rk3568/clang_x64/ark/ark/build/src/index.js + python3 test262/run_test262.py --es2015 all --threads=16 --libs-dir ../../out/rk3568/clang_x64/ark/ark:../../out/rk3568/clang_x64/ark/ark_js_runtime:../../out/rk3568/clang_x64/thirdparty/icu:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib --ark-tool=../../out/rk3568/clang_x64/ark/ark_js_runtime/ark_js_vm --ark-frontend-tool=../../out/rk3568/clang_x64/ark/ark/build/src/index.js popd fi if [ -d out/hispark_taurus ];then pushd ark/ts2abc - python3 test262/run_test262.py --es2015 all --threads=16 --libs-dir ../../out/hispark_taurus/clang_x64/ark/ark:../../out/hispark_taurus/clang_x64/ark/ark_js_runtime:../../out/hispark_taurus/clang_x64/thirdparty/icu:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib --ark-tool=../../out/rk/clang_x64/ark/ark_js_runtime/ark_js_vm --ark-frontend-tool=../../out/hispark_taurus/clang_x64/ark/ark/build/src/index.js + python3 test262/run_test262.py --es2015 all --threads=16 --libs-dir ../../out/hispark_taurus/clang_x64/ark/ark:../../out/hispark_taurus/clang_x64/ark/ark_js_runtime:../../out/hispark_taurus/clang_x64/thirdparty/icu:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib --ark-tool=../../out/hispark_taurus/clang_x64/ark/ark_js_runtime/ark_js_vm --ark-frontend-tool=../../out/hispark_taurus/clang_x64/ark/ark/build/src/index.js popd fi From 4e5c0d0ae9ebdc6a765a4c6d5134ea0167485762 Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Mon, 6 Jun 2022 10:05:14 +0800 Subject: [PATCH 16/35] debug Signed-off-by: songzhengchao Change-Id: Ie19553066c5f038237c2f06b42dd2b2a64721a8e --- ecmascript/compiler/BUILD.gn | 40 ++++++++++++++----- .../compiler/llvm/llvm_stackmap_parser.cpp | 6 +++ ecmascript/compiler/llvm_ir_builder.cpp | 2 + ecmascript/compiler/tests/BUILD.gn | 33 +++++++++++---- ecmascript/interpreter/frame_handler.cpp | 2 + js_runtime_config.gni | 3 +- 6 files changed, 68 insertions(+), 18 deletions(-) diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index b2fc7ce53b..a621e467c8 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -27,10 +27,18 @@ if (defined(ark_independent_build)) { config("include_llvm") { if (compile_llvm_online) { - include_dirs = [ - "//third_party/third_party_llvm-project/build/include", - "//third_party/third_party_llvm-project/llvm/include/", - ] + if (compiler_llvm_12) { + include_dirs = [ + "//third_party/third_party_llvm-project/build/include", + "//third_party/third_party_llvm-project/llvm/include/", + ] + } else { + include_dirs = [ + "//third_party/llvm-project/build/include", + "//third_party/llvm-project/llvm/include/", + ] + } + } else { include_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/llvm/include", @@ -78,7 +86,11 @@ source_set("libark_jsoptimizer_set") { ] if (compile_llvm_online) { - lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] + if (compiler_llvm_12) { + lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] + } else { + lib_dirs = [ "//third_party/llvm-project/build/lib" ] + } } else { lib_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/build/lib" ] @@ -142,18 +154,26 @@ source_set("libark_jsoptimizer_set") { "LLVMX86Desc", "LLVMX86Disassembler", "LLVMX86Info", - "LLVMFrontendOpenMP", - "LLVMBitWriter", ] + if (compile_llvm_online && compiler_llvm_12) { + libs += [ + "LLVMFrontendOpenMP", + "LLVMBitWriter", + ] + } else { + libs += [ + "LLVMX86Utils", + ] + } deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", ] - if (compile_llvm_online) { - deps += [ ":build_llvm_libs" ] - } + #if (compile_llvm_online) { + # deps += [ ":build_llvm_libs" ] + #} } source_set("ark_stub_compiler_set") { diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp index 5b53f39065..650d777f90 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -149,6 +149,12 @@ bool LLVMStackMapParser::CollectStackMapSlots(uintptr_t callSiteAddr, uintptr_t uintptr_t *fp = reinterpret_cast(frameFp); uintptr_t callsiteFp = *fp; uintptr_t callSiteSp = FrameHandler::GetPrevFrameCallSiteSp(reinterpret_cast(frameFp), curPc); + std::cout << std::hex << " callSiteAddr:0x" << callSiteAddr << " curPc:0x" << curPc + << " callsiteFp:0x" << callsiteFp + << " callSiteSp:0x" << callSiteSp + << " stack size:0x" << (callsiteFp- callSiteSp) + << std::endl; + ASSERT(callsiteFp - callSiteSp >= 8); uintptr_t address = 0; uintptr_t base = 0; uintptr_t derived = 0; diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index 8dd878d109..f07cca926d 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -375,10 +375,12 @@ void LLVMIRBuilder::GenPrologue([[maybe_unused]] LLVMModuleRef &module, LLVMBuil if (frameType == panda::ecmascript::FrameType::OPTIMIZED_FRAME) { LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); + LLVMAddTargetDependentFunctionAttr(function_, "js-stub-call", "0"); } else if (frameType == panda::ecmascript::FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { reservedSlotsSize = slotSize_ * static_cast(ReservedSlots::OPTIMIZED_JS_FUNCTION_RESERVED_SLOT); LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); + LLVMAddTargetDependentFunctionAttr(function_, "js-stub-call", "1"); } else { COMPILER_OPTIONAL_LOG(FATAL) << "frameType interpret type error !"; ASSERT_PRINT(static_cast(frameType), "is not support !"); diff --git a/ecmascript/compiler/tests/BUILD.gn b/ecmascript/compiler/tests/BUILD.gn index 42a8c571fc..cf05663d05 100644 --- a/ecmascript/compiler/tests/BUILD.gn +++ b/ecmascript/compiler/tests/BUILD.gn @@ -17,10 +17,17 @@ import("//build/test.gni") config("include_llvm_config") { if (compile_llvm_online) { - include_dirs = [ - "//third_party/third_party_llvm-project/build/include", - "//third_party/third_party_llvm-project/llvm/include/", - ] + if (compiler_llvm_12) { + include_dirs = [ + "//third_party/third_party_llvm-project/build/include", + "//third_party/third_party_llvm-project/llvm/include/", + ] + } else { + include_dirs = [ + "//third_party/llvm-project/build/include", + "//third_party/llvm-project/llvm/include/", + ] + } } else { include_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/llvm/include", @@ -46,7 +53,11 @@ host_unittest_action("StubTest") { ] if (compile_llvm_online) { - lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] + if (compiler_llvm_12) { + lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] + } else { + lib_dirs = [ "//third_party/llvm-project/build/lib" ] + } } else { lib_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/build/lib" ] @@ -135,7 +146,11 @@ host_unittest_action("AssemblerTest") { ] if (compile_llvm_online) { - lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] + if (compiler_llvm_12) { + lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] + } else { + lib_dirs = [ "//third_party/llvm-project/build/lib" ] + } } else { lib_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/build/lib" ] @@ -223,7 +238,11 @@ host_unittest_action("CircuitOptimizerTest") { ] if (compile_llvm_online) { - lib_dirs = [ "//third_party/llvm-project/build/lib" ] + if (compiler_llvm_12) { + lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] + } else { + lib_dirs = [ "//third_party/llvm-project/build/lib" ] + } } else { lib_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/build/lib" ] diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index f531f341da..b93790931c 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -583,6 +583,7 @@ ARK_INLINE void FrameHandler::OptimizedLeaveFrameIterate(const JSTaggedType *sp, ChunkMap *derivedPointers, bool isVerifying) { + std::cout << __FUNCTION__ << " " << std::dec << __LINE__ << " " << std::hex << " sp:0x" << sp << std::endl; OptimizedLeaveFrame *frame = OptimizedLeaveFrame::GetFrameFromSp(sp); if (frame->argc > 0) { JSTaggedType *argv = reinterpret_cast(&frame->argc + 1); @@ -731,6 +732,7 @@ void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &v0, } case FrameType::LEAVE_FRAME: { auto frame = OptimizedLeaveFrame::GetFrameFromSp(current); + std::cout << __FUNCTION__ << " " << std::dec << __LINE__ << " " << std::hex << " sp:0x" << current << std::endl; OptimizedLeaveFrameIterate(current, v0, v1, derivedPointers, isVerifying); current = frame->GetPrevFrameFp(); optimizedReturnAddr_ = frame->returnAddr; diff --git a/js_runtime_config.gni b/js_runtime_config.gni index 440bc34410..d8266e92bb 100644 --- a/js_runtime_config.gni +++ b/js_runtime_config.gni @@ -20,7 +20,8 @@ if (!defined(ark_independent_build)) { js_root = "//js_runtime" third_party_gn_path = "$build_root/third_party_gn" } -compile_llvm_online = false +compile_llvm_online = true +compiler_llvm_12 = false run_with_asan = false enable_bytrace = true enable_dump_in_faultlog = true From 1678169dc66b95221df191707ea52dc431b34b43 Mon Sep 17 00:00:00 2001 From: "yingguofeng@huawei.com" Date: Thu, 2 Jun 2022 19:18:27 +0800 Subject: [PATCH 17/35] =?UTF-8?q?Description:1=E3=80=810x06=20is=20judge?= =?UTF-8?q?=20to=20forward=20address.=202=E3=80=81Mem=20Pool=20capacity=20?= =?UTF-8?q?cause=20oom=20in=20multi=20worker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolution:1、Modify INVALID_OBJECT from 0x06 to 0x05 2、Auto adapter mem pool capacity according to physics memory Issue: https://gitee.com/openharmony/ark_js_runtime/issues/I5AKVH?from=project-issue Change-Id: If09a2cc792d27cd14a8e7ed88af192a78bab8356 Signed-off-by: yingguofeng@huawei.com --- ecmascript/free_object.h | 2 +- ecmascript/mem/mem.h | 3 +++ ecmascript/mem/mem_map_allocator.cpp | 35 ++++++++++++++++++++++++++++ ecmascript/mem/mem_map_allocator.h | 8 ++++--- ecmascript/napi/include/jsnapi.h | 2 +- ecmascript/napi/jsnapi.cpp | 6 ++--- 6 files changed, 48 insertions(+), 8 deletions(-) diff --git a/ecmascript/free_object.h b/ecmascript/free_object.h index 63c7042acf..04eb383113 100644 --- a/ecmascript/free_object.h +++ b/ecmascript/free_object.h @@ -20,7 +20,7 @@ #include "ecmascript/mem/barriers.h" #include "ecmascript/mem/tagged_object-inl.h" -#define INVALID_OBJECT ((FreeObject *)0x06) +#define INVALID_OBJECT ((FreeObject *)NULL_POINTER) namespace panda::ecmascript { class FreeObject : public TaggedObject { diff --git a/ecmascript/mem/mem.h b/ecmascript/mem/mem.h index 9523570a32..d10da9d629 100644 --- a/ecmascript/mem/mem.h +++ b/ecmascript/mem/mem.h @@ -46,6 +46,9 @@ static constexpr size_t CONSTRAINT_MIN_NONMOVABLE_SPACE_SIZE = 1_MB; static constexpr size_t CONSTRAINT_MIN_SNAPSHOT_SPACE_SIZE = 256_KB; static constexpr size_t CONSTRAINT_MIN_MACHINECODE_SPACE_SIZE = 4_MB; +static constexpr size_t MIN_MEM_POOL_CAPACITY = 32_MB; +static constexpr size_t PHY_SIZE_MULTIPLE = 4; + static constexpr size_t MIN_OLD_SPACE_LIMIT = 2_MB; static constexpr size_t MIN_GROWING_STEP = 16_MB; diff --git a/ecmascript/mem/mem_map_allocator.cpp b/ecmascript/mem/mem_map_allocator.cpp index b606cf73dc..232d523edc 100644 --- a/ecmascript/mem/mem_map_allocator.cpp +++ b/ecmascript/mem/mem_map_allocator.cpp @@ -14,7 +14,16 @@ */ #include "ecmascript/mem/mem_map_allocator.h" +#include "mem/runslots.h" +#if defined(PANDA_TARGET_WINDOWS) +#include +#elif defined(PANDA_TARGET_MACOS) +#include "sys/sysctl.h" +#else +#include "sys/sysinfo.h" +#endif #ifdef PANDA_TARGET_WINDOWS + void *mmap(size_t size, int fd, off_t offset) { HANDLE handle = reinterpret_cast(_get_osfhandle(fd)); @@ -93,4 +102,30 @@ MemMap MemMapAllocator::PageMap(size_t size, size_t alignment) #endif return MemMap(reinterpret_cast(alignResult), size); } + +void MemMapAllocator::AdapterSuitablePoolCapacity() +{ +#ifdef PANDA_TARGET_WINDOWS + MEMORYSTATUSEX status; + status.dwLength = sizeof(status); + GlobalMemoryStatusEx(&status); + long physSize = status.ullTotalPhys; +#elif PANDA_TARGET_MACOS + static constexpr int MIB_LENGTH = 2; + int mib[2]; + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + int64_t size = 0; + if (sysctl(mib, MIB_LENGTH, &size, sizeof(size), NULL, 0) != 0) { + LOG(FATAL, RUNTIME) << "sysctl error"; + } + long physSize = static_cast(size); +#else + auto pages = sysconf(_SC_PHYS_PAGES); + auto pageSize = sysconf(_SC_PAGE_SIZE); + long physSize = pages * pageSize; +#endif + capacity_ = std::max(physSize / PHY_SIZE_MULTIPLE, MIN_MEM_POOL_CAPACITY); + LOG(INFO, RUNTIME) << "Auto adapter memory pool capacity:" << capacity_; +} } // namespace panda::ecmascript diff --git a/ecmascript/mem/mem_map_allocator.h b/ecmascript/mem/mem_map_allocator.h index b898b7089f..357d73270d 100644 --- a/ecmascript/mem/mem_map_allocator.h +++ b/ecmascript/mem/mem_map_allocator.h @@ -199,11 +199,11 @@ public: NO_COPY_SEMANTIC(MemMapAllocator); NO_MOVE_SEMANTIC(MemMapAllocator); - void Initialize(size_t capacity, size_t alignment) + void Initialize(size_t alignment) { + AdapterSuitablePoolCapacity(); memMapTotalSize_ = 0; - capacity_ = capacity; - MemMap memMap = PageMap(capacity, alignment); + MemMap memMap = PageMap(capacity_ / 2, alignment); PageRelease(memMap.GetMem(), memMap.GetSize()); memMapFreeList_.Initialize(memMap); } @@ -249,6 +249,8 @@ private: #endif // PANDA_TARGET_UNIX } + void AdapterSuitablePoolCapacity(); + MemMapPool memMapPool_; MemMapFreeList memMapFreeList_; std::atomic_size_t memMapTotalSize_ {0}; diff --git a/ecmascript/napi/include/jsnapi.h b/ecmascript/napi/include/jsnapi.h index 0af9e28c18..02de20fe05 100644 --- a/ecmascript/napi/include/jsnapi.h +++ b/ecmascript/napi/include/jsnapi.h @@ -1107,7 +1107,7 @@ public: static void SetHostResolvePathTracker(EcmaVM *vm, std::function cb); static void SetHostEnqueueJob(const EcmaVM* vm, Local cb); - static void InitializeMemMapAllocator(const ecmascript::JSRuntimeOptions &options); + static void InitializeMemMapAllocator(); static void DestroyMemMapAllocator(); static EcmaVM* CreateEcmaVM(const ecmascript::JSRuntimeOptions &options); private: diff --git a/ecmascript/napi/jsnapi.cpp b/ecmascript/napi/jsnapi.cpp index 4e32c69de7..eeaf941d10 100644 --- a/ecmascript/napi/jsnapi.cpp +++ b/ecmascript/napi/jsnapi.cpp @@ -156,7 +156,7 @@ EcmaVM *JSNApi::CreateEcmaVM(const JSRuntimeOptions &options) os::memory::LockHolder lock(mutex); vmCount_++; if (!initialize_) { - InitializeMemMapAllocator(options); + InitializeMemMapAllocator(); initialize_ = true; } } @@ -473,9 +473,9 @@ Local JSNApi::GetExportObject(EcmaVM *vm, const std::string &file, co return JSNApiHelper::ToLocal(exportObj); } -void JSNApi::InitializeMemMapAllocator(const ecmascript::JSRuntimeOptions &options) +void JSNApi::InitializeMemMapAllocator() { - MemMapAllocator::GetInstance()->Initialize(options.GetHeapSizeLimit(), ecmascript::DEFAULT_REGION_SIZE); + MemMapAllocator::GetInstance()->Initialize(ecmascript::DEFAULT_REGION_SIZE); } void JSNApi::DestroyMemMapAllocator() From 22e34daa8fecf74d15b2e311e7c1acc2d8ae52ba Mon Sep 17 00:00:00 2001 From: hjzhangcm Date: Thu, 2 Jun 2022 19:07:12 +0800 Subject: [PATCH 18/35] describe:fix codex warning issue:https://gitee.com/openharmony/ark_js_runtime/issues/I5AM6L Signed-off-by: hjzhangcm --- ecmascript/mem/heap.cpp | 4 ++-- ecmascript/tooling/agent/runtime_impl.cpp | 16 ++++++++-------- ecmascript/ts_types/ts_loader.cpp | 2 +- ecmascript/ts_types/ts_type_table.cpp | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ecmascript/mem/heap.cpp b/ecmascript/mem/heap.cpp index 3eecbdc4c5..8aff009846 100644 --- a/ecmascript/mem/heap.cpp +++ b/ecmascript/mem/heap.cpp @@ -231,8 +231,8 @@ void Heap::Resume(TriggerGCType gcType) } if (activeSemiSpace_->AdjustCapacity(inactiveSemiSpace_->GetAllocatedSizeSinceGC())) { // if activeSpace capacity changes, oldSpace maximumCapacity should change, too. - int delta = activeSemiSpace_->GetInitialCapacity() - inactiveSemiSpace_->GetInitialCapacity(); - size_t oldSpaceMaxLimit = static_cast(oldSpace_->GetMaximumCapacity()) - delta * 2; + size_t delta = activeSemiSpace_->GetInitialCapacity() - inactiveSemiSpace_->GetInitialCapacity(); + size_t oldSpaceMaxLimit = oldSpace_->GetMaximumCapacity() - delta * 2; oldSpace_->SetMaximumCapacity(oldSpaceMaxLimit); inactiveSemiSpace_->SetInitialCapacity(activeSemiSpace_->GetInitialCapacity()); } diff --git a/ecmascript/tooling/agent/runtime_impl.cpp b/ecmascript/tooling/agent/runtime_impl.cpp index 9ad5d8a0b3..37764383a9 100644 --- a/ecmascript/tooling/agent/runtime_impl.cpp +++ b/ecmascript/tooling/agent/runtime_impl.cpp @@ -201,22 +201,22 @@ DispatchResponse RuntimeImpl::GetProperties(std::unique_ptr if (isAccessorOnly && !jsProperty.HasGetter() && !jsProperty.HasSetter()) { continue; } - if (jsProperty.HasGetter()) { + if (debuggerProperty->HasGet()) { debuggerProperty->GetGet()->SetObjectId(curObjectId_); properties_[curObjectId_++] = Global(vm_, jsProperty.GetGetter(vm_)); } - if (jsProperty.HasSetter()) { + if (debuggerProperty->HasSet()) { debuggerProperty->GetSet()->SetObjectId(curObjectId_); properties_[curObjectId_++] = Global(vm_, jsProperty.GetSetter(vm_)); } - if (jsProperty.HasValue()) { + if (debuggerProperty->HasValue()) { Local vValue = jsProperty.GetValue(vm_); if (vValue->IsObject() && !vValue->IsProxy()) { debuggerProperty->GetValue()->SetObjectId(curObjectId_); properties_[curObjectId_++] = Global(vm_, vValue); } } - if (name->IsSymbol()) { + if (debuggerProperty->HasSymbol()) { debuggerProperty->GetSymbol()->SetObjectId(curObjectId_); properties_[curObjectId_++] = Global(vm_, name); } @@ -323,7 +323,7 @@ void RuntimeImpl::GetAdditionalProperties(const Local &value, { // The length of the TypedArray have to be limited(less than or equal to lengthTypedArrayLimit) until we construct // the PropertyPreview class. Let lengthTypedArrayLimit be 10000 temporarily. - static const int32_t lengthTypedArrayLimit = 10000; + static const uint32_t lengthTypedArrayLimit = 10000; // The width of the string-expression for JSTypedArray::MAX_TYPED_ARRAY_INDEX which is euqal to // JSObject::MAX_ELEMENT_INDEX which is equal to std::numeric_limits::max(). (42,9496,7295) @@ -331,12 +331,12 @@ void RuntimeImpl::GetAdditionalProperties(const Local &value, if (value->IsTypedArray()) { Local localTypedArrayRef(value); - int32_t lengthTypedArray = localTypedArrayRef->ArrayLength(vm_); - if (lengthTypedArray < 0 || lengthTypedArray > lengthTypedArrayLimit) { + uint32_t lengthTypedArray = localTypedArrayRef->ArrayLength(vm_); + if (lengthTypedArray > lengthTypedArrayLimit) { LOG(ERROR, DEBUGGER) << "The length of the TypedArray is non-compliant or unsupported."; return; } - for (int32_t i = 0; i < lengthTypedArray; i++) { + for (uint32_t i = 0; i < lengthTypedArray; i++) { Local localValRefElement = localTypedArrayRef->Get(vm_, i); std::unique_ptr remoteObjElement = RemoteObject::FromTagged(vm_, localValRefElement); remoteObjElement->SetObjectId(curObjectId_); diff --git a/ecmascript/ts_types/ts_loader.cpp b/ecmascript/ts_types/ts_loader.cpp index 84a23b9fad..fb3fc39036 100644 --- a/ecmascript/ts_types/ts_loader.cpp +++ b/ecmascript/ts_types/ts_loader.cpp @@ -94,7 +94,7 @@ void TSLoader::RecursivelyResolveTargetType(JSMutableHandle& impor JSHandle moduleExportTable = TSTypeTable::GetExportValueTable(thread, typeTable); int localId = GetTypeIndexFromExportTable(target, moduleExportTable); - if (GlobalTSTypeRef(static_cast(localId)).IsBuiltinType()) { + if (GlobalTSTypeRef(static_cast(localId)).IsBuiltinType()) { importType->SetTargetRefGT(GlobalTSTypeRef(localId)); return; } diff --git a/ecmascript/ts_types/ts_type_table.cpp b/ecmascript/ts_types/ts_type_table.cpp index cdff72258d..6945877cde 100644 --- a/ecmascript/ts_types/ts_type_table.cpp +++ b/ecmascript/ts_types/ts_type_table.cpp @@ -558,7 +558,7 @@ JSHandle TSTypeTable::PushBackTypeToInferTable(JSThread *thread, JS const JSHandle &type) { uint32_t capacity = table->GetLength(); // can't be 0 due to RESERVE_TABLE_LENGTH - uint32_t numberOfTypes = table->GetNumberOfTypes(); + uint32_t numberOfTypes = static_cast(table->GetNumberOfTypes()); if (UNLIKELY(capacity <= numberOfTypes + RESERVE_TABLE_LENGTH)) { table = JSHandle(TaggedArray::SetCapacity(thread, JSHandle(table), capacity * INCREASE_CAPACITY_RATE)); From 6f90738f642c8ce29335a7e5117d632844131974 Mon Sep 17 00:00:00 2001 From: hjzhangcm Date: Tue, 31 May 2022 19:06:38 +0800 Subject: [PATCH 19/35] describe:Modify static alarm issue:https://gitee.com/openharmony/ark_js_runtime/issues/I5AA9J Signed-off-by: hjzhangcm --- .../assembler/aarch64/assembler_aarch64.cpp | 4 ++-- .../trampoline/aarch64/assembler_stubs.cpp | 3 +++ .../trampoline/x64/assembler_stubs_x64.cpp | 3 ++- ecmascript/js_handle.h | 1 + ecmascript/js_locale.cpp | 7 +------ ecmascript/js_plural_rules.cpp | 1 - ecmascript/jspandafile/js_pandafile_manager.cpp | 2 ++ ecmascript/module/js_module_source_text.cpp | 15 +++++---------- ecmascript/regexp/regexp_executor.h | 3 --- ecmascript/tagged_tree.cpp | 2 +- 10 files changed, 17 insertions(+), 24 deletions(-) diff --git a/ecmascript/compiler/assembler/aarch64/assembler_aarch64.cpp b/ecmascript/compiler/assembler/aarch64/assembler_aarch64.cpp index 521265d020..c694e5223e 100644 --- a/ecmascript/compiler/assembler/aarch64/assembler_aarch64.cpp +++ b/ecmascript/compiler/assembler/aarch64/assembler_aarch64.cpp @@ -710,12 +710,12 @@ void AssemblerAarch64::Lsr(const Register &rd, const Register &rn, unsigned shif { unsigned imms = 0; if (rd.IsW()) { - // 31 : 32-bit variant Applies when sf == 0 && N == 0 && imms == 011111 + // 31 : 31 32-bit variant Applies when sf == 0 && N == 0 && imms == 011111 // LSR , , # is equivalent to UBFM , , #, #31 // and is always the preferred disassembly imms = 31; } else { - // 63 : 64-bit variant Applies when sf == 1 && N == 1 && imms == 111111 + // 63 : 63 64-bit variant Applies when sf == 1 && N == 1 && imms == 111111 // LSR , , # is equivalent to UBFM , , #, #63 // and is always the preferred disassembly imms = 63; diff --git a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp index b8a3bfc388..54782d5255 100644 --- a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp +++ b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp @@ -340,6 +340,7 @@ void AssemblerStubs::CallBuiltinTrampoline(ExtendedAssembler *assembler) // construct leave frame and callee save Register frameType(X1); __ Mov(frameType, Immediate(static_cast(FrameType::LEAVE_FRAME))); + // 2 : 2 means pair __ Stp(nativeFuncAddr, frameType, MemoryOperand(sp, -FRAME_SLOT_SIZE * 2, AddrMode::PREINDEX)); // load runtime trampoline address @@ -353,10 +354,12 @@ void AssemblerStubs::CallBuiltinTrampoline(ExtendedAssembler *assembler) __ Sub(thread, glue, glueToThread); // thread __ Str(thread, MemoryOperand(sp, 0)); Register argC(X0); + // 1 : 1 means argC id __ Ldr(argC, MemoryOperand(fp, GetStackArgOffSetToFp(1))); // argc __ Sub(argC, argC, Immediate(NUM_MANDATORY_JSFUNC_ARGS)); __ Str(argC, MemoryOperand(sp, EcmaRuntimeCallInfo::GetNumArgsOffset())); Register argV(X0); + // 2 : 2 means argV id __ Add(argV, fp, Immediate(GetStackArgOffSetToFp(2))); // argV __ Str(argV, MemoryOperand(sp, EcmaRuntimeCallInfo::GetStackArgsOffset())); diff --git a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp index 41c8bde90a..20b6f10b8a 100644 --- a/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp +++ b/ecmascript/compiler/trampoline/x64/assembler_stubs_x64.cpp @@ -1278,7 +1278,8 @@ void AssemblerStubsX64::JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMo if (assembler->FromInterpreterHandler()) { auto jumpSize = kungfu::AssemblerModule::GetJumpSizeFromJSCallMode(mode); - auto offset = AsmInterpretedFrame::GetCallSizeOffset(false) - AsmInterpretedFrame::GetSize(false); + int32_t offset = static_cast( + AsmInterpretedFrame::GetCallSizeOffset(false) - AsmInterpretedFrame::GetSize(false)); __ Movq(static_cast(jumpSize), Operand(rbp, offset)); } diff --git a/ecmascript/js_handle.h b/ecmascript/js_handle.h index 4995e6a93f..86506c3494 100644 --- a/ecmascript/js_handle.h +++ b/ecmascript/js_handle.h @@ -160,6 +160,7 @@ public: inline explicit JSHandle(uintptr_t slot) : address_(slot) { if (!std::is_convertible::value) { + ASSERT(slot != 0); T::Cast((*reinterpret_cast(slot)).GetTaggedObject()); } } diff --git a/ecmascript/js_locale.cpp b/ecmascript/js_locale.cpp index 1cb402f634..2082f6cee5 100644 --- a/ecmascript/js_locale.cpp +++ b/ecmascript/js_locale.cpp @@ -134,7 +134,6 @@ bool JSLocale::IsValidTimeZoneName(const icu::TimeZone &tz) void JSLocale::HandleLocaleExtension(size_t &start, size_t &extensionEnd, const std::string result, size_t len) { - bool flag = false; while (start < len - INTL_INDEX_TWO) { if (result[start] != '-') { start++; @@ -142,13 +141,9 @@ void JSLocale::HandleLocaleExtension(size_t &start, size_t &extensionEnd, } if (result[start + INTL_INDEX_TWO] == '-') { extensionEnd = start; - flag = true; break; } - if (!flag) { - start++; - } - start += INTL_INDEX_TWO; + start += INTL_INDEX_THREE; } } diff --git a/ecmascript/js_plural_rules.cpp b/ecmascript/js_plural_rules.cpp index 5feac969ab..f3217a0fe3 100644 --- a/ecmascript/js_plural_rules.cpp +++ b/ecmascript/js_plural_rules.cpp @@ -218,7 +218,6 @@ JSHandle JSPluralRules::InitializePluralRules(JSThread *thread, if (!success || icuPluralRules == nullptr) { icu::Locale noExtensionLocale(icuLocale.getBaseName()); status = U_ZERO_ERROR; - icuType = UPLURAL_TYPE_CARDINAL; switch (type) { case TypeOption::ORDINAL: icuType = UPLURAL_TYPE_ORDINAL; diff --git a/ecmascript/jspandafile/js_pandafile_manager.cpp b/ecmascript/jspandafile/js_pandafile_manager.cpp index f3182547c2..64635a7f48 100644 --- a/ecmascript/jspandafile/js_pandafile_manager.cpp +++ b/ecmascript/jspandafile/js_pandafile_manager.cpp @@ -54,6 +54,7 @@ const JSPandaFile *JSPandaFileManager::LoadAotInfoFromPf(const CString &filename if (!jsPandaFile->HasTSTypes()) { LOG_ECMA(ERROR) << filename << " has no type info"; + ReleaseJSPandaFile(jsPandaFile); return nullptr; } @@ -67,6 +68,7 @@ const JSPandaFile *JSPandaFileManager::LoadAotInfoFromPf(const CString &filename } PandaFileTranslator::TranslateClasses(jsPandaFile, methodName, methodPcInfos); + InsertJSPandaFile(jsPandaFile); return jsPandaFile; } diff --git a/ecmascript/module/js_module_source_text.cpp b/ecmascript/module/js_module_source_text.cpp index 7c1caaa99e..d0e742b717 100644 --- a/ecmascript/module/js_module_source_text.cpp +++ b/ecmascript/module/js_module_source_text.cpp @@ -262,8 +262,7 @@ int SourceTextModule::Instantiate(JSThread *thread, const JSHandleGetStatus(); - ASSERT(status != ModuleStatus::INSTANTIATING && status != ModuleStatus::EVALUATING); + ASSERT(module->GetStatus() != ModuleStatus::INSTANTIATING && module->GetStatus() != ModuleStatus::EVALUATING); // 3. Let stack be a new empty List. CVector> stack; // 4. Let result be InnerModuleInstantiation(module, stack, 0). @@ -274,8 +273,7 @@ int SourceTextModule::Instantiate(JSThread *thread, const JSHandleGetStatus(); - ASSERT(mmStatus == ModuleStatus::INSTANTIATING); + ASSERT(mm->GetStatus() == ModuleStatus::INSTANTIATING); // ii. Set m.[[Status]] to "uninstantiated". mm->SetStatus(ModuleStatus::UNINSTANTIATED); // iii. Set m.[[Environment]] to undefined. @@ -285,14 +283,12 @@ int SourceTextModule::Instantiate(JSThread *thread, const JSHandleSetDFSAncestorIndex(SourceTextModule::UNDEFINED_INDEX); } // b. Assert: module.[[Status]] is "uninstantiated". - status = module->GetStatus(); - ASSERT(status == ModuleStatus::UNINSTANTIATED); + ASSERT(module->GetStatus() == ModuleStatus::UNINSTANTIATED); // c. return result return result; } // 6. Assert: module.[[Status]] is "instantiated" or "evaluated". - status = module->GetStatus(); - ASSERT(status == ModuleStatus::INSTANTIATED || status == ModuleStatus::EVALUATED); + ASSERT(module->GetStatus() == ModuleStatus::INSTANTIATED || module->GetStatus() == ModuleStatus::EVALUATED); // 7. Assert: stack is empty. ASSERT(stack.empty()); // 8. Return undefined. @@ -535,8 +531,7 @@ int SourceTextModule::Evaluate(JSThread *thread, const JSHandleGetStatus(); - ASSERT(mmStatus == ModuleStatus::EVALUATING); + ASSERT(mm->GetStatus() == ModuleStatus::EVALUATING); // ii. Set m.[[Status]] to "evaluated". mm->SetStatus(ModuleStatus::EVALUATED); // iii. Set m.[[EvaluationError]] to result. diff --git a/ecmascript/regexp/regexp_executor.h b/ecmascript/regexp/regexp_executor.h index 2df3ba8f01..df66b3037a 100644 --- a/ecmascript/regexp/regexp_executor.h +++ b/ecmascript/regexp/regexp_executor.h @@ -493,7 +493,6 @@ public: c1 = *(uint16_t *)cptr; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) if (U16_IS_TRAIL(c1)) { c = static_cast(U16_GET_SUPPLEMENTARY(c, c1)); // NOLINTNEXTLINE(hicpp-signed-bitwise) - cptr += WIDE_CHAR_SIZE; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) } } } @@ -526,7 +525,6 @@ public: const uint8_t *cptr = p; if (!isWideChar_) { c = *(cptr - 1); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - cptr -= 1; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) } else { cptr -= WIDE_CHAR_SIZE; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) @@ -537,7 +535,6 @@ public: c1 = (reinterpret_cast(cptr))[-1]; if (U16_IS_LEAD(c1)) { c = static_cast(U16_GET_SUPPLEMENTARY(c1, c)); // NOLINTNEXTLINE(hicpp-signed-bitwise) - cptr -= WIDE_CHAR_SIZE; // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) } } } diff --git a/ecmascript/tagged_tree.cpp b/ecmascript/tagged_tree.cpp index 6f59040582..e58830d5bb 100644 --- a/ecmascript/tagged_tree.cpp +++ b/ecmascript/tagged_tree.cpp @@ -386,7 +386,7 @@ JSHandle TaggedTree::Insert(JSThread *thread, JSHandleNumberOfElements() + newTree->NumberOfDeletedElements(); - if (static_cast(res)) { + if (res != ComparisonResult::LESS) { newTree->InsertRightEntry(thread, parentIndex, entry, key.GetTaggedValue(), value.GetTaggedValue()); } else { newTree->InsertLeftEntry(thread, parentIndex, entry, key.GetTaggedValue(), value.GetTaggedValue()); From c85139a4c745e414f51404c0d9b1b30fdbe8b4bc Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Mon, 6 Jun 2022 11:35:21 +0800 Subject: [PATCH 20/35] Descriptor: deal with invalid exception details: add empty check issue: https://gitee.com/openharmony/ark_js_runtime/issues/I5AT96 Signed-off-by: wengchangcheng Change-Id: I114a557d7b431f65b1a6145c2f0a0e674789e771 --- ecmascript/tooling/agent/debugger_impl.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ecmascript/tooling/agent/debugger_impl.cpp b/ecmascript/tooling/agent/debugger_impl.cpp index cbefad38cd..266f31ef68 100644 --- a/ecmascript/tooling/agent/debugger_impl.cpp +++ b/ecmascript/tooling/agent/debugger_impl.cpp @@ -527,7 +527,11 @@ DispatchResponse DebuggerImpl::EvaluateOnCallFrame(std::unique_ptr DebuggerImpl::CmptEvaluateValue(CallFrameId callFrameId, } } else { Local value = ConvertToLocal(varValue); + if (value.IsEmpty()) { + return "Unsupported expression."; + } bool ret = DebuggerExecutor::SetValue(vm_, frameHandler, name, value); if (ret) { *result = RemoteObject::FromTagged(vm_, value); From 55dcd77afb073540939258d193efd1ff86fb64db Mon Sep 17 00:00:00 2001 From: xdmal Date: Thu, 2 Jun 2022 17:09:49 +0800 Subject: [PATCH 21/35] add unittest case for WeakRef and FinalizationRegistry add unittest case for WeakRef and FinalizationRegistry issue:https://gitee.com/openharmony/ark_js_runtime/issues/I5AL8K Signed-off-by: xdmal --- .../builtins_finalizationregistry_test.cpp | 202 ++++++++++++++++-- .../builtins/tests/builtins_weak_ref_test.cpp | 111 ++++++---- test/moduletest/finalizationregistry/BUILD.gn | 18 -- .../finalizationregistry/expect_output.txt | 16 -- .../finalizationregistry.js | 37 ---- 5 files changed, 248 insertions(+), 136 deletions(-) delete mode 100644 test/moduletest/finalizationregistry/BUILD.gn delete mode 100644 test/moduletest/finalizationregistry/expect_output.txt delete mode 100644 test/moduletest/finalizationregistry/finalizationregistry.js diff --git a/ecmascript/builtins/tests/builtins_finalizationregistry_test.cpp b/ecmascript/builtins/tests/builtins_finalizationregistry_test.cpp index abc44f330e..bec679f736 100644 --- a/ecmascript/builtins/tests/builtins_finalizationregistry_test.cpp +++ b/ecmascript/builtins/tests/builtins_finalizationregistry_test.cpp @@ -17,6 +17,7 @@ #include "ecmascript/js_finalization_registry.h" #include "ecmascript/ecma_vm.h" #include "ecmascript/global_env.h" +#include "ecmascript/jobs/micro_job_queue.h" #include "ecmascript/js_array.h" #include "ecmascript/js_array_iterator.h" @@ -32,12 +33,10 @@ #include "ecmascript/tests/test_helper.h" #include "utils/bit_utils.h" -#include "ecmascript/jobs/micro_job_queue.h" - using namespace panda::ecmascript; using namespace panda::ecmascript::builtins; using BuiltinsBase = panda::ecmascript::base::BuiltinsBase; -static JSTaggedValue testArgv = JSTaggedValue(0); +static int testValue = 0; namespace panda::test { class BuiltinsFinalizationRegistryTest : public testing::Test { @@ -70,7 +69,7 @@ public: public: static JSTaggedValue cleanupCallback() { - testArgv = JSTaggedValue(10); // number of 10 + ++testValue; return JSTaggedValue::Undefined(); } }; @@ -116,6 +115,7 @@ HWTEST_F_L0(BuiltinsFinalizationRegistryTest, FinalizationRegistryConstructor) // finalizationRegistry.Register(target, heldValue [ , unregisterToken ]) HWTEST_F_L0(BuiltinsFinalizationRegistryTest, Register1) { + testValue = 0; ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objectFunc = env->GetObjectFunction(); @@ -136,12 +136,13 @@ HWTEST_F_L0(BuiltinsFinalizationRegistryTest, Register1) [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); BuiltinsFinalizationRegistry::Register(ecmaRuntimeCallInfo.get()); - ASSERT_EQ(testArgv, JSTaggedValue(0)); + ASSERT_EQ(testValue, 0); } // finalizationRegistry.Register(target, heldValue [ , unregisterToken ]) HWTEST_F_L0(BuiltinsFinalizationRegistryTest, Register2) { + testValue = 0; EcmaVM *vm = thread->GetEcmaVM(); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); @@ -149,31 +150,143 @@ HWTEST_F_L0(BuiltinsFinalizationRegistryTest, Register2) JSTaggedValue result = CreateFinalizationRegistryConstructor(thread); JSHandle jsfinalizationRegistry(thread, result); - JSTaggedValue target = - factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc).GetTaggedValue(); + vm->SetEnableForceGC(false); + JSTaggedValue target = JSTaggedValue::Undefined(); + { + [[maybe_unused]] EcmaHandleScope handleScope(thread); + auto obj = + factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc); + target = obj.GetTaggedValue(); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(jsfinalizationRegistry.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(0, target); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(10)); + ecmaRuntimeCallInfo->SetCallArg(2, target); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); - ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); - ecmaRuntimeCallInfo->SetThis(jsfinalizationRegistry.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, target); - ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(10)); - ecmaRuntimeCallInfo->SetCallArg(2, target); - target = JSTaggedValue::Undefined(); - - [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); - BuiltinsFinalizationRegistry::Register(ecmaRuntimeCallInfo.get()); - [[maybe_unused]] JSTaggedValue target22 = - factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc).GetTaggedValue(); + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + BuiltinsFinalizationRegistry::Register(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + } vm->CollectGarbage(TriggerGCType::FULL_GC); if (!thread->HasPendingException()) { job::MicroJobQueue::ExecutePendingJob(thread, vm->GetMicroJobQueue()); } - ASSERT_EQ(testArgv, JSTaggedValue(0)); + vm->SetEnableForceGC(true); + ASSERT_EQ(testValue, 1); +} + +// finalizationRegistry.Register(target, heldValue [ , unregisterToken ]) +HWTEST_F_L0(BuiltinsFinalizationRegistryTest, Register3) +{ + testValue = 0; + EcmaVM *vm = thread->GetEcmaVM(); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + JSHandle objectFunc = env->GetObjectFunction(); + + JSTaggedValue result = CreateFinalizationRegistryConstructor(thread); + JSHandle jsfinalizationRegistry(thread, result); + + vm->SetEnableForceGC(false); + JSTaggedValue target = JSTaggedValue::Undefined(); + JSTaggedValue target1 = JSTaggedValue::Undefined(); + { + [[maybe_unused]] EcmaHandleScope handleScope(thread); + auto obj = + factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc); + auto obj1 = + factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc); + target = obj.GetTaggedValue(); + target1 = obj1.GetTaggedValue(); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(jsfinalizationRegistry.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(0, target); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(10)); + ecmaRuntimeCallInfo->SetCallArg(2, target); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + BuiltinsFinalizationRegistry::Register(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo1->SetThis(jsfinalizationRegistry.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(0, target1); + ecmaRuntimeCallInfo1->SetCallArg(1, JSTaggedValue(10)); + ecmaRuntimeCallInfo1->SetCallArg(2, target1); + + [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1.get()); + BuiltinsFinalizationRegistry::Register(ecmaRuntimeCallInfo1.get()); + TestHelper::TearDownFrame(thread, prev1); + } + vm->CollectGarbage(TriggerGCType::FULL_GC); + if (!thread->HasPendingException()) { + job::MicroJobQueue::ExecutePendingJob(thread, vm->GetMicroJobQueue()); + } + vm->SetEnableForceGC(true); + ASSERT_EQ(testValue, 2); +} + +// finalizationRegistry.Register(target, heldValue [ , unregisterToken ]) +HWTEST_F_L0(BuiltinsFinalizationRegistryTest, Register4) +{ + testValue = 0; + EcmaVM *vm = thread->GetEcmaVM(); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + JSHandle objectFunc = env->GetObjectFunction(); + + JSTaggedValue result = CreateFinalizationRegistryConstructor(thread); + JSHandle jsfinalizationRegistry(thread, result); + JSTaggedValue result1 = CreateFinalizationRegistryConstructor(thread); + JSHandle jsfinalizationRegistry1(thread, result1); + vm->SetEnableForceGC(false); + JSTaggedValue target = JSTaggedValue::Undefined(); + JSTaggedValue target1 = JSTaggedValue::Undefined(); + { + [[maybe_unused]] EcmaHandleScope handleScope(thread); + auto obj = + factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc); + auto obj1 = + factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc); + target = obj.GetTaggedValue(); + target1 = obj1.GetTaggedValue(); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(jsfinalizationRegistry.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(0, target); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(10)); + ecmaRuntimeCallInfo->SetCallArg(2, target); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + BuiltinsFinalizationRegistry::Register(ecmaRuntimeCallInfo.get()); + TestHelper::TearDownFrame(thread, prev); + + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo1->SetThis(jsfinalizationRegistry1.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(0, target1); + ecmaRuntimeCallInfo1->SetCallArg(1, JSTaggedValue(10)); + ecmaRuntimeCallInfo1->SetCallArg(2, target1); + + [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1.get()); + BuiltinsFinalizationRegistry::Register(ecmaRuntimeCallInfo1.get()); + TestHelper::TearDownFrame(thread, prev1); + } + vm->CollectGarbage(TriggerGCType::FULL_GC); + if (!thread->HasPendingException()) { + job::MicroJobQueue::ExecutePendingJob(thread, vm->GetMicroJobQueue()); + } + vm->SetEnableForceGC(true); + ASSERT_EQ(testValue, 2); } // finalizationRegistry.Unregister(unregisterToken ]) -HWTEST_F_L0(BuiltinsFinalizationRegistryTest, Unregister) +HWTEST_F_L0(BuiltinsFinalizationRegistryTest, Unregister1) { + testValue = 0; ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle objectFunc = env->GetObjectFunction(); @@ -201,7 +314,50 @@ HWTEST_F_L0(BuiltinsFinalizationRegistryTest, Unregister) ecmaRuntimeCallInfo1->SetCallArg(0, target.GetTaggedValue()); [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1.get()); - BuiltinsFinalizationRegistry::Register(ecmaRuntimeCallInfo1.get()); - ASSERT_EQ(testArgv, JSTaggedValue(0)); + BuiltinsFinalizationRegistry::Unregister(ecmaRuntimeCallInfo1.get()); + ASSERT_EQ(testValue, 0); +} + +HWTEST_F_L0(BuiltinsFinalizationRegistryTest, Unregister2) +{ + testValue = 0; + EcmaVM *vm = thread->GetEcmaVM(); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + JSHandle objectFunc = env->GetObjectFunction(); + + JSTaggedValue result = CreateFinalizationRegistryConstructor(thread); + JSHandle jsfinalizationRegistry(thread, result); + vm->SetEnableForceGC(false); + JSTaggedValue target = JSTaggedValue::Undefined(); + { + [[maybe_unused]] EcmaHandleScope handleScope(thread); + auto obj = + factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc); + target = obj.GetTaggedValue(); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(jsfinalizationRegistry.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(0, target); + ecmaRuntimeCallInfo->SetCallArg(1, JSTaggedValue(10)); + ecmaRuntimeCallInfo->SetCallArg(2, target); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + BuiltinsFinalizationRegistry::Register(ecmaRuntimeCallInfo.get()); + + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6); + ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo1->SetThis(jsfinalizationRegistry.GetTaggedValue()); + ecmaRuntimeCallInfo1->SetCallArg(0, target); + + BuiltinsFinalizationRegistry::Unregister(ecmaRuntimeCallInfo1.get()); + TestHelper::TearDownFrame(thread, prev); + } + vm->CollectGarbage(TriggerGCType::FULL_GC); + if (!thread->HasPendingException()) { + job::MicroJobQueue::ExecutePendingJob(thread, vm->GetMicroJobQueue()); + } + vm->SetEnableForceGC(true); + ASSERT_EQ(testValue, 0); } } // namespace panda::test diff --git a/ecmascript/builtins/tests/builtins_weak_ref_test.cpp b/ecmascript/builtins/tests/builtins_weak_ref_test.cpp index 5f8a19dbfe..c25e0697f7 100644 --- a/ecmascript/builtins/tests/builtins_weak_ref_test.cpp +++ b/ecmascript/builtins/tests/builtins_weak_ref_test.cpp @@ -15,6 +15,7 @@ #include "ecmascript/base/builtins_base.h" #include "ecmascript/builtins/builtins_weak_ref.h" +#include "ecmascript/jobs/micro_job_queue.h" #include "ecmascript/js_weak_ref.h" #include "ecmascript/tests/test_helper.h" #include "ecmascript/ecma_runtime_call_info.h" @@ -65,15 +66,29 @@ public: JSThread *thread {nullptr}; }; +JSTaggedValue CreateWeakRefConstructor(JSThread *thread, JSTaggedValue target) +{ + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + JSHandle globalObject(thread, env->GetGlobalObject()); + JSHandle weakRef(env->GetBuiltinsWeakRefFunction()); + + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue(*weakRef), 6); + ecmaRuntimeCallInfo->SetFunction(weakRef.GetTaggedValue()); + ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); + ecmaRuntimeCallInfo->SetCallArg(0, target); + + [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); + return JSTaggedValue(BuiltinsWeakRef::WeakRefConstructor(ecmaRuntimeCallInfo.get())); +} + // new WeakRef(target) HWTEST_F_L0(BuiltinsWeakRefTest, WeakRefConstructor) { - JSHandle globalEnv = thread->GetEcmaVM()->GetGlobalEnv(); + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - JSHandle objectFunc(globalEnv->GetObjectFunction()); + JSHandle objectFunc(env->GetObjectFunction()); JSHandle target(factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc)); - JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle weakRef(env->GetBuiltinsWeakRefFunction()); JSHandle globalObject(thread, env->GetGlobalObject()); @@ -96,31 +111,16 @@ HWTEST_F_L0(BuiltinsWeakRefTest, Deref1) ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objectFunc(env->GetObjectFunction()); - JSHandle weakRef(env->GetBuiltinsWeakRefFunction()); - JSHandle globalObject(thread, env->GetGlobalObject()); JSHandle target(factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc)); - JSHandle formatStyle = thread->GlobalConstants()->GetHandledStyleString(); - JSHandle styleKey(factory->NewFromASCII("currency")); - JSHandle styleValue(factory->NewFromASCII("EUR")); - JSObject::SetProperty(thread, target, formatStyle, styleKey); - JSObject::SetProperty(thread, target, styleKey, styleValue); - - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, weakRef.GetTaggedValue(), 6); - ecmaRuntimeCallInfo->SetFunction(weakRef.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, target.GetTaggedValue()); + JSTaggedValue result = CreateWeakRefConstructor(thread, target.GetTaggedValue()); + JSHandle jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast(result.GetRawData()))); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(jsWeakRef.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); - JSTaggedValue result = BuiltinsWeakRef::WeakRefConstructor(ecmaRuntimeCallInfo.get()); - JSHandle jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast(result.GetRawData()))); - - auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); - ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); - ecmaRuntimeCallInfo1->SetThis(jsWeakRef.GetTaggedValue()); - ecmaRuntimeCallInfo1->SetCallArg(0, target.GetTaggedValue()); - [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1.get()); - JSTaggedValue result1 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo1.get()); - EXPECT_TRUE(!result1.IsUndefined()); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue result1 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo.get()); ASSERT_EQ(result1, target.GetTaggedValue()); } @@ -130,33 +130,60 @@ HWTEST_F_L0(BuiltinsWeakRefTest, Deref2) JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objectFunc(env->GetObjectFunction()); - - JSHandle weakRef(env->GetBuiltinsWeakRefFunction()); - JSHandle globalObject(thread, env->GetGlobalObject()); - JSHandle target(factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc)); JSHandle formatStyle = thread->GlobalConstants()->GetHandledStyleString(); JSHandle styleKey(factory->NewFromASCII("currency")); JSHandle styleValue(factory->NewFromASCII("EUR")); + JSHandle target(factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc)); JSObject::SetProperty(thread, target, formatStyle, styleKey); JSObject::SetProperty(thread, target, styleKey, styleValue); - auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, weakRef.GetTaggedValue(), 6); - ecmaRuntimeCallInfo->SetFunction(weakRef.GetTaggedValue()); - ecmaRuntimeCallInfo->SetThis(globalObject.GetTaggedValue()); - ecmaRuntimeCallInfo->SetCallArg(0, target.GetTaggedValue()); + JSTaggedValue result = CreateWeakRefConstructor(thread, target.GetTaggedValue()); + JSHandle jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast(result.GetRawData()))); + auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo->SetThis(jsWeakRef.GetTaggedValue()); [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo.get()); - JSTaggedValue result = BuiltinsWeakRef::WeakRefConstructor(ecmaRuntimeCallInfo.get()); - JSHandle jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast(result.GetRawData()))); - - auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8); - ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); - ecmaRuntimeCallInfo1->SetThis(jsWeakRef.GetTaggedValue()); - ecmaRuntimeCallInfo1->SetCallArg(0, target.GetTaggedValue()); - [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1.get()); - JSTaggedValue result1 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo1.get()); + TestHelper::TearDownFrame(thread, prev); + JSTaggedValue result1 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo.get()); + ASSERT_EQ(result1, target.GetTaggedValue()); JSObject::SetProperty(thread, target, styleKey, styleValue); ASSERT_EQ(result1, target.GetTaggedValue()); } + +// weakRef.Deref() +HWTEST_F_L0(BuiltinsWeakRefTest, Deref3) +{ + EcmaVM *vm = thread->GetEcmaVM(); + JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + JSHandle objectFunc(env->GetObjectFunction()); + + JSTaggedValue target = + factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc).GetTaggedValue(); + JSTaggedValue result = CreateWeakRefConstructor(thread, target); + JSHandle jsWeakRef(thread, JSWeakRef::Cast(reinterpret_cast(result.GetRawData()))); + JSTaggedValue result2 = JSTaggedValue::Undefined(); + + { + [[maybe_unused]] EcmaHandleScope handleScope(thread); + auto obj = + factory->NewJSObjectByConstructor(JSHandle(objectFunc), objectFunc); + target = obj.GetTaggedValue(); + auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 4); + ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined()); + ecmaRuntimeCallInfo1->SetThis(jsWeakRef.GetTaggedValue()); + + [[maybe_unused]] auto prev1 = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1.get()); + result2 = BuiltinsWeakRef::Deref(ecmaRuntimeCallInfo1.get()); + TestHelper::TearDownFrame(thread, prev1); + } + vm->CollectGarbage(TriggerGCType::FULL_GC); + if (!thread->HasPendingException()) { + job::MicroJobQueue::ExecutePendingJob(thread, vm->GetMicroJobQueue()); + } + vm->SetEnableForceGC(true); + ASSERT_TRUE(!result2.IsUndefined()); +} } // namespace panda::test diff --git a/test/moduletest/finalizationregistry/BUILD.gn b/test/moduletest/finalizationregistry/BUILD.gn deleted file mode 100644 index b2ea58ea3a..0000000000 --- a/test/moduletest/finalizationregistry/BUILD.gn +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2021 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_moduletest_action("finalizationregistry") { - deps = [] -} diff --git a/test/moduletest/finalizationregistry/expect_output.txt b/test/moduletest/finalizationregistry/expect_output.txt deleted file mode 100644 index ef2e721d9f..0000000000 --- a/test/moduletest/finalizationregistry/expect_output.txt +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2021 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. - -hello=====3333 -hello====222 -hello diff --git a/test/moduletest/finalizationregistry/finalizationregistry.js b/test/moduletest/finalizationregistry/finalizationregistry.js deleted file mode 100644 index f8ca66d599..0000000000 --- a/test/moduletest/finalizationregistry/finalizationregistry.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2021 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. - */ - -var fn = function(held) { - print(held); - } - var obj = {name:'ddd'}; - var obj2 = {name:'fff'}; - var fin = new FinalizationRegistry(fn); - var fin2 = new FinalizationRegistry(fn); - var fin3 = new FinalizationRegistry(fn); - - if(true){ - fin.register(obj, 'hello'); - fin.register(obj2, 'hello123'); - fin2.register(obj, 'hello====222'); - fin2.register(obj2, 'hello====456'); - fin3.register(obj, 'hello=====3333'); - fin3.register(obj2, 'hello=====789'); - } - obj = undefined; - // Create variable to wait for variable obj to be GC - for(var i = 0; i < 500000; ++i) { - var a = BigInt(123); - } From 717a4a3de521963f3200687fe094a130b95b3b0d Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Mon, 6 Jun 2022 20:37:57 +0800 Subject: [PATCH 22/35] Added method to set sampling interval add ProfileImpl.SetSamplingInterval ISSUE:https://gitee.com/openharmony/ark_js_runtime/issues/I5A8ZK Signed-off-by: buzhuyu Change-Id: I39912ff70935d947222e9aef0340063ab82b6717 --- ecmascript/dfx/cpu_profiler/cpu_profiler.cpp | 5 ++ ecmascript/dfx/cpu_profiler/cpu_profiler.h | 1 + ecmascript/napi/dfx_jsnapi.cpp | 6 +++ ecmascript/napi/include/dfx_jsnapi.h | 1 + ecmascript/tooling/agent/profiler_impl.cpp | 19 +++++++ ecmascript/tooling/agent/profiler_impl.h | 2 + ecmascript/tooling/base/pt_params.cpp | 39 ++++++++++++++ ecmascript/tooling/base/pt_params.h | 26 +++++++++ .../tooling/test/debugger_params_test.cpp | 54 +++++++++++++++++++ 9 files changed, 153 insertions(+) diff --git a/ecmascript/dfx/cpu_profiler/cpu_profiler.cpp b/ecmascript/dfx/cpu_profiler/cpu_profiler.cpp index 42c59f27b8..d894de9152 100644 --- a/ecmascript/dfx/cpu_profiler/cpu_profiler.cpp +++ b/ecmascript/dfx/cpu_profiler/cpu_profiler.cpp @@ -161,6 +161,11 @@ std::unique_ptr CpuProfiler::StopCpuProfilerForInfo() return profileInfo; } +void CpuProfiler::SetCpuSamplingInterval(int interval) +{ + interval_ = interval; +} + void CpuProfiler::StopCpuProfilerForFile() { if (!isProfiling_) { diff --git a/ecmascript/dfx/cpu_profiler/cpu_profiler.h b/ecmascript/dfx/cpu_profiler/cpu_profiler.h index f05b91bc55..60ae0b2c8e 100644 --- a/ecmascript/dfx/cpu_profiler/cpu_profiler.h +++ b/ecmascript/dfx/cpu_profiler/cpu_profiler.h @@ -62,6 +62,7 @@ public: std::unique_ptr StopCpuProfilerForInfo(); void StartCpuProfilerForFile(const EcmaVM *vm, const std::string &fileName); void StopCpuProfilerForFile(); + void SetCpuSamplingInterval(int interval); std::string GetProfileName() const; virtual ~CpuProfiler(); diff --git a/ecmascript/napi/dfx_jsnapi.cpp b/ecmascript/napi/dfx_jsnapi.cpp index f1691c9144..8aecab7d90 100644 --- a/ecmascript/napi/dfx_jsnapi.cpp +++ b/ecmascript/napi/dfx_jsnapi.cpp @@ -160,6 +160,12 @@ std::unique_ptr DFXJSNApi::StopCpuProfilerForInfo() } return profile; } + +void DFXJSNApi::SetCpuSamplingInterval(int interval) +{ + CpuProfiler *singleton = CpuProfiler::GetInstance(); + singleton->SetCpuSamplingInterval(interval); +} #endif bool DFXJSNApi::SuspendVM(const EcmaVM *vm) diff --git a/ecmascript/napi/include/dfx_jsnapi.h b/ecmascript/napi/include/dfx_jsnapi.h index cf8a1ae768..75dcd350ba 100644 --- a/ecmascript/napi/include/dfx_jsnapi.h +++ b/ecmascript/napi/include/dfx_jsnapi.h @@ -66,6 +66,7 @@ public: static void StopCpuProfilerForFile(); static void StartCpuProfilerForInfo(const EcmaVM *vm); static std::unique_ptr StopCpuProfilerForInfo(); + static void SetCpuSamplingInterval(int interval); #endif static void ResumeVM(const EcmaVM *vm); diff --git a/ecmascript/tooling/agent/profiler_impl.cpp b/ecmascript/tooling/agent/profiler_impl.cpp index 7167d3e456..def58ac132 100644 --- a/ecmascript/tooling/agent/profiler_impl.cpp +++ b/ecmascript/tooling/agent/profiler_impl.cpp @@ -28,6 +28,7 @@ void ProfilerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) { "enable", &ProfilerImpl::DispatcherImpl::Enable }, { "start", &ProfilerImpl::DispatcherImpl::Start }, { "stop", &ProfilerImpl::DispatcherImpl::Stop }, + { "SetSamplingInterval", &ProfilerImpl::DispatcherImpl::SetSamplingInterval }, { "getBestEffortCoverage", &ProfilerImpl::DispatcherImpl::GetBestEffortCoverage }, { "stopPreciseCoverage", &ProfilerImpl::DispatcherImpl::StopPreciseCoverage }, { "takePreciseCoverage", &ProfilerImpl::DispatcherImpl::TakePreciseCoverage }, @@ -73,6 +74,18 @@ void ProfilerImpl::DispatcherImpl::Stop(const DispatchRequest &request) SendResponse(request, response, result); } +void ProfilerImpl::DispatcherImpl::SetSamplingInterval(const DispatchRequest &request) +{ + std::unique_ptr params = + SetSamplingIntervalParams::Create(request.GetEcmaVM(), request.GetParams()); + if (params == nullptr) { + SendResponse(request, DispatchResponse::Fail("wrong params")); + return; + } + DispatchResponse response = profiler_->SetSamplingInterval(std::move(params)); + SendResponse(request, response); +} + void ProfilerImpl::DispatcherImpl::GetBestEffortCoverage(const DispatchRequest &request) { DispatchResponse response = profiler_->GetBestEffortCoverage(); @@ -185,6 +198,12 @@ DispatchResponse ProfilerImpl::Stop(std::unique_ptr *profile) return DispatchResponse::Ok(); } +DispatchResponse ProfilerImpl::SetSamplingInterval(std::unique_ptr params) +{ + panda::DFXJSNApi::SetCpuSamplingInterval(params->GetInterval()); + return DispatchResponse::Ok(); +} + DispatchResponse ProfilerImpl::GetBestEffortCoverage() { LOG(ERROR, DEBUGGER) << "GetBestEffortCoverage not support now."; diff --git a/ecmascript/tooling/agent/profiler_impl.h b/ecmascript/tooling/agent/profiler_impl.h index 05a9650be7..d7791f62bd 100644 --- a/ecmascript/tooling/agent/profiler_impl.h +++ b/ecmascript/tooling/agent/profiler_impl.h @@ -32,6 +32,7 @@ public: DispatchResponse Enable(); DispatchResponse Start(); DispatchResponse Stop(std::unique_ptr *profile); + DispatchResponse SetSamplingInterval(std::unique_ptr params); DispatchResponse GetBestEffortCoverage(); DispatchResponse StopPreciseCoverage(); DispatchResponse TakePreciseCoverage(); @@ -51,6 +52,7 @@ public: void Disable(const DispatchRequest &request); void Start(const DispatchRequest &request); void Stop(const DispatchRequest &request); + void SetSamplingInterval(const DispatchRequest &request); void GetBestEffortCoverage(const DispatchRequest &request); void StopPreciseCoverage(const DispatchRequest &request); void TakePreciseCoverage(const DispatchRequest &request); diff --git a/ecmascript/tooling/base/pt_params.cpp b/ecmascript/tooling/base/pt_params.cpp index 2066def7d1..3347063c85 100644 --- a/ecmascript/tooling/base/pt_params.cpp +++ b/ecmascript/tooling/base/pt_params.cpp @@ -1057,4 +1057,43 @@ Local StartPreciseCoverageParam::ToObject(const EcmaVM *ecmaVm) const return params; } + +std::unique_ptr SetSamplingIntervalParams::Create(const EcmaVM *ecmaVm, + const Local ¶ms) +{ + ASSERT(ecmaVm); + if (params.IsEmpty()) { + LOG(ERROR, DEBUGGER) << "SetSamplingIntervalParams::Create params is nullptr"; + return nullptr; + } + CString error; + auto paramsObject = std::make_unique(); + + Local result = + Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "interval"))); + if (!result.IsEmpty() && !result->IsUndefined()) { + if (result->IsNumber()) { + paramsObject->interval_ = static_cast(Local(result)->Value()); + } else { + error += "'interval' should be a Number;"; + } + } else { + error += "should contain 'interval';"; + } + + if (!error.empty()) { + LOG(ERROR, DEBUGGER) << "SetSamplingIntervalParams::Create " << error; + return nullptr; + } + return paramsObject; +} + +Local SetSamplingIntervalParams::ToObject(const EcmaVM *ecmaVm) const +{ + Local params = NewObject(ecmaVm); + + params->Set(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "interval")), + IntegerRef::New(ecmaVm, interval_)); + return params; +} } // namespace panda::ecmascript::tooling diff --git a/ecmascript/tooling/base/pt_params.h b/ecmascript/tooling/base/pt_params.h index cb16cc45e7..c14c7819a4 100644 --- a/ecmascript/tooling/base/pt_params.h +++ b/ecmascript/tooling/base/pt_params.h @@ -868,5 +868,31 @@ private: std::optional detailed_ {}; std::optional allowTriggeredUpdates_ {}; }; + +class SetSamplingIntervalParams : public PtBaseParams { +public: + SetSamplingIntervalParams() = default; + ~SetSamplingIntervalParams() override = default; + + static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); + Local ToObject(const EcmaVM *ecmaVm) const override; + + int GetInterval() const + { + return interval_; + } + + SetSamplingIntervalParams &SetInterval(int interval) + { + interval_ = interval; + return *this; + } + +private: + NO_COPY_SEMANTIC(SetSamplingIntervalParams); + NO_MOVE_SEMANTIC(SetSamplingIntervalParams); + + int interval_ {0}; +}; } // namespace panda::ecmascript::tooling #endif \ No newline at end of file diff --git a/ecmascript/tooling/test/debugger_params_test.cpp b/ecmascript/tooling/test/debugger_params_test.cpp index f95c54dbba..42ee1f58f0 100644 --- a/ecmascript/tooling/test/debugger_params_test.cpp +++ b/ecmascript/tooling/test/debugger_params_test.cpp @@ -553,4 +553,58 @@ HWTEST_F_L0(DebuggerParamsTest, StartPreciseCoverageParamToObjectTest) ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); ASSERT_TRUE(result->IsTrue()); } + +HWTEST_F_L0(DebuggerParamsTest, SetSamplingIntervalParamsCreateTest) +{ + CString msg; + std::unique_ptr objectData; + + // abnormal params of null msg + msg = CString() + R"({})"; + objectData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); + EXPECT_EQ(objectData, nullptr); + + // abnormal params of unexist key params + msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + objectData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); + EXPECT_EQ(objectData, nullptr); + + // abnormal params of null params.sub-key + msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + objectData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); + EXPECT_EQ(objectData, nullptr); + + // abnormal params of unknown params.sub-key + msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + objectData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); + EXPECT_EQ(objectData, nullptr); + + msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + "interval":"500"}})"; + objectData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); + EXPECT_EQ(objectData, nullptr); + + msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"interval":500}})"; + objectData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); + ASSERT_NE(objectData, nullptr); + EXPECT_EQ(objectData->GetInterval(), 500); +} + +HWTEST_F_L0(DebuggerParamsTest, SetSamplingIntervalParamsToObjectTest) +{ + CString msg; + std::unique_ptr setSamplingIntervalData; + Local tmpStr; + + msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"interval":500}})"; + setSamplingIntervalData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); + ASSERT_NE(setSamplingIntervalData, nullptr); + Local object = setSamplingIntervalData->ToObject(ecmaVm); + + tmpStr = StringRef::NewFromUtf8(ecmaVm, "interval"); + ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); + Local result = object->Get(ecmaVm, tmpStr); + ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); + EXPECT_EQ(Local(result)->Value(), 500); +} } // namespace panda::test From fcbd1a76a23ae69b688148f79159b4b06522d543 Mon Sep 17 00:00:00 2001 From: zhangyukun Date: Mon, 6 Jun 2022 11:08:31 +0800 Subject: [PATCH 23/35] Fix rsp frame on arm64 1. get 32bits of argc 2. add ldur&stur to support signed offset Issue:https://gitee.com/openharmony/ark_js_runtime/issues/I5ASTO?from=project-issue Signed-off-by: zhangyukun Change-Id: Id4a6bad2977611939ef5fbece5ae5a862cab6e34 --- .../assembler/aarch64/assembler_aarch64.cpp | 24 ++++++++++++ .../assembler/aarch64/assembler_aarch64.h | 2 + .../aarch64/assembler_aarch64_constants.h | 2 + .../tests/assembler_aarch64_test.cpp | 6 ++- .../trampoline/aarch64/assembler_stubs.cpp | 39 +++++++++++-------- ecmascript/frames.h | 2 +- 6 files changed, 56 insertions(+), 19 deletions(-) diff --git a/ecmascript/compiler/assembler/aarch64/assembler_aarch64.cpp b/ecmascript/compiler/assembler/aarch64/assembler_aarch64.cpp index 521265d020..9dd4d23253 100644 --- a/ecmascript/compiler/assembler/aarch64/assembler_aarch64.cpp +++ b/ecmascript/compiler/assembler/aarch64/assembler_aarch64.cpp @@ -335,6 +335,30 @@ void AssemblerAarch64::Str(const Register &rt, const MemoryOperand &operand) UNREACHABLE(); } +void AssemblerAarch64::Ldur(const Register &rt, const MemoryOperand &operand) +{ + bool regX = !rt.IsW(); + uint32_t op = LDUR_Offset; + ASSERT(operand.IsImmediateOffset()); + uint64_t imm = static_cast(operand.GetImmediate().Value()); + // 30: 30bit indicate the size of LDUR Reg + uint32_t instructionCode = (regX << 30) | op | LoadAndStoreImm(imm, true) + | Rn(operand.GetRegBase().GetId()) | Rt(rt.GetId()); + EmitU32(instructionCode); +} + +void AssemblerAarch64::Stur(const Register &rt, const MemoryOperand &operand) +{ + bool regX = !rt.IsW(); + uint32_t op = STUR_Offset; + ASSERT(operand.IsImmediateOffset()); + uint64_t imm = static_cast(operand.GetImmediate().Value()); + // 30: 30bit indicate the size of LDUR Reg + uint32_t instructionCode = (regX << 30) | op | LoadAndStoreImm(imm, true) + | Rn(operand.GetRegBase().GetId()) | Rt(rt.GetId()); + EmitU32(instructionCode); +} + void AssemblerAarch64::Mov(const Register &rd, const Immediate &imm) { ASSERT_PRINT(!rd.IsSp(), "sp can't load immediate, please use add instruction"); diff --git a/ecmascript/compiler/assembler/aarch64/assembler_aarch64.h b/ecmascript/compiler/assembler/aarch64/assembler_aarch64.h index 8cecb0c707..016f787da0 100644 --- a/ecmascript/compiler/assembler/aarch64/assembler_aarch64.h +++ b/ecmascript/compiler/assembler/aarch64/assembler_aarch64.h @@ -291,6 +291,8 @@ public: void Ldrh(const Register &rt, const MemoryOperand &operand); void Ldrb(const Register &rt, const MemoryOperand &operand); void Str(const Register &rt, const MemoryOperand &operand); + void Ldur(const Register &rt, const MemoryOperand &operand); + void Stur(const Register &rt, const MemoryOperand &operand); void Mov(const Register &rd, const Immediate &imm); void Mov(const Register &rd, const Register &rm); void Movz(const Register &rd, uint64_t imm, int shift); diff --git a/ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h b/ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h index 88941ef154..37ed6565b2 100644 --- a/ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h +++ b/ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h @@ -184,6 +184,8 @@ enum LoadStoreOpCode { LDR_Register = 0xb8600800, LDRB_Register = 0x38600800, LDRH_Register = 0x78600800, + LDUR_Offset = 0xb8400000, + STUR_Offset = 0xb8000000, }; enum AddrMode { diff --git a/ecmascript/compiler/assembler/tests/assembler_aarch64_test.cpp b/ecmascript/compiler/assembler/tests/assembler_aarch64_test.cpp index 3d06d8b127..a6f982a3e4 100644 --- a/ecmascript/compiler/assembler/tests/assembler_aarch64_test.cpp +++ b/ecmascript/compiler/assembler/tests/assembler_aarch64_test.cpp @@ -185,7 +185,9 @@ HWTEST_F_L0(AssemblerAarch64Test, LdrStr) "00000014:38408fe1 \tldrb\tw1, [sp, #8]!\n" "00000018:394023e1 \tldrb\tw1, [sp, #8]\n" "0000001c:78408fe1 \tldrh\tw1, [sp, #8]!\n" - "00000020:794013e1 \tldrh\tw1, [sp, #8]\n"); + "00000020:794013e1 \tldrh\tw1, [sp, #8]\n" + "00000024:f85f83e1 \tldur\tx1, [sp, #-8]\n" + "00000028:f81f83e3 \tstur\tx3, [sp, #-8]\n"); AssemblerAarch64 masm(chunk_); __ Str(Register(X1), MemoryOperand(Register(SP), 8, POSTINDEX)); @@ -197,6 +199,8 @@ HWTEST_F_L0(AssemblerAarch64Test, LdrStr) __ Ldrb(Register(X1).W(), MemoryOperand(Register(SP), 8, OFFSET)); __ Ldrh(Register(X1).W(), MemoryOperand(Register(SP), 8, PREINDEX)); __ Ldrh(Register(X1).W(), MemoryOperand(Register(SP), 8, OFFSET)); + __ Ldur(Register(X1), MemoryOperand(Register(SP), -8, OFFSET)); + __ Stur(Register(X3), MemoryOperand(Register(SP), -8, OFFSET)); std::ostringstream oss; DisassembleChunk("aarch64-unknown-linux-gnu", &masm, oss); ASSERT_EQ(oss.str(), expectResult); diff --git a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp index 4ca0628fb1..f893e9e2d1 100644 --- a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp +++ b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp @@ -785,11 +785,11 @@ void AssemblerStubs::JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode auto jumpSize = kungfu::AssemblerModule::GetJumpSizeFromJSCallMode(mode); [[maybe_unused]] TempRegister1Scope scope1(assembler); Register temp = __ TempRegister1(); - [[maybe_unused]] TempRegister2Scope scope2(assembler); - Register frameStateRegister = __ TempRegister2(); __ Mov(temp, Immediate(static_cast(jumpSize))); - __ Sub(frameStateRegister, Register(FP), Immediate(AsmInterpretedFrame::GetSize(false))); - __ Str(temp, MemoryOperand(frameStateRegister, AsmInterpretedFrame::GetCallSizeOffset(false))); + int64_t offset = static_cast(AsmInterpretedFrame::GetCallSizeOffset(false)) + - static_cast(AsmInterpretedFrame::GetSize(false)); + ASSERT(offset < 0); + __ Stur(temp, MemoryOperand(Register(FP), offset)); } Register declaredNumArgsRegister = __ AvailableRegister2(); @@ -815,7 +815,7 @@ void AssemblerStubs::JSCallCommonEntry(ExtendedAssembler *assembler, JSCallMode // GHC calling convention // Input1: for callarg0/1/2/3 Input2: for callrange // X19 - glue // X19 - glue -// FP - sp // FP - sp +// FP - sp // FP - sp // X20 - callTarget // X20 - callTarget // X21 - method // X21 - method // X22 - callField // X22 - callField @@ -997,7 +997,7 @@ void AssemblerStubs::CallIThisRangeNoExtraEntry(ExtendedAssembler *assembler) __ Bind(&pushCallThis); { Register thisRegister = __ AvailableRegister2(); - __ Ldr(thisRegister, MemoryOperand(argvRegister, -8)); // 8: this is just before the argv list + __ Ldur(thisRegister, MemoryOperand(argvRegister, -8)); // 8: this is just before the argv list PushCallThis(assembler, thisRegister, false); } } @@ -1201,11 +1201,15 @@ void AssemblerStubs::ResumeRspAndDispatch(ExtendedAssembler *assembler) Register opcode(X6, W); Register bcStub(X7); - Register frameStateRegister(X16); - __ Sub(frameStateRegister, sp, Immediate(AsmInterpretedFrame::GetSize(false))); - __ Ldr(Register(SP), MemoryOperand(frameStateRegister, AsmInterpretedFrame::GetFpOffset(false))); // resume rsp - __ Ldr(sp, MemoryOperand(frameStateRegister, AsmInterpretedFrame::GetBaseOffset(false))); // update sp + int64_t fpOffset = static_cast(AsmInterpretedFrame::GetFpOffset(false)) + - static_cast(AsmInterpretedFrame::GetSize(false)); + int64_t spOffset = static_cast(AsmInterpretedFrame::GetBaseOffset(false)) + - static_cast(AsmInterpretedFrame::GetSize(false)); + ASSERT(fpOffset < 0); + ASSERT(spOffset < 0); + __ Ldur(Register(SP), MemoryOperand(sp, fpOffset)); // resume rsp + __ Ldur(sp, MemoryOperand(sp, spOffset)); // update sp __ Add(pc, pc, Operand(jumpSize, LSL, 0)); __ Ldrb(opcode, MemoryOperand(pc, 0)); @@ -1222,10 +1226,10 @@ void AssemblerStubs::ResumeRspAndReturn([[maybe_unused]] ExtendedAssembler *asse [[maybe_unused]] TempRegister1Scope scope1(assembler); Register fpRegister = __ TempRegister1(); - [[maybe_unused]] TempRegister2Scope scope2(assembler); - Register frameStateRegister = __ TempRegister2(); - __ Sub(frameStateRegister, Register(FP), Immediate(AsmInterpretedFrame::GetSize(false))); - __ Ldr(fpRegister, MemoryOperand(frameStateRegister, AsmInterpretedFrame::GetFpOffset(false))); + int64_t offset = static_cast(AsmInterpretedFrame::GetFpOffset(false)) + - static_cast(AsmInterpretedFrame::GetSize(false)); + ASSERT(offset < 0); + __ Ldur(fpRegister, MemoryOperand(Register(FP), offset)); __ Mov(sp, fpRegister); // return @@ -1372,7 +1376,7 @@ void AssemblerStubs::CallIThisRangeEntry(ExtendedAssembler *assembler) } __ Bind(&pushCallThis); Register thisRegister = __ AvailableRegister2(); - __ Ldr(thisRegister, MemoryOperand(argvRegister, -8)); // 8: this is just before the argv list + __ Ldur(thisRegister, MemoryOperand(argvRegister, -8)); // 8: this is just before the argv list PushCallThis(assembler, thisRegister, false); } @@ -1600,6 +1604,7 @@ void AssemblerStubs::ConstructEcmaRuntimeCallInfo(ExtendedAssembler *assembler, Register sp(SP); __ Sub(sp, sp, Immediate(sizeof(EcmaRuntimeCallInfo))); __ Str(thread, MemoryOperand(sp, EcmaRuntimeCallInfo::GetThreadOffset())); + __ And(numArgs, numArgs, LogicalImmediate::Create(0x00000000FFFFFFFF, RegXSize)); __ Str(numArgs, MemoryOperand(sp, EcmaRuntimeCallInfo::GetNumArgsOffset())); __ Str(stackArgs, MemoryOperand(sp, EcmaRuntimeCallInfo::GetStackArgsOffset())); } @@ -1705,8 +1710,8 @@ void AssemblerStubs::CallNativeEntry(ExtendedAssembler *assembler) __ Ldr(nativeCode, MemoryOperand(method, JSMethod::GetBytecodeArrayOffset(false))); CallNativeInternal(assembler, glue, argc, argv, nativeCode); - // 40: skip function - __ Add(sp, sp, Immediate(40)); + // 32: skip function + __ Add(sp, sp, Immediate(32)); __ Ret(); } diff --git a/ecmascript/frames.h b/ecmascript/frames.h index e51dba1ad3..8d85482614 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -697,7 +697,7 @@ struct BuiltinFrame : public base::AlignedStruct Date: Thu, 2 Jun 2022 16:45:54 +0800 Subject: [PATCH 24/35] fix globalEnvConstants initialize bug add a member to identify whether the globalEnvConstants is initialized or not. issue:https://gitee.com/openharmony/ark_js_runtime/issues/I5AY58 Signed-off-by: xiongluo --- ecmascript/ecma_vm.cpp | 4 ++-- ecmascript/ecma_vm.h | 6 ++++++ ecmascript/object_factory.cpp | 4 +--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 1ef1a2d09c..946bfcd73a 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -146,8 +146,8 @@ bool EcmaVM::Initialize() JSHandle globalEnvClass = factory_->NewEcmaDynClass(*dynClassClassHandle, GlobalEnv::SIZE, JSType::GLOBAL_ENV); - globalConst->InitRootsClass(thread_, *dynClassClassHandle); - globalConst->InitGlobalConstant(thread_); + globalConst->Init(thread_, *dynClassClassHandle); + globalConstInitialized_ = true; JSHandle globalEnv = factory_->NewGlobalEnv(*globalEnvClass); globalEnv->Init(thread_); globalEnv_ = globalEnv.GetTaggedValue(); diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index 73842003f2..7920fdcc30 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -94,6 +94,11 @@ public: return vmInitialized_; } + bool IsGlobalConstInitialized() const + { + return globalConstInitialized_; + } + ObjectFactory *GetFactory() const { return factory_; @@ -335,6 +340,7 @@ private: JSRuntimeOptions options_; bool icEnabled_ {true}; bool vmInitialized_ {false}; + bool globalConstInitialized_ {false}; GCStats *gcStats_ {nullptr}; bool snapshotSerializeEnable_ {false}; bool snapshotDeserializeEnable_ {false}; diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index 48fb40fec5..f6d646dfa0 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -1181,10 +1181,8 @@ FreeObject *ObjectFactory::FillFreeObject(uintptr_t address, size_t size, Remove object->SetNext(INVALID_OBJECT); } else if (size >= FreeObject::SIZE) { object = reinterpret_cast(address); - bool firstHClassLoaded = false; - if (!firstHClassLoaded && !globalConst->GetFreeObjectWithTwoFieldClass().GetRawData()) { + if (!vm_->IsGlobalConstInitialized()) { object->SetClassWithoutBarrier(nullptr); - firstHClassLoaded = true; } else { object->SetClassWithoutBarrier( JSHClass::Cast(globalConst->GetFreeObjectWithTwoFieldClass().GetTaggedObject())); From 3ad1c55280821cc89139682577d44eba8dffb485 Mon Sep 17 00:00:00 2001 From: hjzhangcm Date: Tue, 7 Jun 2022 09:57:59 +0800 Subject: [PATCH 25/35] describe:fix 262 script issue:https://gitee.com/openharmony/ark_js_runtime/issues/I5AZHA Signed-off-by: hjzhangcm --- test/run_test262.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/run_test262.sh b/test/run_test262.sh index a20e831eec..43539778dd 100644 --- a/test/run_test262.sh +++ b/test/run_test262.sh @@ -34,7 +34,8 @@ pushd ark/ts2abc python3 test262/run_test262.py --es2015 all --threads=16 --libs-dir ../../out/hispark_taurus/clang_x64/ark/ark:../../out/hispark_taurus/clang_x64/ark/ark_js_runtime:../../out/hispark_taurus/clang_x64/thirdparty/icu:../../prebuilts/clang/ohos/linux-x86_64/llvm/lib --ark-tool=../../out/hispark_taurus/clang_x64/ark/ark_js_runtime/ark_js_vm --ark-frontend-tool=../../out/hispark_taurus/clang_x64/ark/ark/build/src/index.js popd fi - + popd + if [ $? -ne 0 ];then echo 'execute run_test262.py failed!' exit 1; From e09d591eb5bda29808cc9c7fc089bfa4d2bf1f12 Mon Sep 17 00:00:00 2001 From: Riachel Date: Mon, 6 Jun 2022 14:47:02 +0800 Subject: [PATCH 26/35] Descriptor: support heapprofiler domain details: 1. add statsUpdate event 2. add lastObjectId event issue: https://gitee.com/openharmony/ark_js_runtime/issues/I5AUJA Signed-off-by: Riachel --- ecmascript/dfx/hprof/heap_profiler.cpp | 5 +- ecmascript/dfx/hprof/heap_profiler.h | 2 +- .../dfx/hprof/heap_profiler_interface.h | 2 +- ecmascript/dfx/hprof/heap_snapshot.cpp | 53 ++++++++++- ecmascript/dfx/hprof/heap_snapshot.h | 28 +++++- ecmascript/dfx/hprof/heap_tracker.cpp | 7 +- ecmascript/dfx/hprof/heap_tracker.h | 14 ++- ecmascript/mem/heap-inl.h | 16 ++-- ecmascript/mem/heap.h | 4 +- ecmascript/mem/parallel_marker-inl.h | 3 +- ecmascript/napi/dfx_jsnapi.cpp | 6 +- ecmascript/napi/include/dfx_jsnapi.h | 3 +- .../tooling/agent/heapprofiler_impl.cpp | 94 ++++++------------- ecmascript/tooling/agent/heapprofiler_impl.h | 79 ++++++++++++++-- ecmascript/tooling/base/pt_events.cpp | 4 +- ecmascript/tooling/base/pt_events.h | 18 ++-- ecmascript/tooling/interface/file_stream.h | 12 +++ ecmascript/tooling/interface/stream.h | 12 +++ .../tooling/test/debugger_events_test.cpp | 2 +- 19 files changed, 253 insertions(+), 111 deletions(-) diff --git a/ecmascript/dfx/hprof/heap_profiler.cpp b/ecmascript/dfx/hprof/heap_profiler.cpp index 7e3757ccd0..00792920f7 100644 --- a/ecmascript/dfx/hprof/heap_profiler.cpp +++ b/ecmascript/dfx/hprof/heap_profiler.cpp @@ -54,13 +54,14 @@ bool HeapProfiler::DumpHeapSnapshot(DumpFormat dumpFormat, Stream *stream, Progr return jsonSerializer_->Serialize(snapshot, stream); } -bool HeapProfiler::StartHeapTracking(double timeInterval, bool isVmMode) +bool HeapProfiler::StartHeapTracking(double timeInterval, bool isVmMode, Stream *stream) { HeapSnapshot *snapshot = MakeHeapSnapshot(SampleType::REAL_TIME, isVmMode); if (snapshot == nullptr) { return false; } - heapTracker_ = std::make_unique(snapshot, timeInterval); + + heapTracker_ = std::make_unique(snapshot, timeInterval, stream); const_cast(vm_)->StartHeapTracking(heapTracker_.get()); heapTracker_->StartTracing(); return true; diff --git a/ecmascript/dfx/hprof/heap_profiler.h b/ecmascript/dfx/hprof/heap_profiler.h index 4d9477114b..bb017708dc 100644 --- a/ecmascript/dfx/hprof/heap_profiler.h +++ b/ecmascript/dfx/hprof/heap_profiler.h @@ -53,7 +53,7 @@ public: void AddSnapshot(HeapSnapshot *snapshot); - bool StartHeapTracking(double timeInterval, bool isVmMode = true) override; + bool StartHeapTracking(double timeInterval, bool isVmMode = true, Stream *stream = nullptr) override; bool StopHeapTracking(Stream *stream, Progress *progress = nullptr) override; private: diff --git a/ecmascript/dfx/hprof/heap_profiler_interface.h b/ecmascript/dfx/hprof/heap_profiler_interface.h index 241571f5d6..1e38c6832b 100644 --- a/ecmascript/dfx/hprof/heap_profiler_interface.h +++ b/ecmascript/dfx/hprof/heap_profiler_interface.h @@ -35,7 +35,7 @@ public: virtual bool DumpHeapSnapshot(DumpFormat dumpFormat, Stream *stream, Progress *progress = nullptr, bool isVmMode = true, bool isPrivate = false) = 0; - virtual bool StartHeapTracking(double timeInterval, bool isVmMode = true) = 0; + virtual bool StartHeapTracking(double timeInterval, bool isVmMode = true, Stream *stream = nullptr) = 0; virtual bool StopHeapTracking(Stream *stream, Progress *progress = nullptr) = 0; NO_MOVE_SEMANTIC(HeapProfilerInterface); diff --git a/ecmascript/dfx/hprof/heap_snapshot.cpp b/ecmascript/dfx/hprof/heap_snapshot.cpp index d74c7b8140..2c1d4874ae 100644 --- a/ecmascript/dfx/hprof/heap_snapshot.cpp +++ b/ecmascript/dfx/hprof/heap_snapshot.cpp @@ -119,15 +119,62 @@ bool HeapSnapshot::FinishSnapshot() void HeapSnapshot::RecordSampleTime() { - timeStamps_.emplace_back(sequenceId_); + int len = timeStamps_.size(); + if (len > 0) { + if (sequenceId_ != timeStamps_[len - 1].GetLastSequenceId()) { + timeStamps_.emplace_back(sequenceId_); + } + } else { + timeStamps_.emplace_back(sequenceId_); + } } -void HeapSnapshot::AddNode(uintptr_t address) +void HeapSnapshot::PushHeapStat(Stream* stream) +{ + CVector statsBuffer; + if (stream == nullptr) { + LOG(ERROR, DEBUGGER) << "HeapSnapshot::PushHeapStat::stream is nullptr"; + return; + } + int preChunkSize = stream->GetSize(); + uint32_t sequenceId = 0; + auto iter = nodes_.begin(); + for (size_t timeIndex = 0; timeIndex < timeStamps_.size(); ++timeIndex) { + TimeStamp& timeStamp = timeStamps_[timeIndex]; + sequenceId = timeStamp.GetLastSequenceId(); + uint32_t nodesSize = 0; + uint32_t nodesCount = 0; + + while (iter != nodes_.end() && (*iter)->GetId() <= sequenceId) { + nodesCount++; + nodesSize += (*iter)->GetSelfSize(); + iter++; + } + if (((timeStamp.GetCount() != nodesCount) || (timeStamp.GetSize() != nodesSize)) + && ((nodesCount != 0) && (nodesSize != 0))) { + timeStamp.SetCount(nodesCount); + timeStamp.SetSize(nodesSize); + statsBuffer.emplace_back(static_cast(timeIndex), nodesCount, nodesSize); + if (static_cast(statsBuffer.size()) >= preChunkSize) { + stream->UpdateHeapStats(&statsBuffer.front(), static_cast(statsBuffer.size())); + statsBuffer.clear(); + } + } + } + + if (!statsBuffer.empty()) { + stream->UpdateHeapStats(&statsBuffer.front(), static_cast(statsBuffer.size())); + statsBuffer.clear(); + } + stream->UpdateLastSeenObjectId(sequenceId); +} + +void HeapSnapshot::AddNode(TaggedObject* address) { GenerateNode(JSTaggedValue(address)); } -void HeapSnapshot::MoveNode(uintptr_t address, uintptr_t forward_address) +void HeapSnapshot::MoveNode(uintptr_t address, TaggedObject* forward_address) { int sequenceId = -1; Node *node = entryMap_.FindAndEraseNode(address); diff --git a/ecmascript/dfx/hprof/heap_snapshot.h b/ecmascript/dfx/hprof/heap_snapshot.h index e9853c5cdb..5f95f766be 100644 --- a/ecmascript/dfx/hprof/heap_snapshot.h +++ b/ecmascript/dfx/hprof/heap_snapshot.h @@ -29,6 +29,7 @@ #include "ecmascript/js_tagged_value.h" #include "ecmascript/mem/c_containers.h" #include "os/mem.h" +#include "ecmascript/tooling/interface/stream.h" namespace panda::ecmascript { // Define the Object Graphic @@ -196,6 +197,26 @@ public: return timeStampUs_; } + uint32_t GetSize() const + { + return size_; + } + + void SetSize(uint32_t size) + { + size_ = size; + } + + uint32_t GetCount() const + { + return count_; + } + + void SetCount(uint32_t count) + { + count_ = count; + } + private: static int64_t Now() { @@ -207,6 +228,8 @@ private: int lastSequenceId_ {0}; int64_t timeStampUs_ {0}; + uint32_t size_ {0}; + uint32_t count_ {0}; }; class HeapEntryMap { @@ -248,10 +271,11 @@ public: void PrepareSnapshot(); void UpdateNode(); - void AddNode(uintptr_t address); - void MoveNode(uintptr_t address, uintptr_t forward_address); + void AddNode(TaggedObject* address); + void MoveNode(uintptr_t address, TaggedObject* forward_address); void RecordSampleTime(); bool FinishSnapshot(); + void PushHeapStat(Stream* stream); const CVector &GetTimeStamps() const { diff --git a/ecmascript/dfx/hprof/heap_tracker.cpp b/ecmascript/dfx/hprof/heap_tracker.cpp index c8f1b926fe..0d3e4d98eb 100644 --- a/ecmascript/dfx/hprof/heap_tracker.cpp +++ b/ecmascript/dfx/hprof/heap_tracker.cpp @@ -24,18 +24,21 @@ void HeapTrackerSample::Run() { while (!isInterrupt_) { snapshot_->RecordSampleTime(); + if (stream_ != nullptr) { + snapshot_->PushHeapStat(stream_); + } usleep(timeInterval_ * MILLI_TO_MICRO); } } -void HeapTracker::AllocationEvent(uintptr_t address) +void HeapTracker::AllocationEvent(TaggedObject* address) { if (snapshot_ != nullptr) { snapshot_->AddNode(address); } } -void HeapTracker::MoveEvent(uintptr_t address, uintptr_t forward_address) +void HeapTracker::MoveEvent(uintptr_t address, TaggedObject* forward_address) { if (snapshot_ != nullptr) { snapshot_->MoveNode(address, forward_address); diff --git a/ecmascript/dfx/hprof/heap_tracker.h b/ecmascript/dfx/hprof/heap_tracker.h index 161471d7dc..c739fe5024 100644 --- a/ecmascript/dfx/hprof/heap_tracker.h +++ b/ecmascript/dfx/hprof/heap_tracker.h @@ -21,14 +21,16 @@ #include #include "libpandabase/macros.h" +#include "ecmascript/tooling/interface/stream.h" +#include "ecmascript/mem/tagged_object.h" namespace panda::ecmascript { class HeapSnapshot; class HeapTrackerSample { public: - explicit HeapTrackerSample(HeapSnapshot *snapshot, double timeInterval) - : timeInterval_(timeInterval), snapshot_(snapshot) + explicit HeapTrackerSample(HeapSnapshot *snapshot, double timeInterval, Stream *stream) + : timeInterval_(timeInterval), snapshot_(snapshot), stream_(stream) { } @@ -61,11 +63,13 @@ private: std::atomic_bool isInterrupt_ = true; double timeInterval_ = 0; HeapSnapshot *snapshot_; + Stream *stream_ {nullptr}; }; class HeapTracker { public: - HeapTracker(HeapSnapshot *snapshot, double timeInterval) : snapshot_(snapshot), sample_(snapshot, timeInterval) {} + HeapTracker(HeapSnapshot *snapshot, double timeInterval, Stream *stream) + : snapshot_(snapshot), sample_(snapshot, timeInterval, stream) {} ~HeapTracker() = default; void StartTracing() @@ -78,8 +82,8 @@ public: sample_.Stop(); } - void AllocationEvent(uintptr_t address); - void MoveEvent(uintptr_t address, uintptr_t forward_address); + void AllocationEvent(TaggedObject* address); + void MoveEvent(uintptr_t address, TaggedObject* forward_address); NO_COPY_SEMANTIC(HeapTracker); NO_MOVE_SEMANTIC(HeapTracker); diff --git a/ecmascript/mem/heap-inl.h b/ecmascript/mem/heap-inl.h index 306dcf250b..5195ce9694 100644 --- a/ecmascript/mem/heap-inl.h +++ b/ecmascript/mem/heap-inl.h @@ -135,7 +135,7 @@ TaggedObject *Heap::AllocateYoungOrHugeObject(JSHClass *hclass, size_t size) { auto object = AllocateYoungOrHugeObject(size); object->SetClass(hclass); - OnAllocateEvent(reinterpret_cast(object)); + OnAllocateEvent(reinterpret_cast(object)); return object; } @@ -185,7 +185,7 @@ TaggedObject *Heap::AllocateOldOrHugeObject(JSHClass *hclass, size_t size) UNREACHABLE(); } object->SetClass(hclass); - OnAllocateEvent(reinterpret_cast(object)); + OnAllocateEvent(reinterpret_cast(object)); return object; } @@ -207,7 +207,7 @@ TaggedObject *Heap::AllocateNonMovableOrHugeObject(JSHClass *hclass, size_t size UNREACHABLE(); } object->SetClass(hclass); - OnAllocateEvent(reinterpret_cast(object)); + OnAllocateEvent(reinterpret_cast(object)); return object; } @@ -219,7 +219,7 @@ TaggedObject *Heap::AllocateDynClassClass(JSHClass *hclass, size_t size) LOG_ECMA_MEM(FATAL) << "Heap::AllocateDynClassClass can not allocate any space"; } *reinterpret_cast(ToUintPtr(object)) = reinterpret_cast(hclass); - OnAllocateEvent(reinterpret_cast(object)); + OnAllocateEvent(reinterpret_cast(object)); return object; } @@ -245,7 +245,7 @@ TaggedObject *Heap::AllocateHugeObject(JSHClass *hclass, size_t size) CheckAndTriggerOldGC(); auto object = AllocateHugeObject(size); object->SetClass(hclass); - OnAllocateEvent(reinterpret_cast(object)); + OnAllocateEvent(reinterpret_cast(object)); return object; } @@ -258,7 +258,7 @@ TaggedObject *Heap::AllocateMachineCodeObject(JSHClass *hclass, size_t size) return nullptr; } object->SetClass(hclass); - OnAllocateEvent(reinterpret_cast(object)); + OnAllocateEvent(reinterpret_cast(object)); return object; } @@ -273,7 +273,7 @@ uintptr_t Heap::AllocateSnapshotSpace(size_t size) return object; } -void Heap::OnAllocateEvent([[maybe_unused]] uintptr_t address) +void Heap::OnAllocateEvent([[maybe_unused]] TaggedObject* address) { #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT) if (tracker_ != nullptr) { @@ -282,7 +282,7 @@ void Heap::OnAllocateEvent([[maybe_unused]] uintptr_t address) #endif } -void Heap::OnMoveEvent([[maybe_unused]] uintptr_t address, [[maybe_unused]] uintptr_t forwardAddress) +void Heap::OnMoveEvent([[maybe_unused]] uintptr_t address, [[maybe_unused]] TaggedObject* forwardAddress) { #if defined(ECMASCRIPT_SUPPORT_SNAPSHOT) if (tracker_ != nullptr) { diff --git a/ecmascript/mem/heap.h b/ecmascript/mem/heap.h index eb8403c352..8b7a36569f 100644 --- a/ecmascript/mem/heap.h +++ b/ecmascript/mem/heap.h @@ -354,8 +354,8 @@ public: tracker_ = nullptr; } - inline void OnAllocateEvent(uintptr_t address); - inline void OnMoveEvent(uintptr_t address, uintptr_t forwardAddress); + inline void OnAllocateEvent(TaggedObject* address); + inline void OnMoveEvent(uintptr_t address, TaggedObject* forwardAddress); void AddToKeptObjects(JSHandle value) const; void ClearKeptObjects() const; /* diff --git a/ecmascript/mem/parallel_marker-inl.h b/ecmascript/mem/parallel_marker-inl.h index 5bd0fc5782..371ec15b39 100644 --- a/ecmascript/mem/parallel_marker-inl.h +++ b/ecmascript/mem/parallel_marker-inl.h @@ -166,8 +166,9 @@ inline void MovableMarker::UpdateForwardAddressIfSuccess(uint32_t threadId, Tagg if (isPromoted) { workManager_->IncreasePromotedSize(threadId, size); } + *reinterpret_cast(toAddress) = markWord.GetValue(); - heap_->OnMoveEvent(reinterpret_cast(object), toAddress); + heap_->OnMoveEvent(reinterpret_cast(object), reinterpret_cast(toAddress)); if (klass->HasReferenceField()) { workManager_->Push(threadId, reinterpret_cast(toAddress)); } diff --git a/ecmascript/napi/dfx_jsnapi.cpp b/ecmascript/napi/dfx_jsnapi.cpp index f1691c9144..d1c583487e 100644 --- a/ecmascript/napi/dfx_jsnapi.cpp +++ b/ecmascript/napi/dfx_jsnapi.cpp @@ -22,6 +22,7 @@ #include "ecmascript/mem/heap-inl.h" #include "ecmascript/mem/gc_stats.h" #include "ecmascript/tooling/interface/file_stream.h" +#include "ecmascript/tooling/interface/stream.h" #if defined(ENABLE_DUMP_IN_FAULTLOG) #include "include/faultloggerd_client.h" @@ -39,6 +40,7 @@ template using JSHandle = ecmascript::JSHandle; using ecmascript::FileStream; using ecmascript::FileDescriptorStream; +using ecmascript::Stream; void DFXJSNApi::DumpHeapSnapshot(const EcmaVM *vm, int dumpFormat, const std::string &path, bool isVmMode, bool isPrivate) @@ -80,10 +82,10 @@ bool DFXJSNApi::BuildNativeAndJsBackStackTrace(const EcmaVM *vm, std::string &st return true; } -bool DFXJSNApi::StartHeapTracking(const EcmaVM *vm, double timeInterval, bool isVmMode) +bool DFXJSNApi::StartHeapTracking(const EcmaVM *vm, double timeInterval, bool isVmMode, Stream *stream) { ecmascript::HeapProfilerInterface *heapProfile = ecmascript::HeapProfilerInterface::GetInstance(vm); - return heapProfile->StartHeapTracking(timeInterval, isVmMode); + return heapProfile->StartHeapTracking(timeInterval, isVmMode, stream); } bool DFXJSNApi::StopHeapTracking(const EcmaVM *vm, const std::string &filePath) diff --git a/ecmascript/napi/include/dfx_jsnapi.h b/ecmascript/napi/include/dfx_jsnapi.h index cf8a1ae768..e2ef5a22ca 100644 --- a/ecmascript/napi/include/dfx_jsnapi.h +++ b/ecmascript/napi/include/dfx_jsnapi.h @@ -50,7 +50,8 @@ public: static void DumpHeapSnapshot(const EcmaVM *vm, int dumpFormat, bool isVmMode = true, bool isPrivate = false); static bool BuildNativeAndJsBackStackTrace(const EcmaVM *vm, std::string &stackTraceStr); - static bool StartHeapTracking(const EcmaVM *vm, double timeInterval, bool isVmMode = true); + static bool StartHeapTracking(const EcmaVM *vm, double timeInterval, bool isVmMode = true, + Stream *stream = nullptr); static bool StopHeapTracking(const EcmaVM *vm, const std::string &filePath); static bool StopHeapTracking(const EcmaVM *vm, Stream *stream, Progress *progress = nullptr); static void PrintStatisticResult(const EcmaVM *vm); diff --git a/ecmascript/tooling/agent/heapprofiler_impl.cpp b/ecmascript/tooling/agent/heapprofiler_impl.cpp index a666519813..bcce9c3ede 100644 --- a/ecmascript/tooling/agent/heapprofiler_impl.cpp +++ b/ecmascript/tooling/agent/heapprofiler_impl.cpp @@ -15,7 +15,6 @@ #include "ecmascript/tooling/agent/heapprofiler_impl.h" - namespace panda::ecmascript::tooling { void HeapProfilerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) { @@ -170,54 +169,6 @@ void HeapProfilerImpl::DispatcherImpl::TakeHeapSnapshot(const DispatchRequest &r SendResponse(request, response); } -class HeapProfilerStream final : public Stream { -public: - explicit HeapProfilerStream(HeapProfilerImpl::Frontend *frontend) - : frontend_(frontend) {} - - void EndOfStream() override {} - int GetSize() override - { - static const int heapProfilerChunkSise = 102400; - return heapProfilerChunkSise; - } - bool WriteChunk(char *data, int size) override - { - if (!Good()) { - return false; - } - frontend_->AddHeapSnapshotChunk(data, size); - return true; - } - bool Good() override - { - return frontend_ != nullptr; - } - -private: - NO_COPY_SEMANTIC(HeapProfilerStream); - NO_MOVE_SEMANTIC(HeapProfilerStream); - - HeapProfilerImpl::Frontend *frontend_ {nullptr}; -}; - -class HeapProfilerProgress final : public Progress { -public: - explicit HeapProfilerProgress(HeapProfilerImpl::Frontend *frontend) - : frontend_(frontend) {} - - void ReportProgress(int32_t done, int32_t total) override - { - frontend_->ReportHeapSnapshotProgress(done, total); - } - -private: - NO_COPY_SEMANTIC(HeapProfilerProgress); - NO_MOVE_SEMANTIC(HeapProfilerProgress); - - HeapProfilerImpl::Frontend *frontend_ {nullptr}; -}; - bool HeapProfilerImpl::Frontend::AllowNotify() const { return channel_ != nullptr; @@ -252,24 +203,37 @@ void HeapProfilerImpl::Frontend::ReportHeapSnapshotProgress(int32_t done, int32_ channel_->SendNotification(reportHeapSnapshotProgress); } -void HeapProfilerImpl::Frontend::HeapStatsUpdate() +void HeapProfilerImpl::Frontend::HeapStatsUpdate(HeapStat* updateData, int count) { if (!AllowNotify()) { return; } - + auto statsDiff = CVector(); + for (int i = 0; i < count; ++i) { + statsDiff.emplace_back(updateData[i].index_); + statsDiff.emplace_back(updateData[i].count_); + statsDiff.emplace_back(updateData[i].size_); + } tooling::HeapStatsUpdate heapStatsUpdate; + heapStatsUpdate.SetStatsUpdate(statsDiff); channel_->SendNotification(heapStatsUpdate); } -void HeapProfilerImpl::Frontend::LastSeenObjectId() +void HeapProfilerImpl::Frontend::LastSeenObjectId(uint32_t lastSeenObjectId) { if (!AllowNotify()) { return; } - tooling::LastSeenObjectId lastSeenObjectId; - channel_->SendNotification(lastSeenObjectId); + tooling::LastSeenObjectId lastSeenObjectIdEvent; + lastSeenObjectIdEvent.SetLastSeenObjectId(lastSeenObjectId); + size_t timestamp = 0; + struct timeval tv = {0, 0}; + gettimeofday(&tv, nullptr); + const int THOUSAND = 1000; + timestamp = tv.tv_usec + tv.tv_sec * THOUSAND * THOUSAND; + lastSeenObjectIdEvent.SetTimestamp(timestamp); + channel_->SendNotification(lastSeenObjectIdEvent); } void HeapProfilerImpl::Frontend::ResetProfiles() @@ -333,10 +297,16 @@ DispatchResponse HeapProfilerImpl::StartSampling([[maybe_unused]]std::unique_ptr return DispatchResponse::Ok(); } -DispatchResponse HeapProfilerImpl::StartTrackingHeapObjects( - [[maybe_unused]] std::unique_ptr params) +DispatchResponse HeapProfilerImpl::StartTrackingHeapObjects(std::unique_ptr params) { - bool result = panda::DFXJSNApi::StartHeapTracking(vm_, INTERVAL, true); + bool result = false; + bool trackAllocations = params->GetTrackAllocations(); + if (trackAllocations) { + result = panda::DFXJSNApi::StartHeapTracking(vm_, INTERVAL, true, &stream_); + } else { + result = panda::DFXJSNApi::StartHeapTracking(vm_, INTERVAL, true, nullptr); + } + if (result) { return DispatchResponse::Ok(); } else { @@ -352,13 +322,12 @@ DispatchResponse HeapProfilerImpl::StopSampling([[maybe_unused]]std::unique_ptr< DispatchResponse HeapProfilerImpl::StopTrackingHeapObjects(std::unique_ptr params) { - HeapProfilerStream stream(&frontend_); bool result = false; if (params->GetReportProgress()) { HeapProfilerProgress progress(&frontend_); - result = panda::DFXJSNApi::StopHeapTracking(vm_, &stream, &progress); + result = panda::DFXJSNApi::StopHeapTracking(vm_, &stream_, &progress); } else { - result = panda::DFXJSNApi::StopHeapTracking(vm_, &stream, nullptr); + result = panda::DFXJSNApi::StopHeapTracking(vm_, &stream_, nullptr); } if (result) { return DispatchResponse::Ok(); @@ -369,12 +338,11 @@ DispatchResponse HeapProfilerImpl::StopTrackingHeapObjects(std::unique_ptr params) { - HeapProfilerStream stream(&frontend_); if (params->GetReportProgress()) { HeapProfilerProgress progress(&frontend_); - panda::DFXJSNApi::DumpHeapSnapshot(vm_, 0, &stream, &progress, true); + panda::DFXJSNApi::DumpHeapSnapshot(vm_, 0, &stream_, &progress, true); } else { - panda::DFXJSNApi::DumpHeapSnapshot(vm_, 0, &stream, nullptr, true); + panda::DFXJSNApi::DumpHeapSnapshot(vm_, 0, &stream_, nullptr, true); } return DispatchResponse::Ok(); } diff --git a/ecmascript/tooling/agent/heapprofiler_impl.h b/ecmascript/tooling/agent/heapprofiler_impl.h index 25cbb41b9f..2c9d28ce32 100644 --- a/ecmascript/tooling/agent/heapprofiler_impl.h +++ b/ecmascript/tooling/agent/heapprofiler_impl.h @@ -16,6 +16,7 @@ #ifndef ECMASCRIPT_TOOLING_AGENT_HEAPPROFILER_IMPL_H #define ECMASCRIPT_TOOLING_AGENT_HEAPPROFILER_IMPL_H +#include #include "libpandabase/macros.h" #include "ecmascript/tooling/base/pt_params.h" #include "ecmascript/tooling/base/pt_events.h" @@ -33,7 +34,8 @@ static const double INTERVAL = 0.05; namespace panda::ecmascript::tooling { class HeapProfilerImpl final { public: - explicit HeapProfilerImpl(const EcmaVM *vm, ProtocolChannel *channel) : vm_(vm), frontend_(channel) {} + explicit HeapProfilerImpl(const EcmaVM *vm, ProtocolChannel *channel) + : vm_(vm), frontend_(channel), stream_(&frontend_) {} ~HeapProfilerImpl() = default; DispatchResponse AddInspectedHeapObject(std::unique_ptr params); @@ -79,14 +81,18 @@ public: std::unique_ptr heapprofiler_ {}; }; +private: + NO_COPY_SEMANTIC(HeapProfilerImpl); + NO_MOVE_SEMANTIC(HeapProfilerImpl); + class Frontend { public: explicit Frontend(ProtocolChannel *channel) : channel_(channel) {} void AddHeapSnapshotChunk(char *data, int size); void ReportHeapSnapshotProgress(int32_t done, int32_t total); - void HeapStatsUpdate(); - void LastSeenObjectId(); + void HeapStatsUpdate(HeapStat* updateData, int count); + void LastSeenObjectId(uint32_t lastSeenObjectId); void ResetProfiles(); private: @@ -95,12 +101,73 @@ public: ProtocolChannel *channel_ {nullptr}; }; -private: - NO_COPY_SEMANTIC(HeapProfilerImpl); - NO_MOVE_SEMANTIC(HeapProfilerImpl); + class HeapProfilerStream final : public Stream { + public: + explicit HeapProfilerStream(Frontend *frontend) + : frontend_(frontend) {} + + void EndOfStream() override {} + int GetSize() override + { + static const int heapProfilerChunkSise = 102400; + return heapProfilerChunkSise; + } + bool WriteChunk(char *data, int size) override + { + if (!Good()) { + return false; + } + frontend_->AddHeapSnapshotChunk(data, size); + return true; + } + bool Good() override + { + return frontend_ != nullptr; + } + + void UpdateHeapStats(HeapStat* updateData, int count) override + { + if (!Good()) { + return; + } + frontend_->HeapStatsUpdate(updateData, count); + } + + void UpdateLastSeenObjectId(uint32_t lastSeenObjectId) override + { + if (!Good()) { + return; + } + frontend_->LastSeenObjectId(lastSeenObjectId); + } + + private: + NO_COPY_SEMANTIC(HeapProfilerStream); + NO_MOVE_SEMANTIC(HeapProfilerStream); + + Frontend *frontend_ {nullptr}; + }; + + class HeapProfilerProgress final : public Progress { + public: + explicit HeapProfilerProgress(Frontend *frontend) + : frontend_(frontend) {} + + void ReportProgress(int32_t done, int32_t total) override + { + frontend_->ReportHeapSnapshotProgress(done, total); + } + + private: + NO_COPY_SEMANTIC(HeapProfilerProgress); + NO_MOVE_SEMANTIC(HeapProfilerProgress); + + Frontend *frontend_ {nullptr}; + }; const EcmaVM *vm_ {nullptr}; Frontend frontend_; + HeapProfilerStream stream_; }; } // namespace panda::ecmascript::tooling #endif \ No newline at end of file diff --git a/ecmascript/tooling/base/pt_events.cpp b/ecmascript/tooling/base/pt_events.cpp index eba703cf3a..0f60511c46 100644 --- a/ecmascript/tooling/base/pt_events.cpp +++ b/ecmascript/tooling/base/pt_events.cpp @@ -361,10 +361,10 @@ Local LastSeenObjectId::ToObject(const EcmaVM *ecmaVm) const { Local params = NewObject(ecmaVm); - params->Set(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "timestamp")), - IntegerRef::New(ecmaVm, timestamp_)); params->Set(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "lastSeenObjectId")), IntegerRef::New(ecmaVm, lastSeenObjectId_)); + params->Set(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "timestamp")), + NumberRef::New(ecmaVm, timestamp_)); Local object = NewObject(ecmaVm); object->Set(ecmaVm, diff --git a/ecmascript/tooling/base/pt_events.h b/ecmascript/tooling/base/pt_events.h index 5bce1087ac..398722b8e8 100644 --- a/ecmascript/tooling/base/pt_events.h +++ b/ecmascript/tooling/base/pt_events.h @@ -929,7 +929,7 @@ private: NO_COPY_SEMANTIC(PreciseCoverageDeltaUpdate); NO_MOVE_SEMANTIC(PreciseCoverageDeltaUpdate); - size_t timestamp_ {0}; + int64_t timestamp_ {0}; CString occasion_ {}; CVector> result_ {}; }; @@ -945,12 +945,12 @@ public: return "HeapProfiler.heapStatsUpdate"; } - const CVector *GetStatsUpdate() const + const CVector *GetStatsUpdate() const { return &statsUpdate_; } - HeapStatsUpdate &SetStatsUpdate(CVector statsUpdate) + HeapStatsUpdate &SetStatsUpdate(CVector statsUpdate) { statsUpdate_ = std::move(statsUpdate); return *this; @@ -960,7 +960,7 @@ private: NO_COPY_SEMANTIC(HeapStatsUpdate); NO_MOVE_SEMANTIC(HeapStatsUpdate); - CVector statsUpdate_ {}; + CVector statsUpdate_ {}; }; class LastSeenObjectId final : public PtBaseEvents { @@ -979,18 +979,18 @@ public: return lastSeenObjectId_; } - LastSeenObjectId &SetLastSeenObjectId(int32_t lastSeenObjectId) + LastSeenObjectId &SetLastSeenObjectId(uint32_t lastSeenObjectId) { lastSeenObjectId_ = lastSeenObjectId; return *this; } - size_t GetTimestamp() const + int64_t GetTimestamp() const { return timestamp_; } - LastSeenObjectId &SetTimestamp(size_t timestamp) + LastSeenObjectId &SetTimestamp(int64_t timestamp) { timestamp_ = timestamp; return *this; @@ -1000,8 +1000,8 @@ private: NO_COPY_SEMANTIC(LastSeenObjectId); NO_MOVE_SEMANTIC(LastSeenObjectId); - int32_t lastSeenObjectId_ {}; - size_t timestamp_ {}; + uint32_t lastSeenObjectId_ {}; + int64_t timestamp_ {}; }; class ReportHeapSnapshotProgress final : public PtBaseEvents { diff --git a/ecmascript/tooling/interface/file_stream.h b/ecmascript/tooling/interface/file_stream.h index 6a523be386..0f57f8f07d 100644 --- a/ecmascript/tooling/interface/file_stream.h +++ b/ecmascript/tooling/interface/file_stream.h @@ -38,6 +38,12 @@ public: // Writes the chunk of data into the stream bool WriteChunk(char* data, int size) override; bool Good() override; + void UpdateHeapStats([[maybe_unused]]HeapStat* data, [[maybe_unused]]int count) override + { + } + void UpdateLastSeenObjectId([[maybe_unused]]uint32_t lastSeenObjectId) override + { + } private: void Initialize(const std::string &fileName); @@ -63,6 +69,12 @@ public: // Writes the chunk of data into the stream bool WriteChunk(char *data, int size) override; bool Good() override; + void UpdateHeapStats([[maybe_unused]]HeapStat* data, [[maybe_unused]]int count) override + { + } + void UpdateLastSeenObjectId([[maybe_unused]]uint32_t lastSeenObjectId) override + { + } private: int32_t fd_; diff --git a/ecmascript/tooling/interface/stream.h b/ecmascript/tooling/interface/stream.h index 5f5150b2a9..771895c3e5 100644 --- a/ecmascript/tooling/interface/stream.h +++ b/ecmascript/tooling/interface/stream.h @@ -17,6 +17,16 @@ #define ECMASCRIPT_TOOLING_INTERFACE_STREAM_H namespace panda::ecmascript { +class HeapStat { +public: + HeapStat(uint32_t index, uint32_t count, uint32_t size) + : index_(index), count_(count), size_(size) {} + + uint32_t index_; + uint32_t count_; + uint32_t size_; +}; + class Stream { public: virtual ~Stream() = default; @@ -29,6 +39,8 @@ public: // Writes the chunk of data into the stream virtual bool WriteChunk(char *data, int size) = 0; virtual bool Good() = 0; + virtual void UpdateHeapStats(HeapStat* data, int count) = 0; + virtual void UpdateLastSeenObjectId(uint32_t lastSeenObjectId) = 0; }; } // namespace panda::ecmascript diff --git a/ecmascript/tooling/test/debugger_events_test.cpp b/ecmascript/tooling/test/debugger_events_test.cpp index d92d1fd559..84fb2af0f5 100644 --- a/ecmascript/tooling/test/debugger_events_test.cpp +++ b/ecmascript/tooling/test/debugger_events_test.cpp @@ -514,7 +514,7 @@ HWTEST_F_L0(DebuggerEventsTest, HeapStatsUpdateToObjectTest) HeapStatsUpdate heapStatsUpdate; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); - heapStatsUpdate.SetStatsUpdate(CVector {}); + heapStatsUpdate.SetStatsUpdate(CVector {}); Local object1 = heapStatsUpdate.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); From 01d201d7e87be09a1d21181cc77f4ae509454f78 Mon Sep 17 00:00:00 2001 From: taohong Date: Mon, 6 Jun 2022 19:23:59 +0800 Subject: [PATCH 27/35] add type infer test case add test case for AOT type infer Signed-off-by: taohong Change-Id: Iff28cc77d3f309699000f76d1ed30191176a4d85 --- BUILD.gn | 1 + .../compiler/type_inference/type_infer.cpp | 20 ++++++ .../compiler/type_inference/type_infer.h | 1 + ecmascript/js_runtime_options.h | 13 ++++ ecmascript/ts_types/ts_loader.cpp | 5 ++ ecmascript/ts_types/ts_loader.h | 2 + script/run_ark_executable.py | 30 +++++++++ test/test_helper.gni | 61 +++++++++++++++++++ test/typeinfer/BUILD.gn | 17 ++++++ test/typeinfer/ldobjbyname/BUILD.gn | 18 ++++++ test/typeinfer/ldobjbyname/expect_output.txt | 15 +++++ test/typeinfer/ldobjbyname/ldobjbyname.ts | 22 +++++++ 12 files changed, 205 insertions(+) create mode 100644 test/typeinfer/BUILD.gn create mode 100644 test/typeinfer/ldobjbyname/BUILD.gn create mode 100644 test/typeinfer/ldobjbyname/expect_output.txt create mode 100644 test/typeinfer/ldobjbyname/ldobjbyname.ts diff --git a/BUILD.gn b/BUILD.gn index c2005e4c09..c5b55e1f3d 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -109,6 +109,7 @@ if (defined(ark_independent_build)) { if (is_standard_system) { deps += [ "//ark/js_runtime/test/aottest:ark_aot_test" ] deps += [ "//ark/js_runtime/test/moduletest:ark_asm_test" ] + deps += [ "//ark/js_runtime/test/typeinfer:ark_typeinfer_test" ] } } } diff --git a/ecmascript/compiler/type_inference/type_infer.cpp b/ecmascript/compiler/type_inference/type_infer.cpp index 905dcc794f..0f924f83cd 100644 --- a/ecmascript/compiler/type_inference/type_infer.cpp +++ b/ecmascript/compiler/type_inference/type_infer.cpp @@ -54,6 +54,26 @@ void TypeInfer::TraverseCircuit() COMPILER_LOG(INFO) << "TypeInfer:======================================================"; circuit_->PrintAllGates(*builder_); } + + if (tsLoader_->GetTypeInferenceLog()) { + TypeInferPrint(); + } +} + +void TypeInfer::TypeInferPrint() const +{ + const auto &gateList = circuit_->GetAllGates(); + std::string log("TestInfer:"); + for (const auto &gate : gateList) { + auto op = gateAccessor_.GetOpCode(gate); + if (op == OpCode::JS_BYTECODE) { + log += "&" + builder_->GetBytecodeStr(gate) + ":"; + auto gateType = gateAccessor_.GetGateType(gate); + auto type = gateType > GlobalTSTypeRef::TS_TYPE_RESERVED_COUNT ? "INF" : std::to_string(gateType); + log += type; + } + } + COMPILER_LOG(INFO) << std::dec << log; } bool TypeInfer::UpdateType(GateRef gate, const GateType type) diff --git a/ecmascript/compiler/type_inference/type_infer.h b/ecmascript/compiler/type_inference/type_infer.h index abdc0fa68a..c435b83723 100644 --- a/ecmascript/compiler/type_inference/type_infer.h +++ b/ecmascript/compiler/type_inference/type_infer.h @@ -67,6 +67,7 @@ private: bool InferDefineGetterSetterByValue(GateRef gate); bool InferNewObjSpread(GateRef gate); bool InferSuperCall(GateRef gate); + void TypeInferPrint() const; BytecodeCircuitBuilder *builder_ {nullptr}; Circuit *circuit_ {nullptr}; diff --git a/ecmascript/js_runtime_options.h b/ecmascript/js_runtime_options.h index 0c9255d55f..4c06fcda2c 100644 --- a/ecmascript/js_runtime_options.h +++ b/ecmascript/js_runtime_options.h @@ -72,6 +72,7 @@ public: parser->Add(&startup_time_); parser->Add(&snapshotOutputFile_); parser->Add(&enableRuntimeStat_); + parser->Add(&logTypeInfer_); } bool EnableArkTools() const @@ -471,6 +472,16 @@ public: snapshotOutputFile_.SetValue(std::move(value)); } + bool GetLogTypeInfer() const + { + return logTypeInfer_.GetValue(); + } + + void SetLogTypeInfer(bool value) + { + logTypeInfer_.SetValue(value); + } + private: static constexpr uint64_t INTERNAL_MEMORY_SIZE_LIMIT_DEFAULT = 2147483648; static constexpr uint64_t COMPILER_MEMORY_SIZE_LIMIT_DEFAULT = 268435456; @@ -535,6 +546,8 @@ private: R"(Path to snapshot output file. Default: "snapshot")"}; PandArg enableRuntimeStat_ {"enable-runtime-stat", false, R"(enable statistics of runtime state. Default: false)"}; + PandArg logTypeInfer_ {"log-Type-Infer", false, + R"(print aot type infer log. Default: false)"}; }; } // namespace panda::ecmascript diff --git a/ecmascript/ts_types/ts_loader.cpp b/ecmascript/ts_types/ts_loader.cpp index 84a23b9fad..ddecd7657e 100644 --- a/ecmascript/ts_types/ts_loader.cpp +++ b/ecmascript/ts_types/ts_loader.cpp @@ -481,6 +481,11 @@ size_t TSLoader::GetStringIdx(JSHandle constPool, const uint16_t return AddConstString(str); } +bool TSLoader::GetTypeInferenceLog() const +{ + return vm_->GetJSOptions().GetLogTypeInfer(); +} + void TSModuleTable::Initialize(JSThread *thread, JSHandle mTable) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); diff --git a/ecmascript/ts_types/ts_loader.h b/ecmascript/ts_types/ts_loader.h index 94906dbfd4..fba466da78 100644 --- a/ecmascript/ts_types/ts_loader.h +++ b/ecmascript/ts_types/ts_loader.h @@ -272,6 +272,8 @@ public: size_t PUBLIC_API AddConstString(JSTaggedValue string); + bool PUBLIC_API GetTypeInferenceLog() const; + // add string to constantstringtable and get its index size_t PUBLIC_API GetStringIdx(JSHandle constPool, const uint16_t id); diff --git a/script/run_ark_executable.py b/script/run_ark_executable.py index 1864295255..12e518a853 100755 --- a/script/run_ark_executable.py +++ b/script/run_ark_executable.py @@ -35,11 +35,22 @@ def parse_args(): parser.add_argument('--expect-output', help='expect output') parser.add_argument('--expect-sub-output', help='expect sub output') parser.add_argument('--expect-file', help='expect file') + parser.add_argument('--expect-gatetype', help='expect gatetype') parser.add_argument('--env-path', help='LD_LIBRARY_PATH env') parser.add_argument('--timeout-limit', help='timeout limit') args = parser.parse_args() return args +def isSubSequence(total, subList): + idx = 0 + if len(subList) == 1 and subList[0] == '': + return True + for obj in total: + if idx == len(subList): + return True + if obj == subList[idx]: + idx = idx + 1 + return idx == len(subList) def judge_output(args): """run testcase and judge is success or not.""" @@ -91,6 +102,25 @@ def judge_output(args): print(">>>>> Expect : [" + expect_output \ + "]\n>>>>> But got: [" + out_str + "]") raise RuntimeError("Run [" + cmd + "] failed!") + elif args.expect_gatetype: + with open(args.expect_gatetype, mode='r') as file: + # skip license header + expect_output = ''.join(file.readlines()[13:]) + file.close() + err_str = err.decode('UTF-8') + err_list = [] + for item in err_str.splitlines(): + if "TestInfer:" in item: + err_list.append(item.split("&")[1:]) + expect_output = expect_output.replace('\n', '') + expect_list = [elements.split(",") for elements in expect_output.split("[")] + for obj1, obj2 in zip(err_list, expect_list): + if not isSubSequence(obj1, obj2): + print(">>>>> Expect :", end = " ") + print(obj2) + print(">>>>> But got:", end = " ") + print(obj1) + raise RuntimeError("Run [" + cmd + "] failed!") else: raise RuntimeError("Run [" + cmd + "] with no expect !") diff --git a/test/test_helper.gni b/test/test_helper.gni index 699561017a..0ae11d815e 100644 --- a/test/test_helper.gni +++ b/test/test_helper.gni @@ -318,3 +318,64 @@ template("host_aot_test_action") { outputs = [ "$target_out_dir/${_target_name_}/" ] } } + +template("host_typeinfer_test_action") { + _target_name_ = "${target_name}" + _deps_ = invoker.deps + + _test_ts_path_ = "./${_target_name_}.ts" + _test_abc_path_ = "$target_out_dir/${_target_name_}.abc" + _test_expect_path_ = "./expect_output.txt" + + ts2abc_gen_abc("gen_${_target_name_}_abc") { + extra_visibility = [ ":*" ] # Only targets in this file can depend on this. + extra_dependencies = _deps_ + src_js = rebase_path(_test_ts_path_) + dst_file = rebase_path(_test_abc_path_) + extra_args = [ "--debug" ] + + in_puts = [ + _test_ts_path_, + _test_expect_path_, + ] + out_puts = [ _test_abc_path_ ] + } + + _script_args_ = rebase_path(_test_abc_path_) + + action("${_target_name_}AotTypeInferAction") { + testonly = true + + _host_aot_target_ = "//ark/js_runtime/ecmascript/compiler:ark_aot_compiler(${host_toolchain})" + _root_out_dir_ = get_label_info(_host_aot_target_, "root_out_dir") + deps = [ + ":gen_${_target_name_}_abc", + _host_aot_target_, + ] + deps += _deps_ + + script = "//ark/js_runtime/script/run_ark_executable.py" + + _aot_compile_options_ = " --asm-interpreter=true" + " --log-Type-Infer=true" + + args = [ + "--script-file", + rebase_path(_root_out_dir_) + "/ark/ark_js_runtime/ark_aot_compiler", + "--script-options", + _aot_compile_options_, + "--script-args", + _script_args_, + "--expect-gatetype", + rebase_path(_test_expect_path_), + "--env-path", + rebase_path(_root_out_dir_) + "/ark/ark:" + rebase_path(_root_out_dir_) + + "/ark/ark_js_runtime:" + rebase_path(_root_out_dir_) + + "/${_icu_path_}:" + + rebase_path("//prebuilts/clang/ohos/linux-x86_64/llvm/lib/"), + ] + + inputs = [ _test_abc_path_ ] + + outputs = [ "$target_out_dir/${_target_name_}/" ] + } +} diff --git a/test/typeinfer/BUILD.gn b/test/typeinfer/BUILD.gn new file mode 100644 index 0000000000..2cc162fcdc --- /dev/null +++ b/test/typeinfer/BUILD.gn @@ -0,0 +1,17 @@ +# Copyright (c) 2021 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. + +group("ark_typeinfer_test") { + testonly = true + deps = [ "ldobjbyname:ldobjbynameAotTypeInferAction" ] +} diff --git a/test/typeinfer/ldobjbyname/BUILD.gn b/test/typeinfer/ldobjbyname/BUILD.gn new file mode 100644 index 0000000000..dba1dc4d28 --- /dev/null +++ b/test/typeinfer/ldobjbyname/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_typeinfer_test_action("ldobjbyname") { + deps = [] +} diff --git a/test/typeinfer/ldobjbyname/expect_output.txt b/test/typeinfer/ldobjbyname/expect_output.txt new file mode 100644 index 0000000000..a8fcaa00c0 --- /dev/null +++ b/test/typeinfer/ldobjbyname/expect_output.txt @@ -0,0 +1,15 @@ +# 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. + +LDLEXENVDYN:0,LDA_STR:4,DEFINECLASSWITHBUFFER:INF,LDA_STR:4,LDOBJBYNAME:4,TYPEOFDYN:4 +[LDLEXENVDYN:0 \ No newline at end of file diff --git a/test/typeinfer/ldobjbyname/ldobjbyname.ts b/test/typeinfer/ldobjbyname/ldobjbyname.ts new file mode 100644 index 0000000000..002d39b2f7 --- /dev/null +++ b/test/typeinfer/ldobjbyname/ldobjbyname.ts @@ -0,0 +1,22 @@ +/* + * 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. + */ + +{ + class Student { + static age : string = "18"; + } + let stu = new Student() + typeof(Student.age); +} From 0ff8dcd69d60e232334da5d5fe172789a123e23f Mon Sep 17 00:00:00 2001 From: wangzhaoyong Date: Sat, 28 May 2022 18:13:10 +0800 Subject: [PATCH 28/35] ==-------------------------------------------== Support transfer custom native object 1. add create object interface for napi 2. support serialize custom native object issue: https://gitee.com/openharmony/ark_js_runtime/issues/I59GXI ==-------------------------------------------== Signed-off-by: wangzhaoyong Change-Id: I8c033761f0503698e20241407db47bebb533ee43 --- ecmascript/builtins.cpp | 10 +++ ecmascript/dump.cpp | 6 ++ ecmascript/global_env.h | 4 +- ecmascript/js_serializer.cpp | 120 ++++++++++++++++++++++++++++++- ecmascript/js_serializer.h | 6 ++ ecmascript/layout_info.cpp | 4 +- ecmascript/napi/include/jsnapi.h | 1 + ecmascript/napi/jsnapi.cpp | 17 +++++ 8 files changed, 162 insertions(+), 6 deletions(-) diff --git a/ecmascript/builtins.cpp b/ecmascript/builtins.cpp index 70791f427c..fc42706c57 100644 --- a/ecmascript/builtins.cpp +++ b/ecmascript/builtins.cpp @@ -586,6 +586,10 @@ void Builtins::InitializeSymbol(const JSHandle &env, const JSHandle unscopablesSymbol(factory_->NewPublicSymbolWithChar("Symbol.unscopables")); SetNoneAttributeProperty(symbolFunction, "unscopables", unscopablesSymbol); + JSHandle attachSymbol(factory_->NewPublicSymbolWithChar("Symbol.attach")); + SetNoneAttributeProperty(symbolFunction, "attach", attachSymbol); + JSHandle detachSymbol(factory_->NewPublicSymbolWithChar("Symbol.detach")); + SetNoneAttributeProperty(symbolFunction, "detach", detachSymbol); // symbol.prototype.description PropertyDescriptor descriptionDesc(thread_); @@ -615,6 +619,8 @@ void Builtins::InitializeSymbol(const JSHandle &env, const JSHandleSetSplitSymbol(thread_, splitSymbol); env->SetToPrimitiveSymbol(thread_, toPrimitiveSymbol); env->SetUnscopablesSymbol(thread_, unscopablesSymbol); + env->SetAttachSymbol(thread_, attachSymbol); + env->SetDetachSymbol(thread_, detachSymbol); // Setup %SymbolPrototype% SetStringTagSymbol(env, symbolFuncPrototype, "Symbol"); @@ -670,6 +676,8 @@ void Builtins::InitializeSymbolWithRealm(const JSHandle &realm, SetNoneAttributeProperty(symbolFunction, "split", env->GetSplitSymbol()); SetNoneAttributeProperty(symbolFunction, "toPrimitive", env->GetToPrimitiveSymbol()); SetNoneAttributeProperty(symbolFunction, "unscopables", env->GetUnscopablesSymbol()); + SetNoneAttributeProperty(symbolFunction, "attach", env->GetAttachSymbol()); + SetNoneAttributeProperty(symbolFunction, "detach", env->GetDetachSymbol()); // symbol.prototype.description PropertyDescriptor descriptionDesc(thread_); @@ -700,6 +708,8 @@ void Builtins::InitializeSymbolWithRealm(const JSHandle &realm, realm->SetSplitSymbol(thread_, env->GetSplitSymbol()); realm->SetToPrimitiveSymbol(thread_, env->GetToPrimitiveSymbol()); realm->SetUnscopablesSymbol(thread_, env->GetUnscopablesSymbol()); + realm->SetAttachSymbol(thread_, env->GetAttachSymbol()); + realm->SetDetachSymbol(thread_, env->GetDetachSymbol()); // Setup %SymbolPrototype% SetStringTagSymbol(realm, symbolFuncPrototype, "Symbol"); diff --git a/ecmascript/dump.cpp b/ecmascript/dump.cpp index be4944b046..8b13849ca5 100644 --- a/ecmascript/dump.cpp +++ b/ecmascript/dump.cpp @@ -1814,6 +1814,10 @@ void GlobalEnv::Dump(std::ostream &os) const GetUnscopablesSymbol().GetTaggedValue().Dump(os); os << " - HoleySymbol: "; GetHoleySymbol().GetTaggedValue().Dump(os); + os << " - AttachSymbol: "; + GetAttachSymbol().GetTaggedValue().Dump(os); + os << " - DetachSymbol: "; + GetDetachSymbol().GetTaggedValue().Dump(os); os << " - ConstructorString: "; globalConst->GetConstructorString().Dump(os); os << " - IteratorPrototype: "; @@ -3702,6 +3706,8 @@ void GlobalEnv::DumpForSnapshot(std::vector> & vec.push_back(std::make_pair(CString("ToPrimitiveSymbol"), GetToPrimitiveSymbol().GetTaggedValue())); vec.push_back(std::make_pair(CString("UnscopablesSymbol"), GetUnscopablesSymbol().GetTaggedValue())); vec.push_back(std::make_pair(CString("HoleySymbol"), GetHoleySymbol().GetTaggedValue())); + vec.push_back(std::make_pair(CString("AttachSymbol"), GetAttachSymbol().GetTaggedValue())); + vec.push_back(std::make_pair(CString("DetachSymbol"), GetDetachSymbol().GetTaggedValue())); vec.push_back(std::make_pair(CString("ConstructorString"), globalConst->GetConstructorString())); vec.push_back(std::make_pair(CString("IteratorPrototype"), GetIteratorPrototype().GetTaggedValue())); vec.push_back(std::make_pair(CString("ForinIteratorPrototype"), GetForinIteratorPrototype().GetTaggedValue())); diff --git a/ecmascript/global_env.h b/ecmascript/global_env.h index fa3662160f..2e86fdf694 100644 --- a/ecmascript/global_env.h +++ b/ecmascript/global_env.h @@ -149,7 +149,9 @@ class JSThread; V(JSTaggedValue, ModuleNamespaceClass, MODULENAMESPACE_CLASS) \ V(JSTaggedValue, ObjectLiteralHClassCache, OBJECT_LITERAL_HCLASS_CACHE) \ V(JSTaggedValue, WeakRefKeepObjects, WEAK_REF_KEEP_OBJECTS) \ - V(JSTaggedValue, FinRegLists, FIN_REG_LISTS) + V(JSTaggedValue, FinRegLists, FIN_REG_LISTS) \ + V(JSTaggedValue, AttachSymbol, ATTACH_SYMBOL_INDEX) \ + V(JSTaggedValue, DetachSymbol, DETACH_SYMBOL_INDEX) class GlobalEnv : public TaggedObject { public: diff --git a/ecmascript/js_serializer.cpp b/ecmascript/js_serializer.cpp index 88971fb7d7..70a122f569 100644 --- a/ecmascript/js_serializer.cpp +++ b/ecmascript/js_serializer.cpp @@ -664,6 +664,16 @@ bool JSSerializer::WritePlainObject(const JSHandle &objValue) { JSHandle obj = JSHandle::Cast(objValue); size_t oldSize = bufferSize_; + std::vector keyVector; + uint32_t propertiesLength = obj->GetNumberOfKeys(); + JSObject::GetAllKeys(thread_, obj, keyVector); + if (keyVector.size() != propertiesLength) { + return false; + } + + if (keyVector.size() >= 2 && (keyVector[0].IsSymbol() && keyVector[1].IsSymbol())) { // 2:attachSymbol, detachSymbol + return WriteNativeObject(objValue, keyVector); + } if (!WriteType(SerializationUID::JS_PLAIN_OBJECT)) { return false; } @@ -673,7 +683,7 @@ bool JSSerializer::WritePlainObject(const JSHandle &objValue) bufferSize_ = oldSize; return false; } - std::vector keyVector; + keyVector.clear(); JSObject::GetALLElementKeysIntoVector(thread_, obj, keyVector); // Write elements' description attributes and value if (keyVector.size() != elementsLength) { @@ -700,7 +710,6 @@ bool JSSerializer::WritePlainObject(const JSHandle &objValue) } // Get the number of k-v form properties stored in obj keyVector.clear(); - uint32_t propertiesLength = obj->GetNumberOfKeys(); if (!WriteInt(static_cast(propertiesLength))) { bufferSize_ = oldSize; return false; @@ -736,6 +745,65 @@ bool JSSerializer::WritePlainObject(const JSHandle &objValue) return true; } +bool JSSerializer::WriteNativeObject(const JSHandle &objValue, std::vector keyVector) +{ + JSHandle obj = JSHandle::Cast(objValue); + size_t oldSize = bufferSize_; + JSHandle env = thread_->GetEcmaVM()->GetGlobalEnv(); + JSHandle detach = env->GetDetachSymbol(); + JSHandle attach = env->GetAttachSymbol(); + if (!(JSTaggedValue::Equal(thread_, detach, JSHandle(thread_, keyVector[0]))) || + !(JSTaggedValue::Equal(thread_, attach, JSHandle(thread_, keyVector[1])))) { + return false; + } + if (!WriteType(SerializationUID::JS_NATIVE_OBJECT)) { + return false; + } + // Write custom object's values: AttachFunc*, buffer* + JSHandle detachVal = JSObject::GetProperty(thread_, obj, detach).GetRawValue(); + JSHandle attackVal = JSObject::GetProperty(thread_, obj, attach).GetRawValue(); + DetachFunc detachNative = reinterpret_cast(JSNativePointer::Cast( + detachVal.GetTaggedValue().GetTaggedObject())->GetExternalPointer()); + void *buffer = detachNative(); + AttachFunc attachNative = reinterpret_cast(JSNativePointer::Cast( + attackVal.GetTaggedValue().GetTaggedObject())->GetExternalPointer()); + if (!WriteRawData(&attachNative, sizeof(uintptr_t))) { + bufferSize_ = oldSize; + return false; + } + if (!WriteRawData(&buffer, sizeof(uintptr_t))) { + bufferSize_ = oldSize; + return false; + } + if (keyVector.size() > 2) { // 2:attachSymbol, detachSymbol + uint32_t propertiesLength = keyVector.size() - 2; + if (!WriteInt(static_cast(propertiesLength))) { + bufferSize_ = oldSize; + return false; + } + // Write keys' description attributes and related values + for (uint32_t i = 0; i < propertiesLength; i++) { + JSMutableHandle key(thread_, keyVector[i + 2]); // 2:attachSymbol, detachSymbol + if (!SerializeJSTaggedValue(key)) { + bufferSize_ = oldSize; + return false; + } + PropertyDescriptor desc(thread_); + JSObject::OrdinaryGetOwnProperty(thread_, obj, key, desc); + if (!WriteDesc(desc)) { + bufferSize_ = oldSize; + return false; + } + JSHandle value = desc.GetValue(); + if (!SerializeJSTaggedValue(value)) { + bufferSize_ = oldSize; + return false; + } + } + } + return true; +} + bool JSSerializer::WriteDesc(const PropertyDescriptor &desc) { size_t oldSize = bufferSize_; @@ -874,6 +942,8 @@ JSHandle JSDeserializer::DeserializeJSTaggedValue() return ReadJSDate(); case SerializationUID::JS_PLAIN_OBJECT: return ReadPlainObject(); + case SerializationUID::JS_NATIVE_OBJECT: + return ReadNativeObject(); case SerializationUID::JS_ARRAY: return ReadJSArray(); case SerializationUID::ECMASTRING: @@ -1045,6 +1115,52 @@ JSHandle JSDeserializer::ReadPlainObject() return objTag; } +JSHandle JSDeserializer::ReadNativeObject() +{ + JSHandle env = thread_->GetEcmaVM()->GetGlobalEnv(); + JSHandle objFunc = env->GetObjectFunction(); + JSHandle jsObject = + thread_->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(JSHandle(objFunc), objFunc); + JSHandle objTag(jsObject); + referenceMap_.insert(std::pair(objectId_++, objTag)); + + JSTaggedValue pointer; + if (!ReadJSTaggedValue(&pointer)) { + return JSHandle(); + } + AttachFunc attachFunc = reinterpret_cast(JSNativePointer::Cast(pointer.GetTaggedObject())); + JSTaggedValue bufferPointer; + if (!ReadJSTaggedValue(&bufferPointer)) { + return JSHandle(); + } + void *buffer = reinterpret_cast(JSNativePointer::Cast(bufferPointer.GetTaggedObject())); + attachFunc(buffer); + + int32_t propertyLength; + if (!JudgeType(SerializationUID::INT32) || !ReadInt(&propertyLength)) { + return objTag; + } + for (int32_t i = 0; i < propertyLength; i++) { + JSHandle key = DeserializeJSTaggedValue(); + if (key.IsEmpty()) { + return JSHandle(); + } + PropertyDescriptor desc(thread_); + if (!ReadDesc(&desc)) { + return JSHandle(); + } + JSHandle value = DeserializeJSTaggedValue(); + if (value.IsEmpty()) { + return JSHandle(); + } + desc.SetValue(value); + if (!JSTaggedValue::DefineOwnProperty(thread_, objTag, key, desc)) { + return JSHandle(); + } + } + return objTag; +} + JSHandle JSDeserializer::ReadJSMap() { JSHandle env = thread_->GetEcmaVM()->GetGlobalEnv(); diff --git a/ecmascript/js_serializer.h b/ecmascript/js_serializer.h index 7fdf072fa8..0053b982c6 100644 --- a/ecmascript/js_serializer.h +++ b/ecmascript/js_serializer.h @@ -28,6 +28,9 @@ #include "ecmascript/mem/dyn_chunk.h" namespace panda::ecmascript { +typedef void* (*DetachFunc)(void); +typedef void (*AttachFunc)(void* buffer); + enum class SerializationUID : uint8_t { // JS special values JS_NULL = 0x01, @@ -50,6 +53,7 @@ enum class SerializationUID : uint8_t { JS_DATE, JS_REG_EXP, JS_PLAIN_OBJECT, + JS_NATIVE_OBJECT, JS_SET, JS_MAP, JS_ARRAY, @@ -113,6 +117,7 @@ private: bool WriteEcmaString(const JSHandle &value); bool WriteJSTypedArray(const JSHandle &value, SerializationUID uId); bool WritePlainObject(const JSHandle &value); + bool WriteNativeObject(const JSHandle &value, std::vector keyVector); bool WriteNativeFunctionPointer(const JSHandle &value); bool WriteJSArrayBuffer(const JSHandle &value); bool WriteDesc(const PropertyDescriptor &desc); @@ -160,6 +165,7 @@ private: JSHandle ReadNativeFunctionPointer(); JSHandle ReadJSArrayBuffer(); JSHandle ReadReference(); + JSHandle ReadNativeObject(); bool JudgeType(SerializationUID targetUid); void *GetBuffer(uint32_t bufferSize); bool ReadJSTaggedValue(JSTaggedValue *originalFlags); diff --git a/ecmascript/layout_info.cpp b/ecmascript/layout_info.cpp index 49a951caee..2fa3d9be91 100644 --- a/ecmascript/layout_info.cpp +++ b/ecmascript/layout_info.cpp @@ -72,12 +72,10 @@ void LayoutInfo::GetAllKeys(const JSThread *thread, int end, int offset, TaggedA void LayoutInfo::GetAllKeys([[maybe_unused]] const JSThread *thread, int end, std::vector &keyVector) { ASSERT(end <= NumberOfElements()); - int enumKeys = 0; for (int i = 0; i < end; i++) { JSTaggedValue key = GetKey(i); - if (key.IsString()) { + if (key.IsString() || key.IsSymbol()) { keyVector.emplace_back(key); - enumKeys++; } } } diff --git a/ecmascript/napi/include/jsnapi.h b/ecmascript/napi/include/jsnapi.h index 0af9e28c18..a2c2d91871 100644 --- a/ecmascript/napi/include/jsnapi.h +++ b/ecmascript/napi/include/jsnapi.h @@ -669,6 +669,7 @@ public: return static_cast(value); } static Local New(const EcmaVM *vm); + static Local New(const EcmaVM *vm, void *attach, void *detach); bool Set(const EcmaVM *vm, Local key, Local value); bool Set(const EcmaVM *vm, uint32_t key, Local value); bool SetAccessorProperty(const EcmaVM *vm, Local key, Local getter, diff --git a/ecmascript/napi/jsnapi.cpp b/ecmascript/napi/jsnapi.cpp index 4e32c69de7..a3dcddd8ec 100644 --- a/ecmascript/napi/jsnapi.cpp +++ b/ecmascript/napi/jsnapi.cpp @@ -741,6 +741,23 @@ Local ObjectRef::New(const EcmaVM *vm) return JSNApiHelper::ToLocal(object); } +Local ObjectRef::New(const EcmaVM *vm, void *detach, void *attach) +{ + ObjectFactory *factory = vm->GetFactory(); + JSHandle env = vm->GetGlobalEnv(); + JSHandle constructor = env->GetObjectFunction(); + JSHandle object(factory->NewJSObjectByConstructor(JSHandle(constructor), constructor)); + JSHandle detachKey = env->GetDetachSymbol(); + JSHandle attachKey = env->GetAttachSymbol(); + JSHandle detachValue = JSNApiHelper::ToJSHandle(NativePointerRef::New(vm, detach)); + JSHandle attachValue = JSNApiHelper::ToJSHandle(NativePointerRef::New(vm, attach)); + JSTaggedValue::SetProperty(vm->GetJSThread(), object, detachKey, detachValue); + RETURN_VALUE_IF_ABRUPT(vm->GetJSThread(), JSValueRef::Exception(vm)); + JSTaggedValue::SetProperty(vm->GetJSThread(), object, attachKey, attachValue); + RETURN_VALUE_IF_ABRUPT(vm->GetJSThread(), JSValueRef::Exception(vm)); + return JSNApiHelper::ToLocal(object); +} + bool ObjectRef::Set(const EcmaVM *vm, Local key, Local value) { [[maybe_unused]] LocalScope scope(vm); From b67b4eeeb1550fcbc95b3c5e8195228c0ac3987f Mon Sep 17 00:00:00 2001 From: ding Date: Tue, 7 Jun 2022 12:12:06 +0800 Subject: [PATCH 29/35] AOT compiler supports file without type info Add judement in DecodeTSTypes and GetGateType, to support compiling js files in AOT. Add pf_ as a member of BytecodeCircuitBuilder. issue:https://gitee.com/openharmony/ark_js_runtime/issues/I5AZJV Signed-off-by: ding Change-Id: Ia16039e0ba455c6618fec3691c3089067a508373 --- ecmascript/compiler/bytecode_circuit_builder.cpp | 16 +++++++++------- ecmascript/compiler/bytecode_circuit_builder.h | 3 ++- ecmascript/compiler/pass_manager.cpp | 8 ++++++-- ecmascript/jspandafile/js_pandafile_manager.cpp | 6 ------ ecmascript/ts_types/ts_loader.cpp | 1 + 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/ecmascript/compiler/bytecode_circuit_builder.cpp b/ecmascript/compiler/bytecode_circuit_builder.cpp index 2e82730d7b..a033e3ab3e 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.cpp +++ b/ecmascript/compiler/bytecode_circuit_builder.cpp @@ -149,10 +149,9 @@ std::map, std::vector> BytecodeCircui std::map &byteCodeCurPrePc, std::vector &bytecodeBlockInfos) { // try contains many catch - const panda_file::File *file = file_->GetPandaFile(); std::map, std::vector> byteCodeException; - panda_file::MethodDataAccessor mda(*file, method_->GetMethodId()); - panda_file::CodeDataAccessor cda(*file, mda.GetCodeId().value()); + panda_file::MethodDataAccessor mda(*pf_, method_->GetMethodId()); + panda_file::CodeDataAccessor cda(*pf_, mda.GetCodeId().value()); cda.EnumerateTryBlocks([this, &byteCodeCurPrePc, &bytecodeBlockInfos, &byteCodeException]( panda_file::CodeDataAccessor::TryBlock &try_block) { auto tryStartOffset = try_block.GetStartPc(); @@ -2324,10 +2323,13 @@ GateRef BytecodeCircuitBuilder::NewPhi(BytecodeRegion &bb, uint16_t reg, bool ac GateType BytecodeCircuitBuilder::GetRealGateType(const uint16_t reg, const GateType gateType) { - const panda_file::File *pf = file_->GetPandaFile(); - auto curType = static_cast(tsLoader_->GetGTFromPandaFile(*pf, reg, method_).GetData()); - auto type = (curType == GateType::JS_ANY) ? gateType : curType; - return type; + if (file_->HasTSTypes()) { + auto curType = static_cast(tsLoader_->GetGTFromPandaFile(*pf_, reg, method_).GetData()); + auto type = (curType == GateType::JS_ANY) ? gateType : curType; + return type; + } + + return GateType::JS_ANY; } // recursive variables renaming algorithm diff --git a/ecmascript/compiler/bytecode_circuit_builder.h b/ecmascript/compiler/bytecode_circuit_builder.h index 404ed356a9..324c37e96d 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.h +++ b/ecmascript/compiler/bytecode_circuit_builder.h @@ -351,7 +351,7 @@ class BytecodeCircuitBuilder { public: explicit BytecodeCircuitBuilder(const BytecodeTranslationInfo &translationInfo, size_t index, TSLoader *tsLoader, bool enableLog) - : tsLoader_(tsLoader), file_(translationInfo.jsPandaFile), + : tsLoader_(tsLoader), file_(translationInfo.jsPandaFile), pf_(translationInfo.jsPandaFile->GetPandaFile()), method_(translationInfo.methodPcInfos[index].method), pcArray_(translationInfo.methodPcInfos[index].pcArray), constantPool_(translationInfo.constantPool), @@ -469,6 +469,7 @@ private: std::vector actualArgs_ {}; TSLoader *tsLoader_ {nullptr}; const JSPandaFile *file_ {nullptr}; + const panda_file::File *pf_ {nullptr}; const JSMethod *method_ {nullptr}; const std::vector pcArray_; JSHandle constantPool_; diff --git a/ecmascript/compiler/pass_manager.cpp b/ecmascript/compiler/pass_manager.cpp index 1c3dd0d916..8a8a3dc809 100644 --- a/ecmascript/compiler/pass_manager.cpp +++ b/ecmascript/compiler/pass_manager.cpp @@ -81,8 +81,12 @@ bool PassManager::CollectInfoOfPandaFile(const std::string &fileName, std::strin } translateInfo->jsPandaFile = jsPandaFile; - TSLoader *tsLoader = vm_->GetTSLoader(); - tsLoader->DecodeTSTypes(jsPandaFile); + if (jsPandaFile->HasTSTypes()) { + TSLoader *tsLoader = vm_->GetTSLoader(); + tsLoader->DecodeTSTypes(jsPandaFile); + } else { + COMPILER_LOG(INFO) << fileName << " has no type info"; + } auto program = PandaFileTranslator::GenerateProgram(vm_, jsPandaFile); JSHandle mainFunc(vm_->GetJSThread(), program->GetMainFunction()); diff --git a/ecmascript/jspandafile/js_pandafile_manager.cpp b/ecmascript/jspandafile/js_pandafile_manager.cpp index 64635a7f48..1ac1f2a5b8 100644 --- a/ecmascript/jspandafile/js_pandafile_manager.cpp +++ b/ecmascript/jspandafile/js_pandafile_manager.cpp @@ -52,12 +52,6 @@ const JSPandaFile *JSPandaFileManager::LoadAotInfoFromPf(const CString &filename return nullptr; } - if (!jsPandaFile->HasTSTypes()) { - LOG_ECMA(ERROR) << filename << " has no type info"; - ReleaseJSPandaFile(jsPandaFile); - return nullptr; - } - CString methodName; auto pos = entryPoint.find_last_of("::"); if (pos != std::string_view::npos) { diff --git a/ecmascript/ts_types/ts_loader.cpp b/ecmascript/ts_types/ts_loader.cpp index fb3fc39036..08a02cad78 100644 --- a/ecmascript/ts_types/ts_loader.cpp +++ b/ecmascript/ts_types/ts_loader.cpp @@ -24,6 +24,7 @@ namespace panda::ecmascript { void TSLoader::DecodeTSTypes(const JSPandaFile *jsPandaFile) { + ASSERT_PRINT(jsPandaFile->HasTSTypes(), "the file has no ts type info"); JSThread *thread = vm_->GetJSThread(); ObjectFactory *factory = vm_->GetFactory(); JSHandle mTable = GetTSModuleTable(); From 87d021cec97208d590a135ca3ae5773133e5f0ff Mon Sep 17 00:00:00 2001 From: xiongluo Date: Mon, 6 Jun 2022 21:06:23 +0800 Subject: [PATCH 30/35] add smart gc interface and change gc params add interface to change gc params close concurrent sweep and mark in background limit the post task num issue:https://gitee.com/openharmony/ability_ability_runtime/issues/I59N1V Signed-off-by: xiongluo --- ecmascript/mem/concurrent_sweeper.cpp | 3 ++ ecmascript/mem/concurrent_sweeper.h | 10 +++++ ecmascript/mem/heap.cpp | 60 +++++++++++++++++++++++-- ecmascript/mem/heap.h | 41 ++++++++++++++--- ecmascript/mem/mem_controller.cpp | 19 +++++++- ecmascript/mem/parallel_evacuator-inl.h | 6 ++- ecmascript/napi/dfx_jsnapi.cpp | 9 ++++ ecmascript/napi/include/dfx_jsnapi.h | 2 + ecmascript/tests/gc_test.cpp | 59 ++++++++++++++++++++++++ 9 files changed, 195 insertions(+), 14 deletions(-) diff --git a/ecmascript/mem/concurrent_sweeper.cpp b/ecmascript/mem/concurrent_sweeper.cpp index 4e35ca5499..f923e5d244 100644 --- a/ecmascript/mem/concurrent_sweeper.cpp +++ b/ecmascript/mem/concurrent_sweeper.cpp @@ -95,6 +95,9 @@ void ConcurrentSweeper::EnsureAllTaskFinished() WaitingTaskFinish(static_cast(i)); } isSweeping_ = false; + if (disableConcurrentRequested_) { + EnableConcurrentSweep(false); + } } void ConcurrentSweeper::EnsureTaskFinished(MemSpaceType type) diff --git a/ecmascript/mem/concurrent_sweeper.h b/ecmascript/mem/concurrent_sweeper.h index 8c98eb6819..66037df17e 100644 --- a/ecmascript/mem/concurrent_sweeper.h +++ b/ecmascript/mem/concurrent_sweeper.h @@ -47,6 +47,15 @@ public: { return isSweeping_; } + + void EnableConcurrentSweep(bool flag) + { + if (concurrentSweep_ && isSweeping_ && !flag) { + disableConcurrentRequested_ = true; + } else { + concurrentSweep_ = flag; + } + } private: class SweeperTask : public Task { public: @@ -73,6 +82,7 @@ private: Heap *heap_; bool concurrentSweep_ {false}; + bool disableConcurrentRequested_ {false}; bool isSweeping_ {false}; MemSpaceType startSpaceType_ = MemSpaceType::OLD_SPACE; }; diff --git a/ecmascript/mem/heap.cpp b/ecmascript/mem/heap.cpp index 3eecbdc4c5..a95c21431e 100644 --- a/ecmascript/mem/heap.cpp +++ b/ecmascript/mem/heap.cpp @@ -87,8 +87,11 @@ void Heap::Initialize() compressSpace_ = new OldSpace(this, oldSpaceCapacity, oldSpaceCapacity); oldSpace_->Initialize(); hugeObjectSpace_ = new HugeObjectSpace(heapRegionAllocator_, oldSpaceCapacity, oldSpaceCapacity); - maxTaskCount_ = std::min(ecmaVm_->GetJSOptions().GetGcThreadNum(), - (Taskpool::GetCurrentTaskpool()->GetTotalThreadNum()) - 1); + initialEvacuateTaskCount_ = Taskpool::GetCurrentTaskpool()->GetTotalThreadNum(); + maxEvacuateTaskCount_ = initialEvacuateTaskCount_; + maxMarkTaskCount_ = std::min(ecmaVm_->GetJSOptions().GetGcThreadNum(), + initialEvacuateTaskCount_ - 1); + LOG(INFO, RUNTIME) << "heap initialize: heap size = " << MAX_HEAP_SIZE << ", semispace capacity = " << minSemiSpaceCapacity << ", nonmovablespace capacity = " << nonmovableSpaceCapacity @@ -96,7 +99,7 @@ void Heap::Initialize() << ", machinecodespace capacity = " << machineCodeSpaceCapacity << ", oldspace capacity = " << oldSpaceCapacity << ", globallimit = " << globalSpaceAllocLimit_ - << ", gcThreadNum = " << maxTaskCount_; + << ", gcThreadNum = " << maxMarkTaskCount_; parallelGC_ = ecmaVm_->GetJSOptions().EnableParallelGC(); concurrentMarkingEnabled_ = ecmaVm_->GetJSOptions().EnableConcurrentMark(); markType_ = MarkType::MARK_YOUNG; @@ -482,6 +485,9 @@ bool Heap::CheckOngoingConcurrentMarking() ECMA_GC_LOG() << "wait concurrent marking finish pause time " << clockScope.TotalSpentTime(); } memController_->RecordAfterConcurrentMark(IsFullMark(), concurrentMarker_); + if (disableConcurrentMarkRequested_) { + EnableConcurrentMarking(false); + } return true; } return false; @@ -632,10 +638,56 @@ void Heap::IncreaseTaskCount() runningTaskCount_++; } +void Heap::EnableConcurrentMarking(bool flag) +{ + if (concurrentMarkingEnabled_ && thread_->IsMarking() && !flag) { + disableConcurrentMarkRequested_ = true; + } else { + concurrentMarkingEnabled_ = flag; + } +} + +void Heap::ChangeGCParams(bool inBackground) +{ + if (inBackground) { + LOG(INFO, RUNTIME) << "app is inBackground"; + if (GetMemGrowingType() != MemGrowingType::PRESSURE) { + SetMemGrowingType(MemGrowingType::CONSERVATIVE); + LOG(INFO, RUNTIME) << "Heap Growing Type CONSERVATIVE"; + } + EnableConcurrentMarking(false); + sweeper_->EnableConcurrentSweep(false); + maxMarkTaskCount_ = 1; + maxEvacuateTaskCount_ = 1; + } else { + LOG(INFO, RUNTIME) << "app is not inBackground"; + if (GetMemGrowingType() != MemGrowingType::PRESSURE) { + SetMemGrowingType(MemGrowingType::HIGH_THROUGHPUT); + LOG(INFO, RUNTIME) << "Heap Growing Type HIGH_THROUGHPUT"; + } + EnableConcurrentMarking(true); + sweeper_->EnableConcurrentSweep(true); + maxMarkTaskCount_ = std::min(ecmaVm_->GetJSOptions().GetGcThreadNum(), + initialEvacuateTaskCount_ - 1); + maxEvacuateTaskCount_ = initialEvacuateTaskCount_; + } +} + +void Heap::NotifyMemoryPressure(bool inHighMemoryPressure) +{ + if (inHighMemoryPressure) { + LOG(INFO, RUNTIME) << "app is inHighMemoryPressure"; + SetMemGrowingType(MemGrowingType::PRESSURE); + } else { + LOG(INFO, RUNTIME) << "app is not inHighMemoryPressure"; + SetMemGrowingType(MemGrowingType::CONSERVATIVE); + } +} + bool Heap::CheckCanDistributeTask() { os::memory::LockHolder holder(waitTaskFinishedMutex_); - return runningTaskCount_ < maxTaskCount_; + return runningTaskCount_ < maxMarkTaskCount_; } void Heap::ReduceTaskCount() diff --git a/ecmascript/mem/heap.h b/ecmascript/mem/heap.h index eb8403c352..1b41bcec9a 100644 --- a/ecmascript/mem/heap.h +++ b/ecmascript/mem/heap.h @@ -46,6 +46,11 @@ enum class MarkType : uint8_t { MARK_FULL }; +enum class MemGrowingType : uint8_t { + HIGH_THROUGHPUT, + CONSERVATIVE, + PRESSURE +}; class Heap { public: explicit Heap(EcmaVM *ecmaVm); @@ -236,7 +241,8 @@ public: { return parallelGC_; } - + void ChangeGCParams(bool inBackground); + void NotifyMemoryPressure(bool inHighMemoryPressure); bool CheckCanDistributeTask(); void WaitRunningTaskFinished(); @@ -245,10 +251,7 @@ public: * Concurrent marking related configurations and utilities. */ - void EnableConcurrentMarking(bool flag) - { - concurrentMarkingEnabled_ = flag; - } + void EnableConcurrentMarking(bool flag); bool ConcurrentMarkingEnabled() const { @@ -320,6 +323,16 @@ public: void WaitConcurrentMarkingFinished(); + MemGrowingType GetMemGrowingType() const + { + return memGrowingtype_; + } + + void SetMemGrowingType(MemGrowingType memGrowingType) + { + memGrowingtype_ = memGrowingType; + } + inline size_t GetCommittedSize() const; inline size_t GetHeapObjectSize() const; @@ -333,6 +346,16 @@ public: size_t GetArrayBufferSize() const; + uint32_t GetMaxMarkTaskCount() const + { + return maxMarkTaskCount_; + } + + uint32_t GetMaxEvacuateTaskCount() const + { + return maxEvacuateTaskCount_; + } + ChunkMap *GetDerivedPointers() const { return derivedPointers_; @@ -481,18 +504,24 @@ private: bool parallelGC_ {true}; bool concurrentMarkingEnabled_ {true}; + bool disableConcurrentMarkRequested_ {false}; bool fullGCRequested_ {false}; size_t globalSpaceAllocLimit_ {0}; bool oldSpaceLimitAdjusted_ {false}; size_t promotedSize_ {0}; size_t semiSpaceCopiedSize_ {0}; + MemGrowingType memGrowingtype_ {MemGrowingType::HIGH_THROUGHPUT}; bool clearTaskFinished_ {true}; os::memory::Mutex waitClearTaskFinishedMutex_; os::memory::ConditionVariable waitClearTaskFinishedCV_; uint32_t runningTaskCount_ {0}; - uint32_t maxTaskCount_ {0}; + // parallel marker task number. + uint32_t maxMarkTaskCount_ {0}; + // parallel evacuator task number. + uint32_t initialEvacuateTaskCount_ {0}; + uint32_t maxEvacuateTaskCount_ {0}; os::memory::Mutex waitTaskFinishedMutex_; os::memory::ConditionVariable waitTaskFinishedCV_; diff --git a/ecmascript/mem/mem_controller.cpp b/ecmascript/mem/mem_controller.cpp index 965819f6e9..8bc7bf816e 100644 --- a/ecmascript/mem/mem_controller.cpp +++ b/ecmascript/mem/mem_controller.cpp @@ -39,8 +39,23 @@ double MemController::CalculateAllocLimit(size_t currentSize, size_t minSize, si double MemController::CalculateGrowingFactor(double gcSpeed, double mutatorSpeed) { - static constexpr double minGrowingFactor = 1.3; - static constexpr double maxGrowingFactor = 4.0; + double maxGrowingFactor = 4.0; + double halfMaxGrowingFactor = 2.0; + double minGrowingFactor = 1.3; + double minimumFactor = 1.1; + switch (heap_->GetMemGrowingType()) { + case MemGrowingType::HIGH_THROUGHPUT: + break; + case MemGrowingType::CONSERVATIVE: + minGrowingFactor = minimumFactor; + maxGrowingFactor = halfMaxGrowingFactor; + break; + case MemGrowingType::PRESSURE: + return minimumFactor; + default: + break; + } + static constexpr double targetMutatorUtilization = 0.97; if (gcSpeed == 0 || mutatorSpeed == 0) { return maxGrowingFactor; diff --git a/ecmascript/mem/parallel_evacuator-inl.h b/ecmascript/mem/parallel_evacuator-inl.h index 84c656be9c..080cb21614 100644 --- a/ecmascript/mem/parallel_evacuator-inl.h +++ b/ecmascript/mem/parallel_evacuator-inl.h @@ -120,7 +120,8 @@ int ParallelEvacuator::CalculateEvacuationThreadNum() { uint32_t length = workloads_.size(); uint32_t regionPerThread = 8; - uint32_t maxThreadNum = Taskpool::GetCurrentTaskpool()->GetTotalThreadNum(); + uint32_t maxThreadNum = std::min(heap_->GetMaxEvacuateTaskCount(), + Taskpool::GetCurrentTaskpool()->GetTotalThreadNum()); return static_cast(std::min(std::max(1U, length / regionPerThread), maxThreadNum)); } @@ -129,7 +130,8 @@ int ParallelEvacuator::CalculateUpdateThreadNum() uint32_t length = workloads_.size(); double regionPerThread = 1.0 / 4; length = std::pow(length, regionPerThread); - uint32_t maxThreadNum = Taskpool::GetCurrentTaskpool()->GetTotalThreadNum(); + uint32_t maxThreadNum = std::min(heap_->GetMaxEvacuateTaskCount(), + Taskpool::GetCurrentTaskpool()->GetTotalThreadNum()); return static_cast(std::min(std::max(1U, length), maxThreadNum)); } } // namespace panda::ecmascript diff --git a/ecmascript/napi/dfx_jsnapi.cpp b/ecmascript/napi/dfx_jsnapi.cpp index f1691c9144..ac5efd1a62 100644 --- a/ecmascript/napi/dfx_jsnapi.cpp +++ b/ecmascript/napi/dfx_jsnapi.cpp @@ -132,6 +132,15 @@ size_t DFXJSNApi::GetHeapUsedSize(const EcmaVM *vm) return vm->GetHeap()->GetHeapObjectSize(); } +void DFXJSNApi::NotifyApplicationState(EcmaVM *vm, bool inBackground) +{ + const_cast(vm->GetHeap())->ChangeGCParams(inBackground); +} + +void DFXJSNApi::NotifyMemoryPressure(EcmaVM *vm, bool inHighMemoryPressure) +{ + const_cast(vm->GetHeap())->NotifyMemoryPressure(inHighMemoryPressure); +} #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER) void DFXJSNApi::StartCpuProfilerForFile(const EcmaVM *vm, const std::string &fileName) { diff --git a/ecmascript/napi/include/dfx_jsnapi.h b/ecmascript/napi/include/dfx_jsnapi.h index cf8a1ae768..3c1d5e26b8 100644 --- a/ecmascript/napi/include/dfx_jsnapi.h +++ b/ecmascript/napi/include/dfx_jsnapi.h @@ -59,6 +59,8 @@ public: static size_t GetArrayBufferSize(const EcmaVM *vm); static size_t GetHeapTotalSize(const EcmaVM *vm); static size_t GetHeapUsedSize(const EcmaVM *vm); + static void NotifyApplicationState(EcmaVM *vm, bool inBackground); + static void NotifyMemoryPressure(EcmaVM *vm, bool inHighMemoryPressure); // profile generator #if defined(ECMASCRIPT_SUPPORT_CPUPROFILER) diff --git a/ecmascript/tests/gc_test.cpp b/ecmascript/tests/gc_test.cpp index 6f20bbe06b..6ad648f255 100644 --- a/ecmascript/tests/gc_test.cpp +++ b/ecmascript/tests/gc_test.cpp @@ -17,6 +17,7 @@ #include "ecmascript/mem/full_gc.h" #include "ecmascript/object_factory.h" #include "ecmascript/mem/stw_young_gc.h" +#include "ecmascript/mem/partial_gc.h" #include "ecmascript/tests/test_helper.h" using namespace panda; @@ -75,4 +76,62 @@ HWTEST_F_L0(GCTest, FullGCOne) auto oldSizeAfter = heap->GetOldSpace()->GetHeapObjectSize(); EXPECT_TRUE(oldSizeBefore > oldSizeAfter); } + +HWTEST_F_L0(GCTest, ChangeGCParams) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + EXPECT_EQ(heap->GetMemGrowingType(), MemGrowingType::HIGH_THROUGHPUT); + uint32_t markTaskNum = heap->GetMaxMarkTaskCount(); + uint32_t evacuateTaskNum = heap->GetMaxEvacuateTaskCount(); + + auto partialGc = heap->GetPartialGC(); + partialGc->RunPhases(); + heap->ChangeGCParams(true); + heap->Prepare(); + uint32_t markTaskNumBackground = heap->GetMaxMarkTaskCount(); + uint32_t evacuateTaskNumBackground = heap->GetMaxEvacuateTaskCount(); + EXPECT_TRUE(markTaskNum > markTaskNumBackground); + EXPECT_TRUE(evacuateTaskNum > evacuateTaskNumBackground); + EXPECT_EQ(heap->GetMemGrowingType(), MemGrowingType::CONSERVATIVE); + + partialGc->RunPhases(); + heap->ChangeGCParams(false); + heap->Prepare(); + uint32_t markTaskNumForeground = heap->GetMaxMarkTaskCount(); + uint32_t evacuateTaskNumForeground = heap->GetMaxEvacuateTaskCount(); + EXPECT_EQ(markTaskNum, markTaskNumForeground); + EXPECT_EQ(evacuateTaskNum, evacuateTaskNumForeground); + EXPECT_EQ(heap->GetMemGrowingType(), MemGrowingType::HIGH_THROUGHPUT); +} + +HWTEST_F_L0(GCTest, NotifyMemoryPressure) +{ + auto heap = const_cast(thread->GetEcmaVM()->GetHeap()); + EXPECT_EQ(heap->GetMemGrowingType(), MemGrowingType::HIGH_THROUGHPUT); + uint32_t markTaskNum = heap->GetMaxMarkTaskCount(); + uint32_t evacuateTaskNum = heap->GetMaxEvacuateTaskCount(); + + auto partialGc = heap->GetPartialGC(); + partialGc->RunPhases(); + heap->ChangeGCParams(true); + heap->NotifyMemoryPressure(true); + heap->Prepare(); + uint32_t markTaskNumBackground = heap->GetMaxMarkTaskCount(); + uint32_t evacuateTaskNumBackground = heap->GetMaxEvacuateTaskCount(); + EXPECT_TRUE(markTaskNum > markTaskNumBackground); + EXPECT_TRUE(evacuateTaskNum > evacuateTaskNumBackground); + EXPECT_EQ(heap->GetMemGrowingType(), MemGrowingType::PRESSURE); + + partialGc->RunPhases(); + heap->ChangeGCParams(false); + heap->Prepare(); + uint32_t markTaskNumForeground = heap->GetMaxMarkTaskCount(); + uint32_t evacuateTaskNumForeground = heap->GetMaxEvacuateTaskCount(); + EXPECT_EQ(markTaskNum, markTaskNumForeground); + EXPECT_EQ(evacuateTaskNum, evacuateTaskNumForeground); + EXPECT_EQ(heap->GetMemGrowingType(), MemGrowingType::PRESSURE); + + heap->NotifyMemoryPressure(false); + EXPECT_EQ(heap->GetMemGrowingType(), MemGrowingType::CONSERVATIVE); +} } // namespace panda::test From 397cd9279df2e8d257460231c72a5df1558bebfd Mon Sep 17 00:00:00 2001 From: Rtangyu Date: Tue, 7 Jun 2022 14:33:17 +0800 Subject: [PATCH 31/35] JS stack printing supports native method pointer printing Implement JS stack printing and support native method pointer printing issue:https://gitee.com/openharmony/arkui_napi/issues/I5AOZC Signed-off-by: Rtangyu --- ecmascript/base/error_helper.cpp | 36 +++++++++++++++--------- ecmascript/base/error_helper.h | 4 +-- ecmascript/interpreter/frame_handler.cpp | 10 +++++++ ecmascript/interpreter/frame_handler.h | 1 + ecmascript/napi/dfx_jsnapi.cpp | 16 +++++++++-- ecmascript/napi/include/dfx_jsnapi.h | 3 +- 6 files changed, 49 insertions(+), 21 deletions(-) diff --git a/ecmascript/base/error_helper.cpp b/ecmascript/base/error_helper.cpp index 56770f6c66..2ce134ed87 100644 --- a/ecmascript/base/error_helper.cpp +++ b/ecmascript/base/error_helper.cpp @@ -182,23 +182,26 @@ CString ErrorHelper::DecodeFunctionName(const CString &name) JSHandle ErrorHelper::BuildEcmaStackTrace(JSThread *thread) { - CString data = BuildNativeAndJsStackTrace(thread); + CString data = BuildJsStackTrace(thread, false); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); LOG(DEBUG, ECMASCRIPT) << data; return factory->NewFromUtf8(data); } -CString ErrorHelper::BuildNativeEcmaStackTrace(JSThread *thread) +CString ErrorHelper::BuildJsStackTrace(JSThread *thread, bool needNative) { CString data; CString fristLineSrcCode; bool isFirstLine = true; FrameHandler frameHandler(thread); for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) { - if (frameHandler.IsEntryFrame()) { + if (!frameHandler.IsInterpretedFrame()) { + continue; + } + auto method = frameHandler.CheckAndGetMethod(); + if (method == nullptr) { continue; } - auto method = frameHandler.GetMethod(); if (!method->IsNativeWithCallField()) { data.append(" at "); data += DecodeFunctionName(method->ParseFunctionName()); @@ -239,6 +242,15 @@ CString ErrorHelper::BuildNativeEcmaStackTrace(JSThread *thread) fristLineSrcCode = StringHelper::GetSpecifiedLine(sourceCode, lineNumber); isFirstLine = false; } + } else if (needNative) { + data.append(" at native method"); + data.append(" ("); + auto addr = method->GetNativePointer(); + std::stringstream strm; + strm << addr; + data.append(strm.str()); + data.push_back(')'); + data.push_back('\n'); } } if (!fristLineSrcCode.empty()) { @@ -246,17 +258,13 @@ CString ErrorHelper::BuildNativeEcmaStackTrace(JSThread *thread) if (fristLineSrcCode[codeLen - 1] == '\r') { fristLineSrcCode = fristLineSrcCode.substr(0, codeLen - 1); } - fristLineSrcCode = "SourceCode (" + fristLineSrcCode; - fristLineSrcCode.push_back(')'); - fristLineSrcCode.push_back('\n'); - data = fristLineSrcCode + data; + if (fristLineSrcCode != "ANDA") { + fristLineSrcCode = "SourceCode (" + fristLineSrcCode; + fristLineSrcCode.push_back(')'); + fristLineSrcCode.push_back('\n'); + data = fristLineSrcCode + data; + } } return data; } - -CString ErrorHelper::BuildNativeAndJsStackTrace(JSThread *thread) -{ - CString data = BuildNativeEcmaStackTrace(thread); - return data; -} } // namespace panda::ecmascript::base diff --git a/ecmascript/base/error_helper.h b/ecmascript/base/error_helper.h index 27beef773f..f262152ff0 100644 --- a/ecmascript/base/error_helper.h +++ b/ecmascript/base/error_helper.h @@ -31,9 +31,7 @@ public: static JSTaggedValue ErrorCommonConstructor(EcmaRuntimeCallInfo *argv, const ErrorType &errorType); - static CString BuildNativeEcmaStackTrace(JSThread *thread); - - static CString BuildNativeAndJsStackTrace(JSThread *thread); + static CString BuildJsStackTrace(JSThread *thread, bool needNative); private: static CString DecodeFunctionName(const CString &name); diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index 8eff24124f..764cc8214f 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -234,6 +234,16 @@ JSMethod *FrameHandler::GetMethod() const return ECMAObject::Cast(function.GetTaggedObject())->GetCallTarget(); } +JSMethod *FrameHandler::CheckAndGetMethod() const +{ + ASSERT(IsInterpretedFrame()); + auto function = GetFunction(); + if (function.IsJSFunctionBase() || function.IsJSProxy()) { + return ECMAObject::Cast(function.GetTaggedObject())->GetCallTarget(); + } + return nullptr; +} + JSTaggedValue FrameHandler::GetFunction() const { ASSERT(IsInterpretedFrame()); diff --git a/ecmascript/interpreter/frame_handler.h b/ecmascript/interpreter/frame_handler.h index ff6dc64497..8d31fbe7a0 100644 --- a/ecmascript/interpreter/frame_handler.h +++ b/ecmascript/interpreter/frame_handler.h @@ -126,6 +126,7 @@ public: uint32_t GetNumberArgs(); uint32_t GetBytecodeOffset() const; JSMethod *GetMethod() const; + JSMethod *CheckAndGetMethod() const; JSTaggedValue GetFunction() const; const uint8_t *GetPc() const; ConstantPool *GetConstpool() const; diff --git a/ecmascript/napi/dfx_jsnapi.cpp b/ecmascript/napi/dfx_jsnapi.cpp index d1c583487e..dd00a41979 100644 --- a/ecmascript/napi/dfx_jsnapi.cpp +++ b/ecmascript/napi/dfx_jsnapi.cpp @@ -72,11 +72,21 @@ void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unus #endif } -bool DFXJSNApi::BuildNativeAndJsBackStackTrace(const EcmaVM *vm, std::string &stackTraceStr) +bool DFXJSNApi::BuildNativeAndJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr) { - CString trace = ecmascript::base::ErrorHelper::BuildNativeAndJsStackTrace(vm->GetJSThreadNoCheck()); + CString trace = ecmascript::base::ErrorHelper::BuildJsStackTrace(vm->GetJSThreadNoCheck(), true); stackTraceStr = CstringConvertToStdString(trace); - if (stackTraceStr == "") { + if (stackTraceStr.empty()) { + return false; + } + return true; +} + +bool DFXJSNApi::BuildJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr) +{ + CString trace = ecmascript::base::ErrorHelper::BuildJsStackTrace(vm->GetJSThreadNoCheck(), false); + stackTraceStr = CstringConvertToStdString(trace); + if (stackTraceStr.empty()) { return false; } return true; diff --git a/ecmascript/napi/include/dfx_jsnapi.h b/ecmascript/napi/include/dfx_jsnapi.h index e2ef5a22ca..1f84f6a898 100644 --- a/ecmascript/napi/include/dfx_jsnapi.h +++ b/ecmascript/napi/include/dfx_jsnapi.h @@ -49,7 +49,8 @@ public: bool isVmMode = true, bool isPrivate = false); static void DumpHeapSnapshot(const EcmaVM *vm, int dumpFormat, bool isVmMode = true, bool isPrivate = false); - static bool BuildNativeAndJsBackStackTrace(const EcmaVM *vm, std::string &stackTraceStr); + static bool BuildNativeAndJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr); + static bool BuildJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr); static bool StartHeapTracking(const EcmaVM *vm, double timeInterval, bool isVmMode = true, Stream *stream = nullptr); static bool StopHeapTracking(const EcmaVM *vm, const std::string &filePath); From a229ee99279e6ab5f5f2e595f9afefa540ee627c Mon Sep 17 00:00:00 2001 From: songzhengchao Date: Tue, 7 Jun 2022 14:39:13 +0800 Subject: [PATCH 32/35] Revert "debug" This reverts commit 4e5c0d0ae9ebdc6a765a4c6d5134ea0167485762. Signed-off-by: songzhengchao Change-Id: Iafb4e81981e7b3eef79672684aa4dfc8e75f791a --- ecmascript/compiler/BUILD.gn | 40 +++++-------------- .../compiler/llvm/llvm_stackmap_parser.cpp | 6 --- ecmascript/compiler/llvm_ir_builder.cpp | 2 - ecmascript/compiler/tests/BUILD.gn | 33 ++++----------- ecmascript/interpreter/frame_handler.cpp | 5 +-- js_runtime_config.gni | 1 - 6 files changed, 19 insertions(+), 68 deletions(-) diff --git a/ecmascript/compiler/BUILD.gn b/ecmascript/compiler/BUILD.gn index cec5592f0e..b2fc7ce53b 100644 --- a/ecmascript/compiler/BUILD.gn +++ b/ecmascript/compiler/BUILD.gn @@ -27,18 +27,10 @@ if (defined(ark_independent_build)) { config("include_llvm") { if (compile_llvm_online) { - if (compiler_llvm_12) { - include_dirs = [ - "//third_party/third_party_llvm-project/build/include", - "//third_party/third_party_llvm-project/llvm/include/", - ] - } else { - include_dirs = [ - "//third_party/llvm-project/build/include", - "//third_party/llvm-project/llvm/include/", - ] - } - + include_dirs = [ + "//third_party/third_party_llvm-project/build/include", + "//third_party/third_party_llvm-project/llvm/include/", + ] } else { include_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/llvm/include", @@ -86,11 +78,7 @@ source_set("libark_jsoptimizer_set") { ] if (compile_llvm_online) { - if (compiler_llvm_12) { - lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] - } else { - lib_dirs = [ "//third_party/llvm-project/build/lib" ] - } + lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] } else { lib_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/build/lib" ] @@ -154,26 +142,18 @@ source_set("libark_jsoptimizer_set") { "LLVMX86Desc", "LLVMX86Disassembler", "LLVMX86Info", + "LLVMFrontendOpenMP", + "LLVMBitWriter", ] - if (compile_llvm_online && compiler_llvm_12) { - libs += [ - "LLVMX86Utils", - ] - } else { - libs += [ - "LLVMFrontendOpenMP", - "LLVMBitWriter", - ] - } deps = [ "$ark_root/libpandabase:libarkbase", "$ark_root/libpandafile:libarkfile", ] - #if (compile_llvm_online) { - # deps += [ ":build_llvm_libs" ] - #} + if (compile_llvm_online) { + deps += [ ":build_llvm_libs" ] + } } source_set("ark_stub_compiler_set") { diff --git a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp index ad4a22897a..7a572a2bab 100644 --- a/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp +++ b/ecmascript/compiler/llvm/llvm_stackmap_parser.cpp @@ -149,12 +149,6 @@ bool LLVMStackMapParser::CollectStackMapSlots(uintptr_t callSiteAddr, uintptr_t uintptr_t *fp = reinterpret_cast(frameFp); uintptr_t callsiteFp = *fp; uintptr_t callSiteSp = FrameHandler::GetPrevFrameCallSiteSp(reinterpret_cast(frameFp), curPc); - // std::cout << std::hex << " callSiteAddr:0x" << callSiteAddr << " curPc:0x" << curPc - // << " callsiteFp:0x" << callsiteFp - // << " callSiteSp:0x" << callSiteSp - // << " stack size:0x" << (callsiteFp- callSiteSp) - // << std::endl; - ASSERT(callsiteFp - callSiteSp >= 8); uintptr_t address = 0; uintptr_t base = 0; uintptr_t derived = 0; diff --git a/ecmascript/compiler/llvm_ir_builder.cpp b/ecmascript/compiler/llvm_ir_builder.cpp index f07cca926d..8dd878d109 100644 --- a/ecmascript/compiler/llvm_ir_builder.cpp +++ b/ecmascript/compiler/llvm_ir_builder.cpp @@ -375,12 +375,10 @@ void LLVMIRBuilder::GenPrologue([[maybe_unused]] LLVMModuleRef &module, LLVMBuil if (frameType == panda::ecmascript::FrameType::OPTIMIZED_FRAME) { LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); - LLVMAddTargetDependentFunctionAttr(function_, "js-stub-call", "0"); } else if (frameType == panda::ecmascript::FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { reservedSlotsSize = slotSize_ * static_cast(ReservedSlots::OPTIMIZED_JS_FUNCTION_RESERVED_SLOT); LLVMAddTargetDependentFunctionAttr(function_, "frame-reserved-slots", std::to_string(reservedSlotsSize).c_str()); - LLVMAddTargetDependentFunctionAttr(function_, "js-stub-call", "1"); } else { COMPILER_OPTIONAL_LOG(FATAL) << "frameType interpret type error !"; ASSERT_PRINT(static_cast(frameType), "is not support !"); diff --git a/ecmascript/compiler/tests/BUILD.gn b/ecmascript/compiler/tests/BUILD.gn index cf05663d05..42a8c571fc 100644 --- a/ecmascript/compiler/tests/BUILD.gn +++ b/ecmascript/compiler/tests/BUILD.gn @@ -17,17 +17,10 @@ import("//build/test.gni") config("include_llvm_config") { if (compile_llvm_online) { - if (compiler_llvm_12) { - include_dirs = [ - "//third_party/third_party_llvm-project/build/include", - "//third_party/third_party_llvm-project/llvm/include/", - ] - } else { - include_dirs = [ - "//third_party/llvm-project/build/include", - "//third_party/llvm-project/llvm/include/", - ] - } + include_dirs = [ + "//third_party/third_party_llvm-project/build/include", + "//third_party/third_party_llvm-project/llvm/include/", + ] } else { include_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/llvm/include", @@ -53,11 +46,7 @@ host_unittest_action("StubTest") { ] if (compile_llvm_online) { - if (compiler_llvm_12) { - lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] - } else { - lib_dirs = [ "//third_party/llvm-project/build/lib" ] - } + lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] } else { lib_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/build/lib" ] @@ -146,11 +135,7 @@ host_unittest_action("AssemblerTest") { ] if (compile_llvm_online) { - if (compiler_llvm_12) { - lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] - } else { - lib_dirs = [ "//third_party/llvm-project/build/lib" ] - } + lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] } else { lib_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/build/lib" ] @@ -238,11 +223,7 @@ host_unittest_action("CircuitOptimizerTest") { ] if (compile_llvm_online) { - if (compiler_llvm_12) { - lib_dirs = [ "//third_party/third_party_llvm-project/build/lib" ] - } else { - lib_dirs = [ "//third_party/llvm-project/build/lib" ] - } + lib_dirs = [ "//third_party/llvm-project/build/lib" ] } else { lib_dirs = [ "//prebuilts/ark_tools/ark_js_prebuilts/llvm_prebuilts/build/lib" ] diff --git a/ecmascript/interpreter/frame_handler.cpp b/ecmascript/interpreter/frame_handler.cpp index 3a44ae4e3a..5cc3242f5b 100644 --- a/ecmascript/interpreter/frame_handler.cpp +++ b/ecmascript/interpreter/frame_handler.cpp @@ -583,7 +583,6 @@ ARK_INLINE void FrameHandler::OptimizedLeaveFrameIterate(const JSTaggedType *sp, ChunkMap *derivedPointers, bool isVerifying) { - // std::cout << __FUNCTION__ << " " << std::dec << __LINE__ << " " << std::hex << " sp:0x" << sp << std::endl; OptimizedLeaveFrame *frame = OptimizedLeaveFrame::GetFrameFromSp(sp); if (frame->argc > 0) { JSTaggedType *argv = reinterpret_cast(&frame->argc + 1); @@ -594,7 +593,8 @@ ARK_INLINE void FrameHandler::OptimizedLeaveFrameIterate(const JSTaggedType *sp, std::set slotAddrs; bool ret = kungfu::LLVMStackMapParser::GetInstance().CollectStackMapSlots( - frame->returnAddr, reinterpret_cast(sp), slotAddrs, derivedPointers, isVerifying, optimizedReturnAddr_); + frame->returnAddr, reinterpret_cast(sp), slotAddrs, + derivedPointers, isVerifying, optimizedReturnAddr_); if (!ret) { return; } @@ -732,7 +732,6 @@ void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &v0, } case FrameType::LEAVE_FRAME: { auto frame = OptimizedLeaveFrame::GetFrameFromSp(current); - //std::cout << __FUNCTION__ << " " << std::dec << __LINE__ << " " << std::hex << " sp:0x" << current << std::endl; OptimizedLeaveFrameIterate(current, v0, v1, derivedPointers, isVerifying); current = frame->GetPrevFrameFp(); optimizedReturnAddr_ = frame->returnAddr; diff --git a/js_runtime_config.gni b/js_runtime_config.gni index ef0f9d4b76..440bc34410 100644 --- a/js_runtime_config.gni +++ b/js_runtime_config.gni @@ -21,7 +21,6 @@ if (!defined(ark_independent_build)) { third_party_gn_path = "$build_root/third_party_gn" } compile_llvm_online = false -compiler_llvm_12 = true run_with_asan = false enable_bytrace = true enable_dump_in_faultlog = true From de388d8f61af996a9a91f8fb6e13540dfffd0a5f Mon Sep 17 00:00:00 2001 From: wengchangcheng Date: Mon, 6 Jun 2022 23:34:43 +0800 Subject: [PATCH 33/35] Descriptor: debugger refactor of independent js_runtime [ part-1 ] details: using stl instead of js_runtime container ans string issue: https://gitee.com/openharmony/ark_js_runtime/issues/I5AYKS Signed-off-by: wengchangcheng Change-Id: I32b4809a4bbd759a562326a59e0cfb0e8e728297 --- ecmascript/base/error_helper.cpp | 18 +- ecmascript/base/error_helper.h | 4 +- ecmascript/base/string_helper.h | 8 +- ecmascript/dfx/cpu_profiler/cpu_profiler.cpp | 8 +- ecmascript/js_function.cpp | 4 +- ecmascript/js_method.cpp | 6 +- ecmascript/js_method.h | 2 +- .../jspandafile/class_info_extractor.cpp | 8 +- .../jspandafile/debug_info_extractor.cpp | 10 +- ecmascript/jspandafile/debug_info_extractor.h | 16 +- ecmascript/napi/dfx_jsnapi.cpp | 6 +- ecmascript/tooling/agent/debugger_impl.cpp | 86 +-- ecmascript/tooling/agent/debugger_impl.h | 34 +- .../tooling/agent/heapprofiler_impl.cpp | 8 +- ecmascript/tooling/agent/profiler_impl.cpp | 4 +- ecmascript/tooling/agent/runtime_impl.cpp | 26 +- ecmascript/tooling/agent/runtime_impl.h | 16 +- ecmascript/tooling/backend/debugger_api.cpp | 16 +- ecmascript/tooling/backend/debugger_api.h | 8 +- .../tooling/backend/js_pt_extractor.cpp | 8 +- ecmascript/tooling/backend/js_pt_extractor.h | 6 +- ecmascript/tooling/base/pt_events.h | 152 ++--- ecmascript/tooling/base/pt_params.cpp | 70 +- ecmascript/tooling/base/pt_params.h | 52 +- ecmascript/tooling/base/pt_returns.cpp | 2 +- ecmascript/tooling/base/pt_returns.h | 60 +- ecmascript/tooling/base/pt_script.cpp | 2 +- ecmascript/tooling/base/pt_script.h | 32 +- ecmascript/tooling/base/pt_types.cpp | 296 ++++---- ecmascript/tooling/base/pt_types.h | 438 ++++++------ ecmascript/tooling/debugger_service.cpp | 2 +- ecmascript/tooling/dispatcher.cpp | 18 +- ecmascript/tooling/dispatcher.h | 26 +- ecmascript/tooling/interface/file_stream.cpp | 3 +- ecmascript/tooling/protocol_handler.cpp | 2 +- ecmascript/tooling/protocol_handler.h | 2 +- .../tooling/test/debugger_entry_test.cpp | 2 +- .../tooling/test/debugger_events_test.cpp | 73 +- .../tooling/test/debugger_params_test.cpp | 168 ++--- .../tooling/test/debugger_returns_test.cpp | 34 +- .../tooling/test/debugger_types_test.cpp | 643 +++++++++--------- ecmascript/tooling/test/utils/test_entry.cpp | 2 +- ecmascript/tooling/test/utils/test_events.h | 2 +- .../tooling/test/utils/test_extractor.h | 2 +- ecmascript/tooling/test/utils/test_hooks.h | 4 +- ecmascript/tooling/test/utils/test_util.h | 6 +- .../testcases/js_breakpoint_arrow_test.h | 6 +- .../testcases/js_breakpoint_async_test.h | 6 +- .../test/utils/testcases/js_breakpoint_test.h | 6 +- .../test/utils/testcases/js_exception_test.h | 10 +- .../utils/testcases/js_single_step_test.h | 6 +- .../test/utils/testcases/test_list.cpp | 12 +- .../tooling/test/utils/testcases/test_list.h | 8 +- 53 files changed, 1210 insertions(+), 1239 deletions(-) diff --git a/ecmascript/base/error_helper.cpp b/ecmascript/base/error_helper.cpp index 2ce134ed87..6e0faefa48 100644 --- a/ecmascript/base/error_helper.cpp +++ b/ecmascript/base/error_helper.cpp @@ -172,7 +172,7 @@ JSTaggedValue ErrorHelper::ErrorCommonConstructor(EcmaRuntimeCallInfo *argv, return nativeInstanceObj.GetTaggedValue(); } -CString ErrorHelper::DecodeFunctionName(const CString &name) +std::string ErrorHelper::DecodeFunctionName(const std::string &name) { if (name.empty()) { return "anonymous"; @@ -182,16 +182,16 @@ CString ErrorHelper::DecodeFunctionName(const CString &name) JSHandle ErrorHelper::BuildEcmaStackTrace(JSThread *thread) { - CString data = BuildJsStackTrace(thread, false); + std::string data = BuildJsStackTrace(thread, false); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); LOG(DEBUG, ECMASCRIPT) << data; - return factory->NewFromUtf8(data); + return factory->NewFromStdString(data); } -CString ErrorHelper::BuildJsStackTrace(JSThread *thread, bool needNative) +std::string ErrorHelper::BuildJsStackTrace(JSThread *thread, bool needNative) { - CString data; - CString fristLineSrcCode; + std::string data; + std::string fristLineSrcCode; bool isFirstLine = true; FrameHandler frameHandler(thread); for (; frameHandler.HasFrame(); frameHandler.PrevInterpretedFrame()) { @@ -204,12 +204,12 @@ CString ErrorHelper::BuildJsStackTrace(JSThread *thread, bool needNative) } if (!method->IsNativeWithCallField()) { data.append(" at "); - data += DecodeFunctionName(method->ParseFunctionName()); + data += DecodeFunctionName(method->ParseFunctionName().c_str()); data.append(" ("); // source file tooling::JSPtExtractor *debugExtractor = JSPandaFileManager::GetInstance()->GetJSPtExtractor(method->GetJSPandaFile()); - const CString &sourceFile = debugExtractor->GetSourceFile(method->GetMethodId()); + const std::string &sourceFile = debugExtractor->GetSourceFile(method->GetMethodId()); if (sourceFile.empty()) { data.push_back('?'); } else { @@ -237,7 +237,7 @@ CString ErrorHelper::BuildJsStackTrace(JSThread *thread, bool needNative) data.push_back(')'); data.push_back('\n'); if (isFirstLine) { - const CString &sourceCode = debugExtractor->GetSourceCode( + const std::string &sourceCode = debugExtractor->GetSourceCode( panda_file::File::EntityId(method->GetJSPandaFile()->GetMainMethodIndex())); fristLineSrcCode = StringHelper::GetSpecifiedLine(sourceCode, lineNumber); isFirstLine = false; diff --git a/ecmascript/base/error_helper.h b/ecmascript/base/error_helper.h index f262152ff0..cde0d80a3f 100644 --- a/ecmascript/base/error_helper.h +++ b/ecmascript/base/error_helper.h @@ -31,10 +31,10 @@ public: static JSTaggedValue ErrorCommonConstructor(EcmaRuntimeCallInfo *argv, const ErrorType &errorType); - static CString BuildJsStackTrace(JSThread *thread, bool needNative); + static std::string BuildJsStackTrace(JSThread *thread, bool needNative); private: - static CString DecodeFunctionName(const CString &name); + static std::string DecodeFunctionName(const std::string &name); static JSHandle BuildEcmaStackTrace(JSThread *thread); diff --git a/ecmascript/base/string_helper.h b/ecmascript/base/string_helper.h index bee9d4e73e..b12404b061 100644 --- a/ecmascript/base/string_helper.h +++ b/ecmascript/base/string_helper.h @@ -201,16 +201,16 @@ public: return res; } - static inline CString GetSpecifiedLine(const CString &srcStr, int lineNumber) + static inline std::string GetSpecifiedLine(const std::string &srcStr, int lineNumber) { - std::stringstream ss(CstringConvertToStdString(srcStr)); + std::stringstream ss(srcStr); int count = 0; - CString lineStr = ""; + std::string lineStr = ""; std::string tempLine; while (getline(ss, tempLine, '\n')) { count++; if (count == lineNumber) { - lineStr = ConvertToString(tempLine); + lineStr = tempLine; break; } } diff --git a/ecmascript/dfx/cpu_profiler/cpu_profiler.cpp b/ecmascript/dfx/cpu_profiler/cpu_profiler.cpp index d894de9152..e7237a686f 100644 --- a/ecmascript/dfx/cpu_profiler/cpu_profiler.cpp +++ b/ecmascript/dfx/cpu_profiler/cpu_profiler.cpp @@ -278,20 +278,20 @@ void CpuProfiler::ParseMethodInfo(JSMethod *method, FrameHandler frameHandler) staticStackInfo_.insert(std::make_pair(method, codeEntry)); } else if (method != nullptr) { codeEntry.codeType = "JS"; - const CString &functionName = method->ParseFunctionName(); + const std::string &functionName = method->ParseFunctionName(); if (functionName.empty()) { codeEntry.functionName = "anonymous"; } else { - codeEntry.functionName = functionName.c_str(); + codeEntry.functionName = functionName; } // source file tooling::JSPtExtractor *debugExtractor = JSPandaFileManager::GetInstance()->GetJSPtExtractor(method->GetJSPandaFile()); - const CString &sourceFile = debugExtractor->GetSourceFile(method->GetMethodId()); + const std::string &sourceFile = debugExtractor->GetSourceFile(method->GetMethodId()); if (sourceFile.empty()) { codeEntry.url = ""; } else { - codeEntry.url = sourceFile.c_str(); + codeEntry.url = sourceFile; auto iter = scriptIdMap_.find(codeEntry.url); if (iter == scriptIdMap_.end()) { scriptIdMap_.insert(std::make_pair(codeEntry.url, scriptIdMap_.size() + 1)); diff --git a/ecmascript/js_function.cpp b/ecmascript/js_function.cpp index 7a8e90340c..8f3db64acf 100644 --- a/ecmascript/js_function.cpp +++ b/ecmascript/js_function.cpp @@ -145,7 +145,7 @@ JSTaggedValue JSFunction::NameGetter(JSThread *thread, const JSHandle if (target->GetPandaFile() == nullptr) { return JSTaggedValue::Undefined(); } - CString funcName = target->ParseFunctionName(); + std::string funcName = target->ParseFunctionName(); if (funcName.empty()) { return thread->GlobalConstants()->GetEmptyString(); } @@ -157,7 +157,7 @@ JSTaggedValue JSFunction::NameGetter(JSThread *thread, const JSHandle } ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - return factory->NewFromUtf8(funcName).GetTaggedValue(); + return factory->NewFromStdString(funcName).GetTaggedValue(); } bool JSFunction::OrdinaryHasInstance(JSThread *thread, const JSHandle &constructor, diff --git a/ecmascript/js_method.cpp b/ecmascript/js_method.cpp index bcbcb1c928..76f239f593 100644 --- a/ecmascript/js_method.cpp +++ b/ecmascript/js_method.cpp @@ -38,14 +38,14 @@ JSMethod::JSMethod(const JSPandaFile *jsPandaFile, panda_file::File::EntityId me } // It's not allowed '#' token appear in ECMA function(method) name, which discriminates same names in panda methods. -CString JSMethod::ParseFunctionName() const +std::string JSMethod::ParseFunctionName() const { - CString methodName(utf::Mutf8AsCString(GetName().data)); + std::string methodName(utf::Mutf8AsCString(GetName().data)); if (LIKELY(methodName[0] != '#')) { return methodName; } size_t index = methodName.find_last_of('#'); - return CString(methodName.substr(index + 1)); + return methodName.substr(index + 1); } void JSMethod::InitializeCallField(uint32_t numVregs, uint32_t numArgs) diff --git a/ecmascript/js_method.h b/ecmascript/js_method.h index 165f2f125a..e1c84ca3eb 100644 --- a/ecmascript/js_method.h +++ b/ecmascript/js_method.h @@ -100,7 +100,7 @@ struct PUBLIC_API JSMethod : public base::AlignedStructGetConstructorMethod()->ParseFunctionName(); - JSHandle clsNameHandle = factory->NewFromUtf8(clsName); + std::string clsName = extractor->GetConstructorMethod()->ParseFunctionName(); + JSHandle clsNameHandle = factory->NewFromStdString(clsName); staticProperties->Set(thread, NAME_INDEX, clsNameHandle); } @@ -150,8 +150,8 @@ bool ClassInfoExtractor::ExtractAndReturnWhetherWithElements(JSThread *thread, c if (LIKELY(!keysHasNameFlag)) { [[maybe_unused]] EcmaHandleScope handleScope(thread); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - CString clsName = detail.ctorMethod->ParseFunctionName(); - JSHandle clsNameHandle = factory->NewFromUtf8(clsName); + std::string clsName = detail.ctorMethod->ParseFunctionName(); + JSHandle clsNameHandle = factory->NewFromStdString(clsName); properties->Set(thread, NAME_INDEX, clsNameHandle); } else { // class has static name property, reserved length bigger 1 than actual, need trim diff --git a/ecmascript/jspandafile/debug_info_extractor.cpp b/ecmascript/jspandafile/debug_info_extractor.cpp index 2c134b96ae..edf18e932c 100644 --- a/ecmascript/jspandafile/debug_info_extractor.cpp +++ b/ecmascript/jspandafile/debug_info_extractor.cpp @@ -32,7 +32,7 @@ using panda::panda_file::ProtoDataAccessor; static const char *GetStringFromConstantPool(const panda_file::File &pf, uint32_t offset) { - return utf::Mutf8AsCString(pf.GetStringData(panda_file::File::EntityId(offset)).data); + return reinterpret_cast(pf.GetStringData(panda_file::File::EntityId(offset)).data); } DebugInfoExtractor::DebugInfoExtractor(const JSPandaFile *jsPandaFile) @@ -196,8 +196,8 @@ void DebugInfoExtractor::Extract(const panda_file::File *pf) programProcessor.Process(); panda_file::File::EntityId methodId = mda.GetMethodId(); - const char *sourceFile = utf::Mutf8AsCString(handler.GetFile()); - const char *sourceCode = utf::Mutf8AsCString(handler.GetSourceCode()); + const char *sourceFile = reinterpret_cast(handler.GetFile()); + const char *sourceCode = reinterpret_cast(handler.GetSourceCode()); methods_.insert(std::make_pair(methodId.GetOffset(), MethodDebugInfo {sourceFile, sourceCode, handler.GetLineNumberTable(), handler.GetColumnNumberTable(), @@ -239,7 +239,7 @@ const LocalVariableTable &DebugInfoExtractor::GetLocalVariableTable(panda_file:: return iter->second.localVariableTable; } -const CString &DebugInfoExtractor::GetSourceFile(panda_file::File::EntityId methodId) const +const std::string &DebugInfoExtractor::GetSourceFile(panda_file::File::EntityId methodId) const { auto iter = methods_.find(methodId.GetOffset()); if (iter == methods_.end()) { @@ -248,7 +248,7 @@ const CString &DebugInfoExtractor::GetSourceFile(panda_file::File::EntityId meth return iter->second.sourceFile; } -const CString &DebugInfoExtractor::GetSourceCode(panda_file::File::EntityId methodId) const +const std::string &DebugInfoExtractor::GetSourceCode(panda_file::File::EntityId methodId) const { auto iter = methods_.find(methodId.GetOffset()); if (iter == methods_.end()) { diff --git a/ecmascript/jspandafile/debug_info_extractor.h b/ecmascript/jspandafile/debug_info_extractor.h index fb82247fa5..ab67fa796c 100644 --- a/ecmascript/jspandafile/debug_info_extractor.h +++ b/ecmascript/jspandafile/debug_info_extractor.h @@ -49,14 +49,14 @@ using ColumnNumberTable = CVector; /* * LocalVariableInfo define in frontend, now only use name and regNumber: - * CString name - * CString type - * CString typeSignature + * std::string name + * std::string type + * std::string typeSignature * int32_t regNumber * uint32_t startOffset * uint32_t endOffset */ -using LocalVariableTable = CUnorderedMap; // name, regNumber +using LocalVariableTable = CUnorderedMap; // name, regNumber // public for debugger class PUBLIC_API DebugInfoExtractor { @@ -74,9 +74,9 @@ public: const LocalVariableTable &GetLocalVariableTable(panda_file::File::EntityId methodId) const; - const CString &GetSourceFile(panda_file::File::EntityId methodId) const; + const std::string &GetSourceFile(panda_file::File::EntityId methodId) const; - const CString &GetSourceCode(panda_file::File::EntityId methodId) const; + const std::string &GetSourceCode(panda_file::File::EntityId methodId) const; CVector GetMethodIdList() const; @@ -84,8 +84,8 @@ private: void Extract(const panda_file::File *pf); struct MethodDebugInfo { - CString sourceFile; - CString sourceCode; + std::string sourceFile; + std::string sourceCode; LineNumberTable lineNumberTable; ColumnNumberTable columnNumberTable; LocalVariableTable localVariableTable; diff --git a/ecmascript/napi/dfx_jsnapi.cpp b/ecmascript/napi/dfx_jsnapi.cpp index cd3016c168..31efbb038b 100644 --- a/ecmascript/napi/dfx_jsnapi.cpp +++ b/ecmascript/napi/dfx_jsnapi.cpp @@ -74,8 +74,7 @@ void DFXJSNApi::DumpHeapSnapshot([[maybe_unused]] const EcmaVM *vm, [[maybe_unus bool DFXJSNApi::BuildNativeAndJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr) { - CString trace = ecmascript::base::ErrorHelper::BuildJsStackTrace(vm->GetJSThreadNoCheck(), true); - stackTraceStr = CstringConvertToStdString(trace); + stackTraceStr = ecmascript::base::ErrorHelper::BuildJsStackTrace(vm->GetJSThreadNoCheck(), true); if (stackTraceStr.empty()) { return false; } @@ -84,8 +83,7 @@ bool DFXJSNApi::BuildNativeAndJsStackTrace(const EcmaVM *vm, std::string &stackT bool DFXJSNApi::BuildJsStackTrace(const EcmaVM *vm, std::string &stackTraceStr) { - CString trace = ecmascript::base::ErrorHelper::BuildJsStackTrace(vm->GetJSThreadNoCheck(), false); - stackTraceStr = CstringConvertToStdString(trace); + stackTraceStr = ecmascript::base::ErrorHelper::BuildJsStackTrace(vm->GetJSThreadNoCheck(), false); if (stackTraceStr.empty()) { return false; } diff --git a/ecmascript/tooling/agent/debugger_impl.cpp b/ecmascript/tooling/agent/debugger_impl.cpp index 266f31ef68..9c33f2c143 100644 --- a/ecmascript/tooling/agent/debugger_impl.cpp +++ b/ecmascript/tooling/agent/debugger_impl.cpp @@ -37,9 +37,9 @@ using ObjectSubType = RemoteObject::SubTypeName; using ObjectClassName = RemoteObject::ClassName; #ifdef DEBUGGER_TEST -const CString DATA_APP_PATH = "/"; +const std::string DATA_APP_PATH = "/"; #else -const CString DATA_APP_PATH = "/data/"; +const std::string DATA_APP_PATH = "/data/"; #endif DebuggerImpl::DebuggerImpl(const EcmaVM *vm, ProtocolChannel *channel, RuntimeImpl *runtime) @@ -60,7 +60,7 @@ DebuggerImpl::~DebuggerImpl() DebuggerApi::DestroyJSDebugger(jsDebugger_); } -bool DebuggerImpl::NotifyScriptParsed(ScriptId scriptId, const CString &fileName) +bool DebuggerImpl::NotifyScriptParsed(ScriptId scriptId, const std::string &fileName) { if (fileName.substr(0, DATA_APP_PATH.length()) != DATA_APP_PATH) { LOG(WARNING, DEBUGGER) << "NotifyScriptParsed: unsupport file: " << fileName; @@ -77,7 +77,7 @@ bool DebuggerImpl::NotifyScriptParsed(ScriptId scriptId, const CString &fileName const JSPandaFile *jsPandaFile = nullptr; JSPandaFileManager::GetInstance()->EnumerateJSPandaFiles([&jsPandaFile, &fileName]( const panda::ecmascript::JSPandaFile *pf) { - if (pf->GetJSPandaFileDesc() == fileName) { + if (fileName == pf->GetJSPandaFileDesc().c_str()) { jsPandaFile = pf; return false; } @@ -95,8 +95,8 @@ bool DebuggerImpl::NotifyScriptParsed(ScriptId scriptId, const CString &fileName } auto mainMethodIndex = panda_file::File::EntityId(jsPandaFile->GetMainMethodIndex()); - const CString &source = extractor->GetSourceCode(mainMethodIndex); - const CString &url = extractor->GetSourceFile(mainMethodIndex); + const std::string &source = extractor->GetSourceCode(mainMethodIndex); + const std::string &url = extractor->GetSourceFile(mainMethodIndex); const uint32_t MIN_SOURCE_CODE_LENGTH = 5; // maybe return 'ANDA' when source code is empty if (source.size() < MIN_SOURCE_CODE_LENGTH) { LOG(ERROR, DEBUGGER) << "NotifyScriptParsed: invalid file: " << fileName; @@ -176,7 +176,7 @@ void DebuggerImpl::NotifyPaused(std::optional location, PauseReaso } Local exception = DebuggerApi::GetAndClearException(vm_); - CVector hitBreakpoints; + std::vector hitBreakpoints; if (location.has_value()) { BreakpointDetails detail; JSPtExtractor *extractor = nullptr; @@ -208,7 +208,7 @@ void DebuggerImpl::NotifyPaused(std::optional location, PauseReaso CleanUpOnPaused(); // Notify paused event - CVector> callFrames; + std::vector> callFrames; if (!GenerateCallFrames(&callFrames)) { LOG(ERROR, DEBUGGER) << "NotifyPaused: GenerateCallFrames failed"; return; @@ -236,7 +236,7 @@ void DebuggerImpl::NotifyPendingJobEntry() void DebuggerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) { - static CUnorderedMap dispatcherTable { + static std::unordered_map dispatcherTable { { "enable", &DebuggerImpl::DispatcherImpl::Enable }, { "disable", &DebuggerImpl::DispatcherImpl::Disable }, { "evaluateOnCallFrame", &DebuggerImpl::DispatcherImpl::EvaluateOnCallFrame }, @@ -253,7 +253,7 @@ void DebuggerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) { "stepOver", &DebuggerImpl::DispatcherImpl::StepOver } }; - const CString &method = request.GetMethod(); + const std::string &method = request.GetMethod(); LOG(DEBUG, DEBUGGER) << "dispatch [" << method << "] to DebuggerImpl"; auto entry = dispatcherTable.find(method); if (entry != dispatcherTable.end() && entry->second != nullptr) { @@ -307,7 +307,7 @@ void DebuggerImpl::DispatcherImpl::GetPossibleBreakpoints(const DispatchRequest SendResponse(request, DispatchResponse::Fail("wrong params")); return; } - CVector> locations; + std::vector> locations; DispatchResponse response = debugger_->GetPossibleBreakpoints(std::move(params), &locations); GetPossibleBreakpointsReturns result(std::move(locations)); SendResponse(request, response, result); @@ -321,7 +321,7 @@ void DebuggerImpl::DispatcherImpl::GetScriptSource(const DispatchRequest &reques SendResponse(request, DispatchResponse::Fail("wrong params")); return; } - CString source; + std::string source; DispatchResponse response = debugger_->GetScriptSource(std::move(params), &source); GetScriptSourceReturns result(source); SendResponse(request, response, result); @@ -371,8 +371,8 @@ void DebuggerImpl::DispatcherImpl::SetBreakpointByUrl(const DispatchRequest &req return; } - CString out_id; - CVector> outLocations; + std::string out_id; + std::vector> outLocations; DispatchResponse response = debugger_->SetBreakpointByUrl(std::move(params), &out_id, &outLocations); SetBreakpointByUrlReturns result(out_id, std::move(outLocations)); SendResponse(request, response, result); @@ -519,12 +519,12 @@ DispatchResponse DebuggerImpl::EvaluateOnCallFrame(std::unique_ptr *result) { CallFrameId callFrameId = params->GetCallFrameId(); - CString expression = params->GetExpression(); + std::string expression = params->GetExpression(); if (callFrameId < 0 || callFrameId >= callFrameHandlers_.size()) { return DispatchResponse::Fail("Invalid callFrameId."); } - CString dest; + std::string dest; if (!DecodeAndCheckBase64(expression, dest)) { LOG(ERROR, DEBUGGER) << "EvaluateValue: base64 decode failed"; auto ret = CmptEvaluateValue(callFrameId, expression, result); @@ -540,7 +540,7 @@ DispatchResponse DebuggerImpl::EvaluateOnCallFrame(std::unique_ptrGetJSThread()->HasPendingException()) { LOG(ERROR, DEBUGGER) << "EvaluateValue: has pending exception"; - CString msg; + std::string msg; DebuggerApi::HandleUncaughtException(vm_, msg); *result = RemoteObject::FromTagged(vm_, Exception::EvalError(vm_, StringRef::NewFromUtf8(vm_, msg.data()))); @@ -553,7 +553,7 @@ DispatchResponse DebuggerImpl::EvaluateOnCallFrame(std::unique_ptr params, - CVector> *locations) + std::vector> *locations) { Location *start = params->GetStart(); auto iter = scripts_.find(start->GetScriptId()); @@ -579,13 +579,13 @@ DispatchResponse DebuggerImpl::GetPossibleBreakpoints(std::unique_ptr params, CString *source) +DispatchResponse DebuggerImpl::GetScriptSource(std::unique_ptr params, std::string *source) { ScriptId scriptId = params->GetScriptId(); auto iter = scripts_.find(scriptId); if (iter == scripts_.end()) { *source = ""; - return DispatchResponse::Fail("unknown script id: " + ToCString(scriptId)); + return DispatchResponse::Fail("unknown script id: " + std::to_string(scriptId)); } *source = iter->second->GetScriptSource(); @@ -600,7 +600,7 @@ DispatchResponse DebuggerImpl::Pause() DispatchResponse DebuggerImpl::RemoveBreakpoint(std::unique_ptr params) { - CString id = params->GetBreakpointId(); + std::string id = params->GetBreakpointId(); LOG(INFO, DEBUGGER) << "RemoveBreakpoint: " << id; BreakpointDetails metaData{}; if (!BreakpointDetails::ParseBreakpointId(id, &metaData)) { @@ -612,7 +612,7 @@ DispatchResponse DebuggerImpl::RemoveBreakpoint(std::unique_ptr bool { fileName = script->GetFileName(); return true; @@ -650,13 +650,13 @@ DispatchResponse DebuggerImpl::SetAsyncCallStackDepth() } DispatchResponse DebuggerImpl::SetBreakpointByUrl(std::unique_ptr params, - CString *outId, - CVector> *outLocations) + std::string *outId, + std::vector> *outLocations) { - const CString &url = params->GetUrl(); + const std::string &url = params->GetUrl(); int32_t lineNumber = params->GetLine(); int32_t columnNumber = params->GetColumn(); - std::optional condition = params->HasCondition() ? params->GetCondition() : std::optional {}; + auto condition = params->HasCondition() ? params->GetCondition() : std::optional {}; JSPtExtractor *extractor = GetExtractor(url); if (extractor == nullptr) { @@ -665,7 +665,7 @@ DispatchResponse DebuggerImpl::SetBreakpointByUrl(std::unique_ptr bool { scriptId = script->GetScriptId(); fileName = script->GetFileName(); @@ -680,7 +680,7 @@ DispatchResponse DebuggerImpl::SetBreakpointByUrl(std::unique_ptr condFuncRef = FunctionRef::Undefined(vm_); if (condition.has_value() && !condition.value().empty()) { - CString dest; + std::string dest; if (!DecodeAndCheckBase64(condition.value(), dest)) { LOG(ERROR, DEBUGGER) << "SetBreakpointByUrl: base64 decode failed"; return false; @@ -701,7 +701,7 @@ DispatchResponse DebuggerImpl::SetBreakpointByUrl(std::unique_ptr>(); + *outLocations = std::vector>(); std::unique_ptr location = std::make_unique(); location->SetScriptId(scriptId).SetLine(lineNumber).SetColumn(0); outLocations->emplace_back(std::move(location)); @@ -774,9 +774,9 @@ void DebuggerImpl::CleanUpOnPaused() scopeObjects_.clear(); } -CString DebuggerImpl::Trim(const CString &str) +std::string DebuggerImpl::Trim(const std::string &str) { - CString ret = str; + std::string ret = str; // If ret has only ' ', remove all charactors. ret.erase(ret.find_last_not_of(' ') + 1); // If ret has only ' ', remove all charactors. @@ -789,7 +789,7 @@ JSPtExtractor *DebuggerImpl::GetExtractor(const JSPandaFile *jsPandaFile) return JSPandaFileManager::GetInstance()->GetJSPtExtractor(jsPandaFile); } -JSPtExtractor *DebuggerImpl::GetExtractor(const CString &url) +JSPtExtractor *DebuggerImpl::GetExtractor(const std::string &url) { auto iter = extractors_.find(url); if (iter == extractors_.end()) { @@ -799,7 +799,7 @@ JSPtExtractor *DebuggerImpl::GetExtractor(const CString &url) return iter->second; } -bool DebuggerImpl::GenerateCallFrames(CVector> *callFrames) +bool DebuggerImpl::GenerateCallFrames(std::vector> *callFrames) { CallFrameId callFrameId = 0; auto walkerFunc = [this, &callFrameId, &callFrames](const FrameHandler *frameHandler) -> StackState { @@ -842,7 +842,7 @@ bool DebuggerImpl::GenerateCallFrame(CallFrame *callFrame, // location std::unique_ptr location = std::make_unique(); - CString url = extractor->GetSourceFile(method->GetMethodId()); + std::string url = extractor->GetSourceFile(method->GetMethodId()); auto scriptFunc = [&location](PtScript *script) -> bool { location->SetScriptId(script->GetScriptId()); return true; @@ -870,12 +870,12 @@ bool DebuggerImpl::GenerateCallFrame(CallFrame *callFrame, std::unique_ptr thisObj = std::make_unique(); thisObj->SetType(ObjectType::Undefined); - CVector> scopeChain; + std::vector> scopeChain; scopeChain.emplace_back(GetLocalScopeChain(frameHandler, &thisObj)); scopeChain.emplace_back(GetGlobalScopeChain()); // functionName - CString functionName = DebuggerApi::ParseFunctionName(method); + std::string functionName = DebuggerApi::ParseFunctionName(method); callFrame->SetCallFrameId(callFrameId) .SetFunctionName(functionName) @@ -1036,7 +1036,7 @@ void DebuggerImpl::UpdateScopeObject(const FrameHandler *frameHandler, } } -std::optional DebuggerImpl::CmptEvaluateValue(CallFrameId callFrameId, const CString &expression, +std::optional DebuggerImpl::CmptEvaluateValue(CallFrameId callFrameId, const std::string &expression, std::unique_ptr *result) { JSMethod *method = DebuggerApi::GetMethod(vm_); @@ -1051,10 +1051,10 @@ std::optional DebuggerImpl::CmptEvaluateValue(CallFrameId callFrameId, Exception::EvalError(vm_, StringRef::NewFromUtf8(vm_, "Internal error."))); return "Internal error."; } - CString varName = expression; - CString varValue; - CString::size_type indexEqual = expression.find_first_of('=', 0); - if (indexEqual != CString::npos) { + std::string varName = expression; + std::string varValue; + std::string::size_type indexEqual = expression.find_first_of('=', 0); + if (indexEqual != std::string::npos) { varName = Trim(expression.substr(0, indexEqual)); varValue = Trim(expression.substr(indexEqual + 1, expression.length())); } @@ -1085,7 +1085,7 @@ std::optional DebuggerImpl::CmptEvaluateValue(CallFrameId callFrameId, return "Unsupported expression."; } -Local DebuggerImpl::ConvertToLocal(const CString &varValue) +Local DebuggerImpl::ConvertToLocal(const std::string &varValue) { Local taggedValue; if (varValue == "false") { @@ -1108,7 +1108,7 @@ Local DebuggerImpl::ConvertToLocal(const CString &varValue) return taggedValue; } -bool DebuggerImpl::DecodeAndCheckBase64(const CString &src, CString &dest) +bool DebuggerImpl::DecodeAndCheckBase64(const std::string &src, std::string &dest) { dest.resize(base64::decoded_size(src.size())); auto [numOctets, _] = base64::decode(dest.data(), src.data(), src.size()); diff --git a/ecmascript/tooling/agent/debugger_impl.h b/ecmascript/tooling/agent/debugger_impl.h index 53fa39ed88..a86d0d459b 100644 --- a/ecmascript/tooling/agent/debugger_impl.h +++ b/ecmascript/tooling/agent/debugger_impl.h @@ -34,7 +34,7 @@ public: ~DebuggerImpl(); // event - bool NotifyScriptParsed(ScriptId scriptId, const CString &fileName); + bool NotifyScriptParsed(ScriptId scriptId, const std::string &fileName); bool NotifySingleStep(const JSPtLocation &location); void NotifyPaused(std::optional location, PauseReason reason); void NotifyPendingJobEntry(); @@ -44,14 +44,14 @@ public: DispatchResponse EvaluateOnCallFrame(std::unique_ptr params, std::unique_ptr *result); DispatchResponse GetPossibleBreakpoints(std::unique_ptr params, - CVector> *outLocations); - DispatchResponse GetScriptSource(std::unique_ptr params, CString *source); + std::vector> *outLocations); + DispatchResponse GetScriptSource(std::unique_ptr params, std::string *source); DispatchResponse Pause(); DispatchResponse RemoveBreakpoint(std::unique_ptr params); DispatchResponse Resume(std::unique_ptr params); DispatchResponse SetAsyncCallStackDepth(); - DispatchResponse SetBreakpointByUrl(std::unique_ptr params, CString *outId, - CVector> *outLocations); + DispatchResponse SetBreakpointByUrl(std::unique_ptr params, std::string *outId, + std::vector> *outLocations); DispatchResponse SetPauseOnExceptions(std::unique_ptr params); DispatchResponse StepInto(std::unique_ptr params); DispatchResponse StepOut(); @@ -64,10 +64,10 @@ public: * @return: true means matched and callback execute success */ template - bool MatchScripts(const Callback &cb, const CString &matchStr, ScriptMatchType type) const + bool MatchScripts(const Callback &cb, const std::string &matchStr, ScriptMatchType type) const { for (const auto &script : scripts_) { - CString value; + std::string value; switch (type) { case ScriptMatchType::URL: { value = script.second->GetUrl(); @@ -91,7 +91,7 @@ public: } return false; } - bool GenerateCallFrames(CVector> *callFrames); + bool GenerateCallFrames(std::vector> *callFrames); class DispatcherImpl final : public DispatcherBase { public: @@ -128,10 +128,10 @@ private: NO_COPY_SEMANTIC(DebuggerImpl); NO_MOVE_SEMANTIC(DebuggerImpl); - CString Trim(const CString &str); + std::string Trim(const std::string &str); JSPtExtractor *GetExtractor(const JSPandaFile *jsPandaFile); - JSPtExtractor *GetExtractor(const CString &url); - std::optional CmptEvaluateValue(CallFrameId callFrameId, const CString &expression, + JSPtExtractor *GetExtractor(const std::string &url); + std::optional CmptEvaluateValue(CallFrameId callFrameId, const std::string &expression, std::unique_ptr *result); bool GenerateCallFrame(CallFrame *callFrame, const FrameHandler *frameHandler, CallFrameId frameId); void SaveCallFrameHandler(const FrameHandler *frameHandler); @@ -142,8 +142,8 @@ private: Local &thisVal, Local &localObj); void CleanUpOnPaused(); void UpdateScopeObject(const FrameHandler *frameHandler, std::string_view varName, const Local &newVal); - Local ConvertToLocal(const CString &varValue); - bool DecodeAndCheckBase64(const CString &src, CString &dest); + Local ConvertToLocal(const std::string &varValue); + bool DecodeAndCheckBase64(const std::string &src, std::string &dest); bool IsSkipLine(const JSPtLocation &location); class Frontend { @@ -170,14 +170,14 @@ private: std::unique_ptr hooks_ {nullptr}; JSDebugger *jsDebugger_ {nullptr}; - CUnorderedMap extractors_ {}; - CUnorderedMap> scripts_ {}; + std::unordered_map extractors_ {}; + std::unordered_map> scripts_ {}; bool pauseOnException_ {false}; bool pauseOnNextByteCode_ {false}; std::unique_ptr singleStepper_ {nullptr}; - CUnorderedMap scopeObjects_ {}; - CVector> callFrameHandlers_; + std::unordered_map scopeObjects_ {}; + std::vector> callFrameHandlers_; JsDebuggerManager::ObjectUpdaterFunc updaterFunc_ {nullptr}; friend class JSPtHooks; diff --git a/ecmascript/tooling/agent/heapprofiler_impl.cpp b/ecmascript/tooling/agent/heapprofiler_impl.cpp index bcce9c3ede..3a8b6b00af 100644 --- a/ecmascript/tooling/agent/heapprofiler_impl.cpp +++ b/ecmascript/tooling/agent/heapprofiler_impl.cpp @@ -18,7 +18,7 @@ namespace panda::ecmascript::tooling { void HeapProfilerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) { - static CUnorderedMap dispatcherTable { + static std::unordered_map dispatcherTable { { "addInspectedHeapObject", &HeapProfilerImpl::DispatcherImpl::AddInspectedHeapObject }, { "collectGarbage", &HeapProfilerImpl::DispatcherImpl::CollectGarbage }, { "enable", &HeapProfilerImpl::DispatcherImpl::Enable }, @@ -33,7 +33,7 @@ void HeapProfilerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) { "takeHeapSnapshot", &HeapProfilerImpl::DispatcherImpl::TakeHeapSnapshot } }; - const CString &method = request.GetMethod(); + const std::string &method = request.GetMethod(); LOG(DEBUG, DEBUGGER) << "dispatch [" << method << "] to HeapProfilerImpl"; auto entry = dispatcherTable.find(method); if (entry != dispatcherTable.end() && entry->second != nullptr) { @@ -208,14 +208,14 @@ void HeapProfilerImpl::Frontend::HeapStatsUpdate(HeapStat* updateData, int count if (!AllowNotify()) { return; } - auto statsDiff = CVector(); + std::vector statsDiff; for (int i = 0; i < count; ++i) { statsDiff.emplace_back(updateData[i].index_); statsDiff.emplace_back(updateData[i].count_); statsDiff.emplace_back(updateData[i].size_); } tooling::HeapStatsUpdate heapStatsUpdate; - heapStatsUpdate.SetStatsUpdate(statsDiff); + heapStatsUpdate.SetStatsUpdate(std::move(statsDiff)); channel_->SendNotification(heapStatsUpdate); } diff --git a/ecmascript/tooling/agent/profiler_impl.cpp b/ecmascript/tooling/agent/profiler_impl.cpp index def58ac132..d0870ddbd1 100644 --- a/ecmascript/tooling/agent/profiler_impl.cpp +++ b/ecmascript/tooling/agent/profiler_impl.cpp @@ -23,7 +23,7 @@ namespace panda::ecmascript::tooling { void ProfilerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) { - static CUnorderedMap dispatcherTable { + static std::unordered_map dispatcherTable { { "disable", &ProfilerImpl::DispatcherImpl::Disable }, { "enable", &ProfilerImpl::DispatcherImpl::Enable }, { "start", &ProfilerImpl::DispatcherImpl::Start }, @@ -38,7 +38,7 @@ void ProfilerImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) { "takeTypeProfile", &ProfilerImpl::DispatcherImpl::TakeTypeProfile } }; - const CString &method = request.GetMethod(); + const std::string &method = request.GetMethod(); LOG(DEBUG, DEBUGGER) << "dispatch [" << method << "] to ProfilerImpl"; auto entry = dispatcherTable.find(method); if (entry != dispatcherTable.end() && entry->second != nullptr) { diff --git a/ecmascript/tooling/agent/runtime_impl.cpp b/ecmascript/tooling/agent/runtime_impl.cpp index f58448305f..aceec6aa5c 100644 --- a/ecmascript/tooling/agent/runtime_impl.cpp +++ b/ecmascript/tooling/agent/runtime_impl.cpp @@ -25,7 +25,7 @@ namespace panda::ecmascript::tooling { void RuntimeImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) { - static CUnorderedMap dispatcherTable { + static std::unordered_map dispatcherTable { { "enable", &RuntimeImpl::DispatcherImpl::Enable }, { "getProperties", &RuntimeImpl::DispatcherImpl::GetProperties }, { "runIfWaitingForDebugger", &RuntimeImpl::DispatcherImpl::RunIfWaitingForDebugger }, @@ -33,7 +33,7 @@ void RuntimeImpl::DispatcherImpl::Dispatch(const DispatchRequest &request) { "getHeapUsage", &RuntimeImpl::DispatcherImpl::GetHeapUsage } }; - const CString &method = request.GetMethod(); + const std::string &method = request.GetMethod(); LOG(DEBUG, DEBUGGER) << "dispatch [" << method << "] to RuntimeImpl"; auto entry = dispatcherTable.find(method); @@ -71,9 +71,9 @@ void RuntimeImpl::DispatcherImpl::GetProperties(const DispatchRequest &request) return; } - CVector> outPropertyDesc; - std::optional>> outInternalDescs; - std::optional>> outPrivateProperties; + std::vector> outPropertyDesc; + std::optional>> outInternalDescs; + std::optional>> outPrivateProperties; std::optional> outExceptionDetails; DispatchResponse response = runtime_->GetProperties(std::move(params), &outPropertyDesc, &outInternalDescs, &outPrivateProperties, &outExceptionDetails); @@ -163,9 +163,9 @@ DispatchResponse RuntimeImpl::GetHeapUsage(double *usedSize, double *totalSize) } DispatchResponse RuntimeImpl::GetProperties(std::unique_ptr params, - CVector> *outPropertyDesc, - [[maybe_unused]] std::optional>> *outInternalDescs, - [[maybe_unused]] std::optional>> *outPrivateProps, + std::vector> *outPropertyDesc, + [[maybe_unused]] std::optional>> *outInternalDescs, + [[maybe_unused]] std::optional>> *outPrivateProps, [[maybe_unused]] std::optional> *outExceptionDetails) { RemoteObjectId objectId = params->GetObjectId(); @@ -227,7 +227,7 @@ DispatchResponse RuntimeImpl::GetProperties(std::unique_ptr } void RuntimeImpl::AddTypedArrayRefs(Local arrayBufferRef, - CVector> *outPropertyDesc) + std::vector> *outPropertyDesc) { int32_t arrayBufferByteLength = arrayBufferRef->ByteLength(vm_); int32_t typedArrayLength = arrayBufferByteLength; @@ -258,7 +258,7 @@ void RuntimeImpl::AddTypedArrayRefs(Local arrayBufferRef, template void RuntimeImpl::AddTypedArrayRef(Local arrayBufferRef, int32_t length, const char* name, - CVector> *outPropertyDesc) + std::vector> *outPropertyDesc) { Local jsValueRefTypedArray(TypedArrayRef::New(vm_, arrayBufferRef, 0, length)); std::unique_ptr remoteObjectTypedArray = RemoteObject::FromTagged(vm_, jsValueRefTypedArray); @@ -283,7 +283,7 @@ void RuntimeImpl::CacheObjectIfNeeded(Local valRef, RemoteObject *re } void RuntimeImpl::GetProtoOrProtoType(const Local &value, bool isOwn, bool isAccessorOnly, - CVector> *outPropertyDesc) + std::vector> *outPropertyDesc) { if (!isAccessorOnly && isOwn && !value->IsProxy()) { return; @@ -317,7 +317,7 @@ void RuntimeImpl::GetProtoOrProtoType(const Local &value, bool isOwn } void RuntimeImpl::GetAdditionalProperties(const Local &value, - CVector> *outPropertyDesc) + std::vector> *outPropertyDesc) { // The length of the TypedArray have to be limited(less than or equal to lengthTypedArrayLimit) until we construct // the PropertyPreview class. Let lengthTypedArrayLimit be 10000 temporarily. @@ -343,7 +343,7 @@ void RuntimeImpl::GetAdditionalProperties(const Local &value, std::ostringstream osNameElement; osNameElement << std::right << std::setw(widthStrExprMaxElementIndex) << i; - CString cStrNameElement = CString(osNameElement.str()); + std::string cStrNameElement = osNameElement.str(); debuggerProperty->SetName(cStrNameElement) .SetWritable(true) .SetConfigurable(true) diff --git a/ecmascript/tooling/agent/runtime_impl.h b/ecmascript/tooling/agent/runtime_impl.h index 41ee6181ff..5ebad5ef43 100644 --- a/ecmascript/tooling/agent/runtime_impl.h +++ b/ecmascript/tooling/agent/runtime_impl.h @@ -37,9 +37,9 @@ public: DispatchResponse GetHeapUsage(double *usedSize, double *totalSize); DispatchResponse GetProperties( std::unique_ptr params, - CVector> *outPropertyDesc, - std::optional>> *outInternalDescs, - std::optional>> *outPrivateProps, + std::vector> *outPropertyDesc, + std::optional>> *outInternalDescs, + std::optional>> *outPrivateProps, std::optional> *outExceptionDetails); class DispatcherImpl final : public DispatcherBase { @@ -73,13 +73,13 @@ private: template void AddTypedArrayRef(Local arrayBufferRef, int32_t length, - const char* name, CVector> *outPropertyDesc); + const char* name, std::vector> *outPropertyDesc); void AddTypedArrayRefs(Local arrayBufferRef, - CVector> *outPropertyDesc); + std::vector> *outPropertyDesc); void GetProtoOrProtoType(const Local &value, bool isOwn, bool isAccessorOnly, - CVector> *outPropertyDesc); + std::vector> *outPropertyDesc); void GetAdditionalProperties(const Local &value, - CVector> *outPropertyDesc); + std::vector> *outPropertyDesc); class Frontend { public: @@ -97,7 +97,7 @@ private: Frontend frontend_; RemoteObjectId curObjectId_ {0}; - CUnorderedMap> properties_ {}; + std::unordered_map> properties_ {}; friend class DebuggerImpl; }; diff --git a/ecmascript/tooling/backend/debugger_api.cpp b/ecmascript/tooling/backend/debugger_api.cpp index 2fe331061f..0ca20e5e23 100644 --- a/ecmascript/tooling/backend/debugger_api.cpp +++ b/ecmascript/tooling/backend/debugger_api.cpp @@ -24,7 +24,6 @@ #include "ecmascript/js_handle.h" #include "ecmascript/js_method.h" #include "ecmascript/jspandafile/js_pandafile_manager.h" -#include "ecmascript/mem/c_string.h" #include "ecmascript/napi/jsnapi_helper.h" #include "ecmascript/tooling/backend/js_debugger.h" @@ -135,22 +134,17 @@ Local DebuggerApi::GetVRegValue(const EcmaVM *ecmaVm, return JSNApiHelper::ToLocal(handledValue); } -CString DebuggerApi::ToCString(Local str) +std::string DebuggerApi::ToStdString(Local str) { ecmascript::JSHandle ret = JSNApiHelper::ToJSHandle(str); ASSERT(ret->IsString()); EcmaString *ecmaStr = EcmaString::Cast(ret.GetTaggedValue().GetTaggedObject()); - return ConvertToString(ecmaStr); -} - -int32_t DebuggerApi::CStringToInt(const CString &str) -{ - return CStringToL(str); + return CstringConvertToStdString(ConvertToString(ecmaStr)); } int32_t DebuggerApi::StringToInt(Local str) { - return CStringToInt(ToCString(str)); + return std::stoi(ToStdString(str)); } // JSThread @@ -206,7 +200,7 @@ bool DebuggerApi::RemoveBreakpoint(JSDebugger *debugger, const JSPtLocation &loc } // JSMethod -CString DebuggerApi::ParseFunctionName(const JSMethod *method) +std::string DebuggerApi::ParseFunctionName(const JSMethod *method) { return method->ParseFunctionName(); } @@ -309,7 +303,7 @@ bool DebuggerApi::SetGlobalValue(const EcmaVM *vm, Local name, Local< return false; } -void DebuggerApi::HandleUncaughtException(const EcmaVM *ecmaVm, CString &message) +void DebuggerApi::HandleUncaughtException(const EcmaVM *ecmaVm, std::string &message) { JSThread *thread = ecmaVm->GetJSThread(); [[maybe_unused]] EcmaHandleScope handleScope(thread); diff --git a/ecmascript/tooling/backend/debugger_api.h b/ecmascript/tooling/backend/debugger_api.h index 774e01987c..2c71543970 100644 --- a/ecmascript/tooling/backend/debugger_api.h +++ b/ecmascript/tooling/backend/debugger_api.h @@ -20,7 +20,6 @@ #include "ecmascript/common.h" #include "ecmascript/jspandafile/scope_info_extractor.h" -#include "ecmascript/mem/c_string.h" #include "ecmascript/napi/include/jsnapi.h" #include "ecmascript/lexical_env.h" #include "ecmascript/tooling/backend/js_debugger_interface.h" @@ -70,8 +69,7 @@ public: static bool SetGlobalValue(const EcmaVM *vm, Local name, Local value); // String - static int32_t CStringToInt(const CString &str); - static CString ToCString(Local str); + static std::string ToStdString(Local str); static int32_t StringToInt(Local str); // JSThread @@ -89,14 +87,14 @@ public: static bool SetBreakpoint(JSDebugger *debugger, const JSPtLocation &location, const Local &condFuncRef); static bool RemoveBreakpoint(JSDebugger *debugger, const JSPtLocation &location); - static void HandleUncaughtException(const EcmaVM *ecmaVm, CString &message); + static void HandleUncaughtException(const EcmaVM *ecmaVm, std::string &message); static Local EvaluateViaFuncCall(EcmaVM *ecmaVm, const Local &funcRef, std::shared_ptr &frameHandler); static Local GenerateFuncFromBuffer(const EcmaVM *ecmaVm, const void *buffer, size_t size, std::string_view entryPoint); // JSMethod - static CString ParseFunctionName(const JSMethod *method); + static std::string ParseFunctionName(const JSMethod *method); }; } // namespace panda::ecmascript::tooling diff --git a/ecmascript/tooling/backend/js_pt_extractor.cpp b/ecmascript/tooling/backend/js_pt_extractor.cpp index 5a48add86d..c37311606b 100644 --- a/ecmascript/tooling/backend/js_pt_extractor.cpp +++ b/ecmascript/tooling/backend/js_pt_extractor.cpp @@ -83,9 +83,9 @@ std::unique_ptr JSPtExtractor::GetStepOutStepper(c return GetStepper(ecmaVm, SingleStepper::Type::OUT); } -CList JSPtExtractor::GetStepRanges(File::EntityId methodId, uint32_t offset) +std::list JSPtExtractor::GetStepRanges(File::EntityId methodId, uint32_t offset) { - CList ranges {}; + std::list ranges {}; const LineNumberTable &table = GetLineNumberTable(methodId); auto callbackFunc = [table, &ranges](int32_t line) -> bool { for (auto it = table.begin(); it != table.end(); ++it) { @@ -107,10 +107,10 @@ std::unique_ptr JSPtExtractor::GetStepper(const Ec ASSERT(method != nullptr); if (type == SingleStepper::Type::OUT) { - return std::make_unique(ecmaVm, method, CList {}, type); + return std::make_unique(ecmaVm, method, std::list {}, type); } - CList ranges = GetStepRanges(method->GetMethodId(), DebuggerApi::GetBytecodeOffset(ecmaVm)); + std::list ranges = GetStepRanges(method->GetMethodId(), DebuggerApi::GetBytecodeOffset(ecmaVm)); return std::make_unique(ecmaVm, method, std::move(ranges), type); } } // namespace panda::ecmascript::tooling diff --git a/ecmascript/tooling/backend/js_pt_extractor.h b/ecmascript/tooling/backend/js_pt_extractor.h index 9530f81dd3..e181b8df59 100644 --- a/ecmascript/tooling/backend/js_pt_extractor.h +++ b/ecmascript/tooling/backend/js_pt_extractor.h @@ -30,7 +30,7 @@ public: class SingleStepper { public: enum class Type { INTO, OVER, OUT }; - SingleStepper(const EcmaVM *ecmaVm, JSMethod *method, CList stepRanges, Type type) + SingleStepper(const EcmaVM *ecmaVm, JSMethod *method, std::list stepRanges, Type type) : ecmaVm_(ecmaVm), method_(method), stepRanges_(std::move(stepRanges)), @@ -50,7 +50,7 @@ public: const EcmaVM *ecmaVm_; JSMethod *method_; - CList stepRanges_; + std::list stepRanges_; uint32_t stackDepth_; Type type_; }; @@ -118,7 +118,7 @@ public: private: NO_COPY_SEMANTIC(JSPtExtractor); NO_MOVE_SEMANTIC(JSPtExtractor); - CList GetStepRanges(File::EntityId methodId, uint32_t offset); + std::list GetStepRanges(File::EntityId methodId, uint32_t offset); std::unique_ptr GetStepper(const EcmaVM *ecmaVm, SingleStepper::Type type); }; } // namespace panda::ecmascript::tooling diff --git a/ecmascript/tooling/base/pt_events.h b/ecmascript/tooling/base/pt_events.h index 398722b8e8..2b0c09fcc3 100644 --- a/ecmascript/tooling/base/pt_events.h +++ b/ecmascript/tooling/base/pt_events.h @@ -30,7 +30,7 @@ public: PtBaseEvents() = default; ~PtBaseEvents() override = default; Local ToObject(const EcmaVM *ecmaVm) const override = 0; - virtual CString GetName() const = 0; + virtual std::string GetName() const = 0; private: NO_COPY_SEMANTIC(PtBaseEvents); @@ -43,7 +43,7 @@ public: ~BreakpointResolved() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const override + std::string GetName() const override { return "Debugger.breakpointResolved"; } @@ -84,23 +84,23 @@ public: ~Paused() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const override + std::string GetName() const override { return "Debugger.paused"; } - const CVector> *GetCallFrames() const + const std::vector> *GetCallFrames() const { return &callFrames_; } - Paused &SetCallFrames(CVector> callFrames) + Paused &SetCallFrames(std::vector> callFrames) { callFrames_ = std::move(callFrames); return *this; } - const CString &GetReason() const + const std::string &GetReason() const { return reason_; } @@ -111,7 +111,7 @@ public: return *this; } - static CString GetReasonString(PauseReason reason) + static std::string GetReasonString(PauseReason reason) { switch (reason) { case AMBIGUOUS: { @@ -176,12 +176,12 @@ public: return data_.has_value(); } - CVector GetHitBreakpoints() const + std::vector GetHitBreakpoints() const { - return hitBreakpoints_.value_or(CVector()); + return hitBreakpoints_.value_or(std::vector()); } - Paused &SetHitBreakpoints(CVector hitBreakpoints) + Paused &SetHitBreakpoints(std::vector hitBreakpoints) { hitBreakpoints_ = std::move(hitBreakpoints); return *this; @@ -196,10 +196,10 @@ private: NO_COPY_SEMANTIC(Paused); NO_MOVE_SEMANTIC(Paused); - CVector> callFrames_ {}; - CString reason_ {}; + std::vector> callFrames_ {}; + std::string reason_ {}; std::optional> data_ {}; - std::optional> hitBreakpoints_ {}; + std::optional> hitBreakpoints_ {}; }; class Resumed final : public PtBaseEvents { @@ -208,7 +208,7 @@ public: ~Resumed() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const override + std::string GetName() const override { return "Debugger.resumed"; } @@ -224,7 +224,7 @@ public: ~ScriptFailedToParse() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const override + std::string GetName() const override { return "Debugger.scriptFailedToParse"; } @@ -240,12 +240,12 @@ public: return *this; } - const CString &GetUrl() const + const std::string &GetUrl() const { return url_; } - ScriptFailedToParse &SetUrl(const CString &url) + ScriptFailedToParse &SetUrl(const std::string &url) { url_ = url; return *this; @@ -306,12 +306,12 @@ public: return *this; } - const CString &GetHash() const + const std::string &GetHash() const { return hash_; } - ScriptFailedToParse &SetHash(const CString &hash) + ScriptFailedToParse &SetHash(const std::string &hash) { hash_ = hash; return *this; @@ -333,12 +333,12 @@ public: return execContextAuxData_.has_value(); } - const CString &GetSourceMapURL() const + const std::string &GetSourceMapURL() const { return sourceMapUrl_.value(); } - ScriptFailedToParse &SetSourceMapURL(const CString &sourceMapUrl) + ScriptFailedToParse &SetSourceMapURL(const std::string &sourceMapUrl) { sourceMapUrl_ = sourceMapUrl; return *this; @@ -413,12 +413,12 @@ public: return codeOffset_.has_value(); } - const CString &GetScriptLanguage() const + const std::string &GetScriptLanguage() const { return scriptLanguage_.value(); } - ScriptFailedToParse &SetScriptLanguage(const CString &scriptLanguage) + ScriptFailedToParse &SetScriptLanguage(const std::string &scriptLanguage) { scriptLanguage_ = scriptLanguage; return *this; @@ -429,12 +429,12 @@ public: return scriptLanguage_.has_value(); } - const CString &GetEmbedderName() const + const std::string &GetEmbedderName() const { return embedderName_.value(); } - ScriptFailedToParse &SetEmbedderName(const CString &embedderName) + ScriptFailedToParse &SetEmbedderName(const std::string &embedderName) { embedderName_ = embedderName; return *this; @@ -450,21 +450,21 @@ private: NO_MOVE_SEMANTIC(ScriptFailedToParse); ScriptId scriptId_ {}; - CString url_ {}; + std::string url_ {}; int32_t startLine_ {0}; int32_t startColumn_ {0}; int32_t endLine_ {0}; int32_t endColumn_ {0}; ExecutionContextId executionContextId_ {0}; - CString hash_ {}; + std::string hash_ {}; std::optional> execContextAuxData_ {}; - std::optional sourceMapUrl_ {}; + std::optional sourceMapUrl_ {}; std::optional hasSourceUrl_ {}; std::optional isModule_ {}; std::optional length_ {}; std::optional codeOffset_ {}; - std::optional scriptLanguage_ {}; - std::optional embedderName_ {}; + std::optional scriptLanguage_ {}; + std::optional embedderName_ {}; }; class ScriptParsed final : public PtBaseEvents { @@ -473,7 +473,7 @@ public: ~ScriptParsed() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const override + std::string GetName() const override { return "Debugger.scriptParsed"; } @@ -489,12 +489,12 @@ public: return *this; } - const CString &GetUrl() const + const std::string &GetUrl() const { return url_; } - ScriptParsed &SetUrl(const CString &url) + ScriptParsed &SetUrl(const std::string &url) { url_ = url; return *this; @@ -555,12 +555,12 @@ public: return *this; } - const CString &GetHash() const + const std::string &GetHash() const { return hash_; } - ScriptParsed &SetHash(const CString &hash) + ScriptParsed &SetHash(const std::string &hash) { hash_ = hash; return *this; @@ -598,12 +598,12 @@ public: return execContextAuxData_.has_value(); } - const CString &GetSourceMapURL() const + const std::string &GetSourceMapURL() const { return sourceMapUrl_.value(); } - ScriptParsed &SetSourceMapURL(const CString &sourceMapUrl) + ScriptParsed &SetSourceMapURL(const std::string &sourceMapUrl) { sourceMapUrl_ = sourceMapUrl; return *this; @@ -678,12 +678,12 @@ public: return codeOffset_.has_value(); } - const CString &GetScriptLanguage() const + const std::string &GetScriptLanguage() const { return scriptLanguage_.value(); } - ScriptParsed &SetScriptLanguage(const CString &scriptLanguage) + ScriptParsed &SetScriptLanguage(const std::string &scriptLanguage) { scriptLanguage_ = scriptLanguage; return *this; @@ -694,12 +694,12 @@ public: return scriptLanguage_.has_value(); } - const CString &GetEmbedderName() const + const std::string &GetEmbedderName() const { return embedderName_.value(); } - ScriptParsed &SetEmbedderName(const CString &embedderName) + ScriptParsed &SetEmbedderName(const std::string &embedderName) { embedderName_ = embedderName; return *this; @@ -715,22 +715,22 @@ private: NO_MOVE_SEMANTIC(ScriptParsed); ScriptId scriptId_ {}; - CString url_ {}; + std::string url_ {}; int32_t startLine_ {0}; int32_t startColumn_ {0}; int32_t endLine_ {0}; int32_t endColumn_ {0}; ExecutionContextId executionContextId_ {0}; - CString hash_ {}; + std::string hash_ {}; std::optional> execContextAuxData_ {}; std::optional isLiveEdit_ {}; - std::optional sourceMapUrl_ {}; + std::optional sourceMapUrl_ {}; std::optional hasSourceUrl_ {}; std::optional isModule_ {}; std::optional length_ {}; std::optional codeOffset_ {}; - std::optional scriptLanguage_ {}; - std::optional embedderName_ {}; + std::optional scriptLanguage_ {}; + std::optional embedderName_ {}; }; class AddHeapSnapshotChunk final : public PtBaseEvents { @@ -739,12 +739,12 @@ public: ~AddHeapSnapshotChunk() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const override + std::string GetName() const override { return "HeapProfiler.addHeapSnapshotChunk"; } - CString &GetChunk() + std::string &GetChunk() { return chunk_; } @@ -753,7 +753,7 @@ private: NO_COPY_SEMANTIC(AddHeapSnapshotChunk); NO_MOVE_SEMANTIC(AddHeapSnapshotChunk); - CString chunk_ {}; + std::string chunk_ {}; }; class ConsoleProfileFinished final : public PtBaseEvents { @@ -761,17 +761,17 @@ public: ConsoleProfileFinished() = default; ~ConsoleProfileFinished() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const override + std::string GetName() const override { return "Profile.ConsoleProfileFinished"; } - const CString &GetId() const + const std::string &GetId() const { return id_; } - ConsoleProfileFinished &SetId(const CString &id) + ConsoleProfileFinished &SetId(const std::string &id) { id_ = id; return *this; @@ -799,12 +799,12 @@ public: return *this; } - const CString &GetTitle() const + const std::string &GetTitle() const { return title_.value(); } - ConsoleProfileFinished &SetTitle(const CString &title) + ConsoleProfileFinished &SetTitle(const std::string &title) { title_ = title; return *this; @@ -819,10 +819,10 @@ private: NO_COPY_SEMANTIC(ConsoleProfileFinished); NO_MOVE_SEMANTIC(ConsoleProfileFinished); - CString id_ {}; + std::string id_ {}; std::unique_ptr location_ {nullptr}; std::unique_ptr profile_ {nullptr}; - std::optional title_ {}; + std::optional title_ {}; }; class ConsoleProfileStarted final : public PtBaseEvents { @@ -830,17 +830,17 @@ public: ConsoleProfileStarted() = default; ~ConsoleProfileStarted() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const override + std::string GetName() const override { return "Profile.ConsoleProfileStarted"; } - const CString &GetId() const + const std::string &GetId() const { return id_; } - ConsoleProfileStarted &SetId(const CString &id) + ConsoleProfileStarted &SetId(const std::string &id) { id_ = id; return *this; @@ -857,12 +857,12 @@ public: return *this; } - const CString &GetTitle() const + const std::string &GetTitle() const { return title_.value(); } - ConsoleProfileStarted &SetTitle(const CString &title) + ConsoleProfileStarted &SetTitle(const std::string &title) { title_ = title; return *this; @@ -877,9 +877,9 @@ private: NO_COPY_SEMANTIC(ConsoleProfileStarted); NO_MOVE_SEMANTIC(ConsoleProfileStarted); - CString id_ {}; + std::string id_ {}; std::unique_ptr location_ {nullptr}; - std::optional title_ {}; + std::optional title_ {}; }; class PreciseCoverageDeltaUpdate final : public PtBaseEvents { @@ -887,7 +887,7 @@ public: PreciseCoverageDeltaUpdate() = default; ~PreciseCoverageDeltaUpdate() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const override + std::string GetName() const override { return "Profile.PreciseCoverageDeltaUpdate"; } @@ -903,23 +903,23 @@ public: return *this; } - const CString &GetOccasion() const + const std::string &GetOccasion() const { return occasion_; } - PreciseCoverageDeltaUpdate &SetOccasion(const CString &occasion) + PreciseCoverageDeltaUpdate &SetOccasion(const std::string &occasion) { occasion_ = occasion; return *this; } - const CVector> *GetResult() const + const std::vector> *GetResult() const { return &result_; } - PreciseCoverageDeltaUpdate &SetResult(CVector> result) + PreciseCoverageDeltaUpdate &SetResult(std::vector> result) { result_ = std::move(result); return *this; @@ -930,8 +930,8 @@ private: NO_MOVE_SEMANTIC(PreciseCoverageDeltaUpdate); int64_t timestamp_ {0}; - CString occasion_ {}; - CVector> result_ {}; + std::string occasion_ {}; + std::vector> result_ {}; }; class HeapStatsUpdate final : public PtBaseEvents { @@ -940,17 +940,17 @@ public: ~HeapStatsUpdate() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const override + std::string GetName() const override { return "HeapProfiler.heapStatsUpdate"; } - const CVector *GetStatsUpdate() const + const std::vector *GetStatsUpdate() const { return &statsUpdate_; } - HeapStatsUpdate &SetStatsUpdate(CVector statsUpdate) + HeapStatsUpdate &SetStatsUpdate(std::vector statsUpdate) { statsUpdate_ = std::move(statsUpdate); return *this; @@ -960,7 +960,7 @@ private: NO_COPY_SEMANTIC(HeapStatsUpdate); NO_MOVE_SEMANTIC(HeapStatsUpdate); - CVector statsUpdate_ {}; + std::vector statsUpdate_ {}; }; class LastSeenObjectId final : public PtBaseEvents { @@ -969,7 +969,7 @@ public: ~LastSeenObjectId() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const override + std::string GetName() const override { return "HeapProfiler.lastSeenObjectId"; } @@ -1010,7 +1010,7 @@ public: ~ReportHeapSnapshotProgress() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const override + std::string GetName() const override { return "HeapProfiler.reportHeapSnapshotProgress"; } diff --git a/ecmascript/tooling/base/pt_params.cpp b/ecmascript/tooling/base/pt_params.cpp index 3347063c85..b03f3235b7 100644 --- a/ecmascript/tooling/base/pt_params.cpp +++ b/ecmascript/tooling/base/pt_params.cpp @@ -23,7 +23,7 @@ std::unique_ptr EnableParams::Create(const EcmaVM *ecmaVm, const L LOG(ERROR, DEBUGGER) << "RemoteObject::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = @@ -51,7 +51,7 @@ std::unique_ptr EvaluateOnCallFrameParams::Create(con LOG(ERROR, DEBUGGER) << "EvaluateOnCallFrameParams::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = @@ -69,7 +69,7 @@ std::unique_ptr EvaluateOnCallFrameParams::Create(con result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "expression"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - paramsObject->expression_ = DebuggerApi::ToCString(result); + paramsObject->expression_ = DebuggerApi::ToStdString(result); } else { error += "'expression' should be a String;"; } @@ -79,7 +79,7 @@ std::unique_ptr EvaluateOnCallFrameParams::Create(con result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "objectGroup"))); if (!result.IsEmpty() && result->IsString()) { - paramsObject->objectGroup_ = DebuggerApi::ToCString(result); + paramsObject->objectGroup_ = DebuggerApi::ToStdString(result); } result = Local(params)->Get(ecmaVm, @@ -125,7 +125,7 @@ std::unique_ptr GetPossibleBreakpointsParams::Crea LOG(ERROR, DEBUGGER) << "RemoteObject::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = @@ -182,7 +182,7 @@ std::unique_ptr GetScriptSourceParams::Create(const EcmaV LOG(ERROR, DEBUGGER) << "RemoteObject::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = @@ -212,14 +212,14 @@ std::unique_ptr RemoveBreakpointParams::Create(const Ecm LOG(ERROR, DEBUGGER) << "RemoteObject::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "breakpointId"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - paramsObject->breakpointId_ = DebuggerApi::ToCString(result); + paramsObject->breakpointId_ = DebuggerApi::ToStdString(result); } else { error += "'breakpointId' should be a String;"; } @@ -241,7 +241,7 @@ std::unique_ptr ResumeParams::Create(const EcmaVM *ecmaVm, const L LOG(ERROR, DEBUGGER) << "RemoteObject::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = @@ -269,7 +269,7 @@ std::unique_ptr SetAsyncCallStackDepthParams::Crea LOG(ERROR, DEBUGGER) << "RemoteObject::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = @@ -299,7 +299,7 @@ std::unique_ptr SetBlackboxPatternsParams::Create(con LOG(ERROR, DEBUGGER) << "RemoteObject::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = @@ -314,7 +314,7 @@ std::unique_ptr SetBlackboxPatternsParams::Create(con Local value = Local(array)->Get(ecmaVm, key->ToString(ecmaVm)); if (value->IsString()) { paramsObject->patterns_.emplace_back( - DebuggerApi::ToCString(value)); + DebuggerApi::ToStdString(value)); } else { error += "'patterns' items should be a String;"; } @@ -341,7 +341,7 @@ std::unique_ptr SetBreakpointByUrlParams::Create(const LOG(ERROR, DEBUGGER) << "RemoteObject::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = @@ -358,7 +358,7 @@ std::unique_ptr SetBreakpointByUrlParams::Create(const result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "url"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - paramsObject->url_ = DebuggerApi::ToCString(result); + paramsObject->url_ = DebuggerApi::ToStdString(result); } else { error += "'url' should be a String;"; } @@ -366,7 +366,7 @@ std::unique_ptr SetBreakpointByUrlParams::Create(const result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "urlRegex"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - paramsObject->urlRegex_ = DebuggerApi::ToCString(result); + paramsObject->urlRegex_ = DebuggerApi::ToStdString(result); } else { error += "'urlRegex' should be a String;"; } @@ -374,7 +374,7 @@ std::unique_ptr SetBreakpointByUrlParams::Create(const result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "scriptHash"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - paramsObject->scriptHash_ = DebuggerApi::ToCString(result); + paramsObject->scriptHash_ = DebuggerApi::ToStdString(result); } else { error += "'scriptHash' should be a String;"; } @@ -390,7 +390,7 @@ std::unique_ptr SetBreakpointByUrlParams::Create(const result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "condition"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - paramsObject->condition_ = DebuggerApi::ToCString(result); + paramsObject->condition_ = DebuggerApi::ToStdString(result); } else { error += "'condition' should be a String;"; } @@ -411,14 +411,14 @@ std::unique_ptr SetPauseOnExceptionsParams::Create(c LOG(ERROR, DEBUGGER) << "RemoteObject::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "state"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - if (!paramsObject->StoreState(DebuggerApi::ToCString(result))) { + if (!paramsObject->StoreState(DebuggerApi::ToStdString(result))) { error += "'state' is invalid;"; } } else { @@ -442,7 +442,7 @@ std::unique_ptr StepIntoParams::Create(const EcmaVM *ecmaVm, con LOG(ERROR, DEBUGGER) << "RemoteObject::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = @@ -493,7 +493,7 @@ std::unique_ptr StepOverParams::Create(const EcmaVM *ecmaVm, con LOG(ERROR, DEBUGGER) << "RemoteObject::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = @@ -536,7 +536,7 @@ std::unique_ptr GetPropertiesParams::Create(const EcmaVM *e LOG(ERROR, DEBUGGER) << "GetPropertiesParams::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = @@ -592,7 +592,7 @@ std::unique_ptr CallFunctionOnParams::Create(const EcmaVM LOG(ERROR, DEBUGGER) << "CallFunctionOnParams::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); // paramsObject->functionDeclaration_ @@ -600,7 +600,7 @@ std::unique_ptr CallFunctionOnParams::Create(const EcmaVM Local(StringRef::NewFromUtf8(ecmaVm, "functionDeclaration"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - paramsObject->functionDeclaration_ = DebuggerApi::ToCString(result); + paramsObject->functionDeclaration_ = DebuggerApi::ToStdString(result); } else { error += "'functionDeclaration' should be a String;"; } @@ -701,7 +701,7 @@ std::unique_ptr CallFunctionOnParams::Create(const EcmaVM result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "objectGroup"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - paramsObject->objectGroup_ = DebuggerApi::ToCString(result); + paramsObject->objectGroup_ = DebuggerApi::ToStdString(result); } else { error += "'objectGroup' should be a String;"; } @@ -716,7 +716,7 @@ std::unique_ptr CallFunctionOnParams::Create(const EcmaVM error += "'throwOnSideEffect' should be a Boolean;"; } } - // Check whether the CString(error) is empty. + // Check whether the error is empty. if (!error.empty()) { LOG(ERROR, DEBUGGER) << "CallFunctionOnParams::Create " << error; return nullptr; @@ -733,7 +733,7 @@ std::unique_ptr StartSamplingParams::Create(const EcmaVM *e LOG(ERROR, DEBUGGER) << "StartSamplingParams::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = Local(params)->Get(ecmaVm, @@ -771,7 +771,7 @@ std::unique_ptr StartTrackingHeapObjectsParams:: LOG(ERROR, DEBUGGER) << "StartTrackingHeapObjectsParams::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = Local(params)->Get(ecmaVm, @@ -808,7 +808,7 @@ std::unique_ptr StopTrackingHeapObjectsParams::Cr LOG(ERROR, DEBUGGER) << "StopTrackingHeapObjectsParams::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = Local(params)->Get(ecmaVm, @@ -870,7 +870,7 @@ std::unique_ptr AddInspectedHeapObjectParams::Crea LOG(ERROR, DEBUGGER) << "AddInspectedHeapObjectParams::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = Local(params)->Get(ecmaVm, @@ -911,7 +911,7 @@ std::unique_ptr GetHeapObjectIdParams::Create(const EcmaV LOG(ERROR, DEBUGGER) << "GetHeapObjectIdParams::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = Local(params)->Get(ecmaVm, @@ -951,7 +951,7 @@ std::unique_ptr GetObjectByHeapObjectIdParams::Cr LOG(ERROR, DEBUGGER) << "GetObjectByHeapObjectIdParams::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = Local(params)->Get(ecmaVm, @@ -970,7 +970,7 @@ std::unique_ptr GetObjectByHeapObjectIdParams::Cr Local(StringRef::NewFromUtf8(ecmaVm, "objectGroup"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - paramsObject->objectGroup_ = DebuggerApi::ToCString(result); + paramsObject->objectGroup_ = DebuggerApi::ToStdString(result); } else { error += "'objectGroup' should be a String;"; } @@ -1004,7 +1004,7 @@ std::unique_ptr StartPreciseCoverageParam::Create(con LOG(ERROR, DEBUGGER) << "StartPreciseCoverageParam::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = Local(params)->Get(ecmaVm, @@ -1066,7 +1066,7 @@ std::unique_ptr SetSamplingIntervalParams::Create(con LOG(ERROR, DEBUGGER) << "SetSamplingIntervalParams::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto paramsObject = std::make_unique(); Local result = diff --git a/ecmascript/tooling/base/pt_params.h b/ecmascript/tooling/base/pt_params.h index c14c7819a4..06eb0104dd 100644 --- a/ecmascript/tooling/base/pt_params.h +++ b/ecmascript/tooling/base/pt_params.h @@ -75,7 +75,7 @@ public: return callFrameId_; } - const CString &GetExpression() + const std::string &GetExpression() { return expression_; } @@ -85,8 +85,8 @@ private: NO_MOVE_SEMANTIC(EvaluateOnCallFrameParams); CallFrameId callFrameId_ {}; - CString expression_ {}; - std::optional objectGroup_ {}; + std::string expression_ {}; + std::optional objectGroup_ {}; std::optional includeCommandLineApi_ {}; std::optional silent_ {}; std::optional returnByValue_ {}; @@ -249,7 +249,7 @@ public: return Local(); } - CList GetPatterns() const + std::list GetPatterns() const { return patterns_; } @@ -258,7 +258,7 @@ private: NO_COPY_SEMANTIC(SetBlackboxPatternsParams); NO_MOVE_SEMANTIC(SetBlackboxPatternsParams); - CList patterns_ {}; + std::list patterns_ {}; }; class SetBreakpointByUrlParams : public PtBaseParams { @@ -277,7 +277,7 @@ public: return line_; } - const CString &GetUrl() const + const std::string &GetUrl() const { return url_.value(); } @@ -287,7 +287,7 @@ public: return url_.has_value(); } - const CString &GetUrlRegex() const + const std::string &GetUrlRegex() const { return urlRegex_.value(); } @@ -297,7 +297,7 @@ public: return urlRegex_.has_value(); } - const CString &GetScriptHash() const + const std::string &GetScriptHash() const { return scriptHash_.value(); } @@ -317,7 +317,7 @@ public: return column_.has_value(); } - const CString &GetCondition() const + const std::string &GetCondition() const { return condition_.value(); } @@ -332,11 +332,11 @@ private: NO_MOVE_SEMANTIC(SetBreakpointByUrlParams); int32_t line_ {0}; - std::optional url_ {}; - std::optional urlRegex_ {}; - std::optional scriptHash_ {}; + std::optional url_ {}; + std::optional urlRegex_ {}; + std::optional scriptHash_ {}; std::optional column_ {0}; - std::optional condition_ {}; + std::optional condition_ {}; }; enum class PauseOnExceptionsState : uint8_t { NONE, UNCAUGHT, ALL }; @@ -356,7 +356,7 @@ public: return state_; } - bool StoreState(const CString &state) + bool StoreState(const std::string &state) { if (state == "none") { state_ = PauseOnExceptionsState::NONE; @@ -401,7 +401,7 @@ public: return breakOnAsyncCall_.has_value(); } - const CList> *GetSkipList() const + const std::list> *GetSkipList() const { if (!skipList_) { return nullptr; @@ -419,7 +419,7 @@ private: NO_MOVE_SEMANTIC(StepIntoParams); std::optional breakOnAsyncCall_ {}; - std::optional>> skipList_ {}; + std::optional>> skipList_ {}; }; class StepOverParams : public PtBaseParams { @@ -433,7 +433,7 @@ public: return Local(); } - const CList> *GetSkipList() const + const std::list> *GetSkipList() const { if (!skipList_) { return nullptr; @@ -450,7 +450,7 @@ private: NO_COPY_SEMANTIC(StepOverParams); NO_MOVE_SEMANTIC(StepOverParams); - std::optional>> skipList_ {}; + std::optional>> skipList_ {}; }; class GetPropertiesParams : public PtBaseParams { @@ -520,7 +520,7 @@ public: return Local(); } - const CString &GetFunctionDeclaration() + const std::string &GetFunctionDeclaration() { return functionDeclaration_; } @@ -541,7 +541,7 @@ public: return objectId_.has_value(); } - const CVector> *GetArguments() const + const std::vector> *GetArguments() const { if (!arguments_) { return nullptr; @@ -620,7 +620,7 @@ public: return executionContextId_.has_value(); } - const CString &GetObjectGroup() const + const std::string &GetObjectGroup() const { return objectGroup_.value(); } @@ -644,16 +644,16 @@ private: NO_COPY_SEMANTIC(CallFunctionOnParams); NO_MOVE_SEMANTIC(CallFunctionOnParams); - CString functionDeclaration_ {}; + std::string functionDeclaration_ {}; std::optional objectId_ {}; - std::optional>> arguments_ {}; + std::optional>> arguments_ {}; std::optional silent_ {}; std::optional returnByValue_ {}; std::optional generatePreview_ {}; std::optional userGesture_ {}; std::optional awaitPromise_ {}; std::optional executionContextId_ {}; - std::optional objectGroup_ {}; + std::optional objectGroup_ {}; std::optional throwOnSideEffect_ {}; }; @@ -803,7 +803,7 @@ public: return objectId_; } - const CString &GetObjectGroup() const + const std::string &GetObjectGroup() const { return objectGroup_.value(); } @@ -818,7 +818,7 @@ private: NO_MOVE_SEMANTIC(GetObjectByHeapObjectIdParams); HeapSnapshotObjectId objectId_ {}; - std::optional objectGroup_ {}; + std::optional objectGroup_ {}; }; class StartPreciseCoverageParam : public PtBaseParams { diff --git a/ecmascript/tooling/base/pt_returns.cpp b/ecmascript/tooling/base/pt_returns.cpp index f39a9afecd..2358b83dda 100644 --- a/ecmascript/tooling/base/pt_returns.cpp +++ b/ecmascript/tooling/base/pt_returns.cpp @@ -152,7 +152,7 @@ Local SetScriptSourceReturns::ToObject(const EcmaVM *ecmaVm) const Local result = NewObject(ecmaVm); if (callFrames_) { - const CVector> &callFrame = callFrames_.value(); + const std::vector> &callFrame = callFrames_.value(); size_t len = callFrame.size(); Local values = ArrayRef::New(ecmaVm, len); for (size_t i = 0; i < len; i++) { diff --git a/ecmascript/tooling/base/pt_returns.h b/ecmascript/tooling/base/pt_returns.h index 8ed0fc8cc7..eb0993a649 100644 --- a/ecmascript/tooling/base/pt_returns.h +++ b/ecmascript/tooling/base/pt_returns.h @@ -51,7 +51,7 @@ private: class SetBreakpointByUrlReturns : public PtBaseReturns { public: - explicit SetBreakpointByUrlReturns(const CString &id, CVector> locations) + explicit SetBreakpointByUrlReturns(const std::string &id, std::vector> locations) : id_(id), locations_(std::move(locations)) {} ~SetBreakpointByUrlReturns() override = default; @@ -63,8 +63,8 @@ private: NO_COPY_SEMANTIC(SetBreakpointByUrlReturns); NO_MOVE_SEMANTIC(SetBreakpointByUrlReturns); - CString id_ {}; - CVector> locations_ {}; + std::string id_ {}; + std::vector> locations_ {}; }; class EvaluateOnCallFrameReturns : public PtBaseReturns { @@ -87,7 +87,7 @@ private: class GetPossibleBreakpointsReturns : public PtBaseReturns { public: - explicit GetPossibleBreakpointsReturns(CVector> locations) + explicit GetPossibleBreakpointsReturns(std::vector> locations) : locations_(std::move(locations)) {} ~GetPossibleBreakpointsReturns() override = default; @@ -99,12 +99,12 @@ private: NO_COPY_SEMANTIC(GetPossibleBreakpointsReturns); NO_MOVE_SEMANTIC(GetPossibleBreakpointsReturns); - CVector> locations_ {}; + std::vector> locations_ {}; }; class GetScriptSourceReturns : public PtBaseReturns { public: - explicit GetScriptSourceReturns(const CString &scriptSource, std::optional bytecode = std::nullopt) + explicit GetScriptSourceReturns(const std::string &scriptSource, std::optional bytecode = std::nullopt) : scriptSource_(scriptSource), bytecode_(std::move(bytecode)) {} ~GetScriptSourceReturns() override = default; @@ -116,13 +116,13 @@ private: NO_COPY_SEMANTIC(GetScriptSourceReturns); NO_MOVE_SEMANTIC(GetScriptSourceReturns); - CString scriptSource_ {}; - std::optional bytecode_ {}; + std::string scriptSource_ {}; + std::optional bytecode_ {}; }; class RestartFrameReturns : public PtBaseReturns { public: - explicit RestartFrameReturns(CVector> callFrames) + explicit RestartFrameReturns(std::vector> callFrames) : callFrames_(std::move(callFrames)) {} ~RestartFrameReturns() override = default; @@ -133,12 +133,12 @@ private: NO_COPY_SEMANTIC(RestartFrameReturns); NO_MOVE_SEMANTIC(RestartFrameReturns); - CVector> callFrames_ {}; + std::vector> callFrames_ {}; }; class SearchInContentReturns : public PtBaseReturns { public: - explicit SearchInContentReturns(CVector> result) : result_(std::move(result)) + explicit SearchInContentReturns(std::vector> result) : result_(std::move(result)) {} ~SearchInContentReturns() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; @@ -148,12 +148,12 @@ private: NO_COPY_SEMANTIC(SearchInContentReturns); NO_MOVE_SEMANTIC(SearchInContentReturns); - CVector> result_ {}; + std::vector> result_ {}; }; class SetBreakpointReturns : public PtBaseReturns { public: - explicit SetBreakpointReturns(const CString &id, std::unique_ptr location) + explicit SetBreakpointReturns(const std::string &id, std::unique_ptr location) : breakpointId_(id), location_(std::move(location)) {} ~SetBreakpointReturns() override = default; @@ -163,13 +163,13 @@ private: SetBreakpointReturns() = default; NO_COPY_SEMANTIC(SetBreakpointReturns); NO_MOVE_SEMANTIC(SetBreakpointReturns); - CString breakpointId_ {}; + std::string breakpointId_ {}; std::unique_ptr location_ {}; }; class SetInstrumentationBreakpointReturns : public PtBaseReturns { public: - explicit SetInstrumentationBreakpointReturns(const CString &id) : breakpointId_(id) + explicit SetInstrumentationBreakpointReturns(const std::string &id) : breakpointId_(id) {} ~SetInstrumentationBreakpointReturns() override = default; Local ToObject(const EcmaVM *ecmaVm) const override; @@ -179,12 +179,12 @@ private: NO_COPY_SEMANTIC(SetInstrumentationBreakpointReturns); NO_MOVE_SEMANTIC(SetInstrumentationBreakpointReturns); - CString breakpointId_ {}; + std::string breakpointId_ {}; }; class SetScriptSourceReturns : public PtBaseReturns { public: - explicit SetScriptSourceReturns(std::optional>> callFrames = std::nullopt, + explicit SetScriptSourceReturns(std::optional>> callFrames = std::nullopt, std::optional stackChanged = std::nullopt, std::optional> exceptionDetails = std::nullopt) : callFrames_(std::move(callFrames)), @@ -199,16 +199,16 @@ private: NO_COPY_SEMANTIC(SetScriptSourceReturns); NO_MOVE_SEMANTIC(SetScriptSourceReturns); - std::optional>> callFrames_ {}; + std::optional>> callFrames_ {}; std::optional stackChanged_ {}; std::optional> exceptionDetails_ {}; }; class GetPropertiesReturns : public PtBaseReturns { public: - explicit GetPropertiesReturns(CVector> descriptor, - std::optional>> internalDescripties = std::nullopt, - std::optional>> privateProperties = std::nullopt, + explicit GetPropertiesReturns(std::vector> descriptor, + std::optional>> internalDescripties = std::nullopt, + std::optional>> privateProperties = std::nullopt, std::optional> exceptionDetails = std::nullopt) : result_(std::move(descriptor)), internalPropertyDescripties_(std::move(internalDescripties)), @@ -223,9 +223,9 @@ private: NO_COPY_SEMANTIC(GetPropertiesReturns); NO_MOVE_SEMANTIC(GetPropertiesReturns); - CVector> result_ {}; - std::optional>> internalPropertyDescripties_ {}; - std::optional>> privateProperties_ {}; + std::vector> result_ {}; + std::optional>> internalPropertyDescripties_ {}; + std::optional>> privateProperties_ {}; std::optional> exceptionDetails_ {}; }; @@ -331,7 +331,7 @@ private: class GetBestEffortCoverageReturns : public PtBaseReturns { public: - explicit GetBestEffortCoverageReturns(CVector> result) + explicit GetBestEffortCoverageReturns(std::vector> result) : result_(std::move(result)) {} ~GetBestEffortCoverageReturns() override = default; @@ -342,7 +342,7 @@ private: NO_COPY_SEMANTIC(GetBestEffortCoverageReturns); NO_MOVE_SEMANTIC(GetBestEffortCoverageReturns); - CVector> result_ {}; + std::vector> result_ {}; }; class StartPreciseCoverageReturns : public PtBaseReturns { @@ -361,7 +361,7 @@ private: class TakePreciseCoverageReturns : public PtBaseReturns { public: - explicit TakePreciseCoverageReturns(CVector> result, size_t tamp) + explicit TakePreciseCoverageReturns(std::vector> result, size_t tamp) : result_(std::move(result)), timestamp_(tamp) {} @@ -373,13 +373,13 @@ private: NO_COPY_SEMANTIC(TakePreciseCoverageReturns); NO_MOVE_SEMANTIC(TakePreciseCoverageReturns); - CVector> result_ {}; + std::vector> result_ {}; size_t timestamp_ {0}; }; class TakeTypeProfileturns : public PtBaseReturns { public: - explicit TakeTypeProfileturns(CVector> result) + explicit TakeTypeProfileturns(std::vector> result) : result_(std::move(result)) {} ~TakeTypeProfileturns() override = default; @@ -390,7 +390,7 @@ private: NO_COPY_SEMANTIC(TakeTypeProfileturns); NO_MOVE_SEMANTIC(TakeTypeProfileturns); - CVector> result_ {}; + std::vector> result_ {}; }; } // namespace panda::ecmascript::tooling #endif \ No newline at end of file diff --git a/ecmascript/tooling/base/pt_script.cpp b/ecmascript/tooling/base/pt_script.cpp index ad3bc09855..120442d93b 100644 --- a/ecmascript/tooling/base/pt_script.cpp +++ b/ecmascript/tooling/base/pt_script.cpp @@ -17,7 +17,7 @@ #include "ecmascript/tooling/backend/debugger_api.h" namespace panda::ecmascript::tooling { -PtScript::PtScript(ScriptId scriptId, const CString &fileName, const CString &url, const CString &source) +PtScript::PtScript(ScriptId scriptId, const std::string &fileName, const std::string &url, const std::string &source) : scriptId_(scriptId), fileName_(fileName), url_(url), diff --git a/ecmascript/tooling/base/pt_script.h b/ecmascript/tooling/base/pt_script.h index 16a3364e25..a7425bb8e5 100644 --- a/ecmascript/tooling/base/pt_script.h +++ b/ecmascript/tooling/base/pt_script.h @@ -28,7 +28,7 @@ enum class ScriptMatchType : uint8_t { class PtScript { public: - PtScript(ScriptId scriptId, const CString &fileName, const CString &url, const CString &source); + PtScript(ScriptId scriptId, const std::string &fileName, const std::string &url, const std::string &source); ~PtScript() = default; ScriptId GetScriptId() const @@ -41,52 +41,52 @@ public: scriptId_ = scriptId; } - const CString &GetFileName() const + const std::string &GetFileName() const { return fileName_; } - void SetFileName(const CString &fileName) + void SetFileName(const std::string &fileName) { fileName_ = fileName; } - const CString &GetUrl() const + const std::string &GetUrl() const { return url_; } - void SetUrl(const CString &url) + void SetUrl(const std::string &url) { url_ = url; } - const CString &GetHash() const + const std::string &GetHash() const { return hash_; } - void SetHash(const CString &hash) + void SetHash(const std::string &hash) { hash_ = hash; } - const CString &GetScriptSource() const + const std::string &GetScriptSource() const { return scriptSource_; } - void SetScriptSource(const CString &scriptSource) + void SetScriptSource(const std::string &scriptSource) { scriptSource_ = scriptSource; } - const CString &GetSourceMapUrl() const + const std::string &GetSourceMapUrl() const { return sourceMapUrl_; } - void SetSourceMapUrl(const CString &sourceMapUrl) + void SetSourceMapUrl(const std::string &sourceMapUrl) { sourceMapUrl_ = sourceMapUrl; } @@ -106,11 +106,11 @@ private: NO_MOVE_SEMANTIC(PtScript); ScriptId scriptId_ {}; // start from 0, such as "0","1","2"... - CString fileName_ {}; // binary file name, such as xx.bin - CString url_ {}; // source file name, such as xx.js - CString hash_ {}; // js source file hash code - CString scriptSource_ {}; // js source code - CString sourceMapUrl_ {}; // source map url + std::string fileName_ {}; // binary file name, such as xx.bin + std::string url_ {}; // source file name, such as xx.js + std::string hash_ {}; // js source file hash code + std::string scriptSource_ {}; // js source code + std::string sourceMapUrl_ {}; // source map url int32_t endLine_ {0}; // total line number of source file }; } // namespace panda::ecmascript::tooling diff --git a/ecmascript/tooling/base/pt_types.cpp b/ecmascript/tooling/base/pt_types.cpp index be87bbe3d2..ffe4195a03 100644 --- a/ecmascript/tooling/base/pt_types.cpp +++ b/ecmascript/tooling/base/pt_types.cpp @@ -22,73 +22,73 @@ using ObjectType = RemoteObject::TypeName; using ObjectSubType = RemoteObject::SubTypeName; using ObjectClassName = RemoteObject::ClassName; -const CString ObjectType::Object = "object"; // NOLINT (readability-identifier-naming) -const CString ObjectType::Function = "function"; // NOLINT (readability-identifier-naming) -const CString ObjectType::Undefined = "undefined"; // NOLINT (readability-identifier-naming) -const CString ObjectType::String = "string"; // NOLINT (readability-identifier-naming) -const CString ObjectType::Number = "number"; // NOLINT (readability-identifier-naming) -const CString ObjectType::Boolean = "boolean"; // NOLINT (readability-identifier-naming) -const CString ObjectType::Symbol = "symbol"; // NOLINT (readability-identifier-naming) -const CString ObjectType::Bigint = "bigint"; // NOLINT (readability-identifier-naming) -const CString ObjectType::Wasm = "wasm"; // NOLINT (readability-identifier-naming) +const std::string ObjectType::Object = "object"; // NOLINT (readability-identifier-naming) +const std::string ObjectType::Function = "function"; // NOLINT (readability-identifier-naming) +const std::string ObjectType::Undefined = "undefined"; // NOLINT (readability-identifier-naming) +const std::string ObjectType::String = "string"; // NOLINT (readability-identifier-naming) +const std::string ObjectType::Number = "number"; // NOLINT (readability-identifier-naming) +const std::string ObjectType::Boolean = "boolean"; // NOLINT (readability-identifier-naming) +const std::string ObjectType::Symbol = "symbol"; // NOLINT (readability-identifier-naming) +const std::string ObjectType::Bigint = "bigint"; // NOLINT (readability-identifier-naming) +const std::string ObjectType::Wasm = "wasm"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Array = "array"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Null = "null"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Node = "node"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Regexp = "regexp"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Date = "date"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Map = "map"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Set = "set"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Weakmap = "weakmap"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Weakset = "weakset"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Iterator = "iterator"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Generator = "generator"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Error = "error"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Proxy = "proxy"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Promise = "promise"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Typedarray = "typedarray"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Arraybuffer = "arraybuffer"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Dataview = "dataview"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::I32 = "i32"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::I64 = "i64"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::F32 = "f32"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::F64 = "f64"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::V128 = "v128"; // NOLINT (readability-identifier-naming) -const CString ObjectSubType::Externref = "externref"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Array = "array"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Null = "null"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Node = "node"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Regexp = "regexp"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Date = "date"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Map = "map"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Set = "set"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Weakmap = "weakmap"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Weakset = "weakset"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Iterator = "iterator"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Generator = "generator"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Error = "error"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Proxy = "proxy"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Promise = "promise"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Typedarray = "typedarray"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Arraybuffer = "arraybuffer"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Dataview = "dataview"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::I32 = "i32"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::I64 = "i64"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::F32 = "f32"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::F64 = "f64"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::V128 = "v128"; // NOLINT (readability-identifier-naming) +const std::string ObjectSubType::Externref = "externref"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Object = "Object"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Function = "Function"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Array = "Array"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Regexp = "RegExp"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Date = "Date"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Map = "Map"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Set = "Set"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Weakmap = "Weakmap"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Weakset = "Weakset"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::ArrayIterator = "ArrayIterator"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::StringIterator = "StringIterator"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::SetIterator = "SetIterator"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::MapIterator = "MapIterator"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Iterator = "Iterator"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Error = "Error"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Proxy = "Object"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Promise = "Promise"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Typedarray = "Typedarray"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Arraybuffer = "Arraybuffer"; // NOLINT (readability-identifier-naming) -const CString ObjectClassName::Global = "global"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Object = "Object"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Function = "Function"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Array = "Array"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Regexp = "RegExp"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Date = "Date"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Map = "Map"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Set = "Set"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Weakmap = "Weakmap"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Weakset = "Weakset"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::ArrayIterator = "ArrayIterator"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::StringIterator = "StringIterator"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::SetIterator = "SetIterator"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::MapIterator = "MapIterator"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Iterator = "Iterator"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Error = "Error"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Proxy = "Object"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Promise = "Promise"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Typedarray = "Typedarray"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Arraybuffer = "Arraybuffer"; // NOLINT (readability-identifier-naming) +const std::string ObjectClassName::Global = "global"; // NOLINT (readability-identifier-naming) -const CString RemoteObject::ObjectDescription = "Object"; // NOLINT (readability-identifier-naming) -const CString RemoteObject::GlobalDescription = "global"; // NOLINT (readability-identifier-naming) -const CString RemoteObject::ProxyDescription = "Proxy"; // NOLINT (readability-identifier-naming) -const CString RemoteObject::PromiseDescription = "Promise"; // NOLINT (readability-identifier-naming) -const CString RemoteObject::ArrayIteratorDescription = // NOLINT (readability-identifier-naming) +const std::string RemoteObject::ObjectDescription = "Object"; // NOLINT (readability-identifier-naming) +const std::string RemoteObject::GlobalDescription = "global"; // NOLINT (readability-identifier-naming) +const std::string RemoteObject::ProxyDescription = "Proxy"; // NOLINT (readability-identifier-naming) +const std::string RemoteObject::PromiseDescription = "Promise"; // NOLINT (readability-identifier-naming) +const std::string RemoteObject::ArrayIteratorDescription = // NOLINT (readability-identifier-naming) "ArrayIterator"; -const CString RemoteObject::StringIteratorDescription = // NOLINT (readability-identifier-naming) +const std::string RemoteObject::StringIteratorDescription = // NOLINT (readability-identifier-naming) "StringIterator"; -const CString RemoteObject::SetIteratorDescription = "SetIterator"; // NOLINT (readability-identifier-naming) -const CString RemoteObject::MapIteratorDescription = "MapIterator"; // NOLINT (readability-identifier-naming) -const CString RemoteObject::WeakMapDescription = "WeakMap"; // NOLINT (readability-identifier-naming) -const CString RemoteObject::WeakSetDescription = "WeakSet"; // NOLINT (readability-identifier-naming) +const std::string RemoteObject::SetIteratorDescription = "SetIterator"; // NOLINT (readability-identifier-naming) +const std::string RemoteObject::MapIteratorDescription = "MapIterator"; // NOLINT (readability-identifier-naming) +const std::string RemoteObject::WeakMapDescription = "WeakMap"; // NOLINT (readability-identifier-naming) +const std::string RemoteObject::WeakSetDescription = "WeakSet"; // NOLINT (readability-identifier-naming) static constexpr uint64_t DOUBLE_SIGN_MASK = 0x8000000000000000ULL; @@ -179,7 +179,7 @@ PrimitiveRemoteObject::PrimitiveRemoteObject(const EcmaVM *ecmaVm, const LocalSetType(ObjectType::Undefined); } else if (tagged->IsNumber()) { this->SetType(ObjectType::Number) - .SetDescription(DebuggerApi::ToCString(tagged->ToString(ecmaVm))); + .SetDescription(DebuggerApi::ToStdString(tagged->ToString(ecmaVm))); double val = Local(tagged)->Value(); if (!std::isfinite(val) || (val == 0 && ((bit_cast(val) & DOUBLE_SIGN_MASK) == DOUBLE_SIGN_MASK))) { this->SetUnserializableValue(this->GetDescription()); @@ -192,7 +192,7 @@ PrimitiveRemoteObject::PrimitiveRemoteObject(const EcmaVM *ecmaVm, const Local &tagged) +std::string ObjectRemoteObject::DescriptionForObject(const EcmaVM *ecmaVm, const Local &tagged) { if (tagged->IsArray(ecmaVm)) { return DescriptionForArray(ecmaVm, Local(tagged)); @@ -242,69 +242,69 @@ CString ObjectRemoteObject::DescriptionForObject(const EcmaVM *ecmaVm, const Loc return RemoteObject::ObjectDescription; } -CString ObjectRemoteObject::DescriptionForArray(const EcmaVM *ecmaVm, const Local &tagged) +std::string ObjectRemoteObject::DescriptionForArray(const EcmaVM *ecmaVm, const Local &tagged) { - CString description = "Array(" + ToCString(tagged->Length(ecmaVm)) + ")"; + std::string description = "Array(" + std::to_string(tagged->Length(ecmaVm)) + ")"; return description; } -CString ObjectRemoteObject::DescriptionForRegexp(const EcmaVM *ecmaVm, const Local &tagged) +std::string ObjectRemoteObject::DescriptionForRegexp(const EcmaVM *ecmaVm, const Local &tagged) { - CString regexpSource = DebuggerApi::ToCString(tagged->GetOriginalSource(ecmaVm)); - CString description = "/" + regexpSource + "/"; + std::string regexpSource = DebuggerApi::ToStdString(tagged->GetOriginalSource(ecmaVm)); + std::string description = "/" + regexpSource + "/"; return description; } -CString ObjectRemoteObject::DescriptionForDate(const EcmaVM *ecmaVm, const Local &tagged) +std::string ObjectRemoteObject::DescriptionForDate(const EcmaVM *ecmaVm, const Local &tagged) { - CString description = DebuggerApi::ToCString(tagged->ToString(ecmaVm)); + std::string description = DebuggerApi::ToStdString(tagged->ToString(ecmaVm)); return description; } -CString ObjectRemoteObject::DescriptionForMap(const Local &tagged) +std::string ObjectRemoteObject::DescriptionForMap(const Local &tagged) { - CString description = ("Map(" + ToCString(tagged->GetSize()) + ")"); + std::string description = ("Map(" + std::to_string(tagged->GetSize()) + ")"); return description; } -CString ObjectRemoteObject::DescriptionForSet(const Local &tagged) +std::string ObjectRemoteObject::DescriptionForSet(const Local &tagged) { - CString description = ("Set(" + ToCString(tagged->GetSize()) + ")"); + std::string description = ("Set(" + std::to_string(tagged->GetSize()) + ")"); return description; } -CString ObjectRemoteObject::DescriptionForError(const EcmaVM *ecmaVm, const Local &tagged) +std::string ObjectRemoteObject::DescriptionForError(const EcmaVM *ecmaVm, const Local &tagged) { // add message Local stack = StringRef::NewFromUtf8(ecmaVm, "message"); Local result = Local(tagged)->Get(ecmaVm, stack); - return DebuggerApi::ToCString(result->ToString(ecmaVm)); + return DebuggerApi::ToStdString(result->ToString(ecmaVm)); } -CString ObjectRemoteObject::DescriptionForArrayBuffer(const EcmaVM *ecmaVm, const Local &tagged) +std::string ObjectRemoteObject::DescriptionForArrayBuffer(const EcmaVM *ecmaVm, const Local &tagged) { int32_t len = tagged->ByteLength(ecmaVm); - CString description = ("ArrayBuffer(" + ToCString(len) + ")"); + std::string description = ("ArrayBuffer(" + std::to_string(len) + ")"); return description; } -CString SymbolRemoteObject::DescriptionForSymbol(const EcmaVM *ecmaVm, const Local &tagged) const +std::string SymbolRemoteObject::DescriptionForSymbol(const EcmaVM *ecmaVm, const Local &tagged) const { - CString description = - "Symbol(" + DebuggerApi::ToCString(tagged->GetDescription(ecmaVm)) + ")"; + std::string description = + "Symbol(" + DebuggerApi::ToStdString(tagged->GetDescription(ecmaVm)) + ")"; return description; } -CString FunctionRemoteObject::DescriptionForFunction(const EcmaVM *ecmaVm, const Local &tagged) const +std::string FunctionRemoteObject::DescriptionForFunction(const EcmaVM *ecmaVm, const Local &tagged) const { - CString sourceCode; + std::string sourceCode; if (tagged->IsNative(ecmaVm)) { sourceCode = "[native code]"; } else { sourceCode = "[js code]"; } Local name = tagged->GetName(ecmaVm); - CString description = "function " + DebuggerApi::ToCString(name) + "( { " + sourceCode + " }"; + std::string description = "function " + DebuggerApi::ToStdString(name) + "( { " + sourceCode + " }"; return description; } @@ -314,14 +314,14 @@ std::unique_ptr RemoteObject::Create(const EcmaVM *ecmaVm, const L LOG(ERROR, DEBUGGER) << "RemoteObject::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto remoteObject = std::make_unique(); Local result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "type"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - auto type = DebuggerApi::ToCString(result); + auto type = DebuggerApi::ToStdString(result); if (ObjectType::Valid(type)) { remoteObject->type_ = type; } else { @@ -336,7 +336,7 @@ std::unique_ptr RemoteObject::Create(const EcmaVM *ecmaVm, const L result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "subtype"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - auto type = DebuggerApi::ToCString(result); + auto type = DebuggerApi::ToStdString(result); if (ObjectSubType::Valid(type)) { remoteObject->subtype_ = type; } else { @@ -349,7 +349,7 @@ std::unique_ptr RemoteObject::Create(const EcmaVM *ecmaVm, const L result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "className"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - remoteObject->className_ = DebuggerApi::ToCString(result); + remoteObject->className_ = DebuggerApi::ToStdString(result); } else { error += "'className' should be a String;"; } @@ -362,7 +362,7 @@ std::unique_ptr RemoteObject::Create(const EcmaVM *ecmaVm, const L Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "unserializableValue"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - remoteObject->unserializableValue_ = DebuggerApi::ToCString(result); + remoteObject->unserializableValue_ = DebuggerApi::ToStdString(result); } else { error += "'unserializableValue' should be a String;"; } @@ -370,7 +370,7 @@ std::unique_ptr RemoteObject::Create(const EcmaVM *ecmaVm, const L result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "description"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - remoteObject->description_ = DebuggerApi::ToCString(result); + remoteObject->description_ = DebuggerApi::ToStdString(result); } else { error += "'description' should be a String;"; } @@ -436,7 +436,7 @@ std::unique_ptr ExceptionDetails::Create(const EcmaVM *ecmaVm, LOG(ERROR, DEBUGGER) << "ExceptionDetails::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto exceptionDetails = std::make_unique(); Local result = @@ -453,7 +453,7 @@ std::unique_ptr ExceptionDetails::Create(const EcmaVM *ecmaVm, result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "text"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - exceptionDetails->text_ = DebuggerApi::ToCString(result); + exceptionDetails->text_ = DebuggerApi::ToStdString(result); } else { error += "'text' should be a String;"; } @@ -491,7 +491,7 @@ std::unique_ptr ExceptionDetails::Create(const EcmaVM *ecmaVm, result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "url"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - exceptionDetails->url_ = DebuggerApi::ToCString(result); + exceptionDetails->url_ = DebuggerApi::ToStdString(result); } else { error += "'url' should be a String;"; } @@ -573,14 +573,14 @@ std::unique_ptr InternalPropertyDescriptor::Create(c LOG(ERROR, DEBUGGER) << "InternalPropertyDescriptor::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto internalPropertyDescriptor = std::make_unique(); Local result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "name"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - internalPropertyDescriptor->name_ = DebuggerApi::ToCString(result); + internalPropertyDescriptor->name_ = DebuggerApi::ToStdString(result); } else { error += "'name' should be a String;"; } @@ -632,14 +632,14 @@ std::unique_ptr PrivatePropertyDescriptor::Create(con LOG(ERROR, DEBUGGER) << "PrivatePropertyDescriptor::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto propertyDescriptor = std::make_unique(); Local result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "name"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - propertyDescriptor->name_ = DebuggerApi::ToCString(result); + propertyDescriptor->name_ = DebuggerApi::ToStdString(result); } else { error += "'name' should be a String;"; } @@ -727,14 +727,14 @@ std::unique_ptr PropertyDescriptor::FromProperty(const EcmaV { std::unique_ptr debuggerProperty = std::make_unique(); - CString nameStr; + std::string nameStr; if (name->IsSymbol()) { Local symbol(name); nameStr = - "Symbol(" + DebuggerApi::ToCString(Local(name)->GetDescription(ecmaVm)) + ")"; + "Symbol(" + DebuggerApi::ToStdString(Local(name)->GetDescription(ecmaVm)) + ")"; debuggerProperty->symbol_ = RemoteObject::FromTagged(ecmaVm, name); } else { - nameStr = DebuggerApi::ToCString(name->ToString(ecmaVm)); + nameStr = DebuggerApi::ToStdString(name->ToString(ecmaVm)); } debuggerProperty->name_ = nameStr; @@ -763,14 +763,14 @@ std::unique_ptr PropertyDescriptor::Create(const EcmaVM *ecm LOG(ERROR, DEBUGGER) << "PropertyDescriptor::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto propertyDescriptor = std::make_unique(); Local result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "name"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - propertyDescriptor->name_ = DebuggerApi::ToCString(result); + propertyDescriptor->name_ = DebuggerApi::ToStdString(result); } else { error += "'name' should be a String;"; } @@ -942,7 +942,7 @@ std::unique_ptr CallArgument::Create(const EcmaVM *ecmaVm, const L LOG(ERROR, DEBUGGER) << "CallArgument::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto callArgument = std::make_unique(); Local result = @@ -954,7 +954,7 @@ std::unique_ptr CallArgument::Create(const EcmaVM *ecmaVm, const L Local(StringRef::NewFromUtf8(ecmaVm, "unserializableValue"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - callArgument->unserializableValue_ = DebuggerApi::ToCString(result); + callArgument->unserializableValue_ = DebuggerApi::ToStdString(result); } else { error += "'unserializableValue' should be a String;"; } @@ -1002,7 +1002,7 @@ std::unique_ptr Location::Create(const EcmaVM *ecmaVm, const Local(); Local result = @@ -1066,7 +1066,7 @@ std::unique_ptr ScriptPosition::Create(const EcmaVM *ecmaVm, con LOG(ERROR, DEBUGGER) << "ScriptPosition::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto scriptPosition = std::make_unique(); Local result = @@ -1116,7 +1116,7 @@ std::unique_ptr SearchMatch::Create(const EcmaVM *ecmaVm, const Loc LOG(ERROR, DEBUGGER) << "SearchMatch::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto locationSearch = std::make_unique(); Local result = @@ -1134,7 +1134,7 @@ std::unique_ptr SearchMatch::Create(const EcmaVM *ecmaVm, const Loc result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "lineContent"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - locationSearch->lineContent_ = DebuggerApi::ToCString(result); + locationSearch->lineContent_ = DebuggerApi::ToStdString(result); } else { error += "'lineContent' should be a String;"; } @@ -1168,7 +1168,7 @@ std::unique_ptr LocationRange::Create(const EcmaVM *ecmaVm, const LOG(ERROR, DEBUGGER) << "BreakLocation::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto locationRange = std::make_unique(); Local result = @@ -1244,7 +1244,7 @@ std::unique_ptr BreakLocation::Create(const EcmaVM *ecmaVm, const LOG(ERROR, DEBUGGER) << "BreakLocation::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto breakLocation = std::make_unique(); Local result = @@ -1279,7 +1279,7 @@ std::unique_ptr BreakLocation::Create(const EcmaVM *ecmaVm, const result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "type"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - auto type = DebuggerApi::ToCString(result); + auto type = DebuggerApi::ToStdString(result); if (BreakType::Valid(type)) { breakLocation->type_ = type; } else { @@ -1326,14 +1326,14 @@ std::unique_ptr Scope::Create(const EcmaVM *ecmaVm, const Local(); Local result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "type"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - auto type = DebuggerApi::ToCString(result); + auto type = DebuggerApi::ToStdString(result); if (Scope::Type::Valid(type)) { scope->type_ = type; } else { @@ -1363,7 +1363,7 @@ std::unique_ptr Scope::Create(const EcmaVM *ecmaVm, const Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "name"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - scope->name_ = DebuggerApi::ToCString(result); + scope->name_ = DebuggerApi::ToStdString(result); } else { error += "'name' should be a String;"; } @@ -1440,7 +1440,7 @@ std::unique_ptr CallFrame::Create(const EcmaVM *ecmaVm, const Local(); Local result = @@ -1457,7 +1457,7 @@ std::unique_ptr CallFrame::Create(const EcmaVM *ecmaVm, const Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "functionName"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - callFrame->functionName_ = DebuggerApi::ToCString(result); + callFrame->functionName_ = DebuggerApi::ToStdString(result); } else { error += "'functionName' should be a String;"; } @@ -1496,7 +1496,7 @@ std::unique_ptr CallFrame::Create(const EcmaVM *ecmaVm, const Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "url"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - callFrame->url_ = DebuggerApi::ToCString(result); + callFrame->url_ = DebuggerApi::ToStdString(result); } else { error += "'url' should be a String;"; } @@ -1610,7 +1610,7 @@ std::unique_ptr SamplingHeapProfileSample::Create(con LOG(ERROR, DEBUGGER) << "SamplingHeapProfileSample::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto samplingHeapProfileSample = std::make_unique(); Local result = Local(params)->Get(ecmaVm, @@ -1675,14 +1675,14 @@ std::unique_ptr RuntimeCallFrame::Create(const EcmaVM *ecmaVm, LOG(ERROR, DEBUGGER) << "RuntimeCallFrame::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto runtimeCallFrame = std::make_unique(); Local result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "functionName"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - runtimeCallFrame->functionName_ = DebuggerApi::ToCString(result); + runtimeCallFrame->functionName_ = DebuggerApi::ToStdString(result); } else { error += "'functionName' should be a String;"; } @@ -1693,7 +1693,7 @@ std::unique_ptr RuntimeCallFrame::Create(const EcmaVM *ecmaVm, result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "scriptId"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - runtimeCallFrame->scriptId_ = DebuggerApi::ToCString(result); + runtimeCallFrame->scriptId_ = DebuggerApi::ToStdString(result); } else { error += "'scriptId' should be a String;"; } @@ -1704,7 +1704,7 @@ std::unique_ptr RuntimeCallFrame::Create(const EcmaVM *ecmaVm, result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "url"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - runtimeCallFrame->url_ = DebuggerApi::ToCString(result); + runtimeCallFrame->url_ = DebuggerApi::ToStdString(result); } else { error += "'url' should be a String;"; } @@ -1745,11 +1745,11 @@ std::unique_ptr RuntimeCallFrame::Create(const EcmaVM *ecmaVm, std::unique_ptr RuntimeCallFrame::FromFrameInfo(const FrameInfo &cpuFrameInfo) { auto runtimeCallFrame = std::make_unique(); - runtimeCallFrame->SetFunctionName(cpuFrameInfo.functionName.c_str()); - runtimeCallFrame->SetScriptId(std::to_string(cpuFrameInfo.scriptId).c_str()); + runtimeCallFrame->SetFunctionName(cpuFrameInfo.functionName); + runtimeCallFrame->SetScriptId(std::to_string(cpuFrameInfo.scriptId)); runtimeCallFrame->SetColumnNumber(cpuFrameInfo.columnNumber); runtimeCallFrame->SetLineNumber(cpuFrameInfo.lineNumber); - runtimeCallFrame->SetUrl(cpuFrameInfo.url.c_str()); + runtimeCallFrame->SetUrl(cpuFrameInfo.url); return runtimeCallFrame; } @@ -1783,7 +1783,7 @@ std::unique_ptr SamplingHeapProfileNode::Create(const E return nullptr; } - CString error; + std::string error; auto samplingHeapProfileNode = std::make_unique(); Local result = Local(params)->Get(ecmaVm, @@ -1889,7 +1889,7 @@ std::unique_ptr SamplingHeapProfile::Create(const EcmaVM *e LOG(ERROR, DEBUGGER) << "SamplingHeapProfile::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto samplingHeapProfile = std::make_unique(); Local result = Local(params)->Get(ecmaVm, @@ -1969,7 +1969,7 @@ std::unique_ptr PositionTickInfo::Create(const EcmaVM *ecmaVm, LOG(ERROR, DEBUGGER) << "PositionTickInfo::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto positionTicks = std::make_unique(); Local result = @@ -2019,7 +2019,7 @@ std::unique_ptr ProfileNode::Create(const EcmaVM *ecmaVm, const Loc LOG(ERROR, DEBUGGER) << "ProfileNode::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto profileNode = std::make_unique(); Local result = @@ -2098,7 +2098,7 @@ std::unique_ptr ProfileNode::Create(const EcmaVM *ecmaVm, const Loc result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "deoptReason"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - profileNode->deoptReason_ = DebuggerApi::ToCString(result); + profileNode->deoptReason_ = DebuggerApi::ToStdString(result); } else { error += "'deoptReason' should be a String;"; } @@ -2119,7 +2119,7 @@ std::unique_ptr ProfileNode::FromCpuProfileNode(const CpuProfileNod profileNode->SetHitCount(cpuProfileNode.hitCount); size_t childrenLen = cpuProfileNode.children.size(); - CVector tmpChildren; + std::vector tmpChildren; tmpChildren.reserve(childrenLen); for (uint32_t i = 0; i < childrenLen; ++i) { tmpChildren.push_back(cpuProfileNode.children[i]); @@ -2180,7 +2180,7 @@ std::unique_ptr Profile::Create(const EcmaVM *ecmaVm, const Local(); Local result = @@ -2273,7 +2273,7 @@ std::unique_ptr Profile::FromProfileInfo(const ProfileInfo &profileInfo profile->SetStartTime(static_cast(profileInfo.startTime)); profile->SetEndTime(static_cast(profileInfo.stopTime)); size_t samplesLen = profileInfo.samples.size(); - CVector tmpSamples; + std::vector tmpSamples; tmpSamples.reserve(samplesLen); for (uint32_t i = 0; i < samplesLen; ++i) { tmpSamples.push_back(profileInfo.samples[i]); @@ -2281,14 +2281,14 @@ std::unique_ptr Profile::FromProfileInfo(const ProfileInfo &profileInfo profile->SetSamples(tmpSamples); size_t timeDeltasLen = profileInfo.timeDeltas.size(); - CVector tmpTimeDeltas; + std::vector tmpTimeDeltas; tmpTimeDeltas.reserve(timeDeltasLen); for (uint32_t i = 0; i < timeDeltasLen; ++i) { tmpTimeDeltas.push_back(profileInfo.timeDeltas[i]); } profile->SetTimeDeltas(tmpTimeDeltas); - CVector> profileNode; + std::vector> profileNode; size_t nodesLen = profileInfo.nodes.size(); for (uint32_t i = 0; i < nodesLen; ++i) { const auto &cpuProfileNode = profileInfo.nodes[i]; @@ -2344,7 +2344,7 @@ std::unique_ptr Coverage::Create(const EcmaVM *ecmaVm, const Local(); Local result = @@ -2403,14 +2403,14 @@ std::unique_ptr FunctionCoverage::Create(const EcmaVM *ecmaVm, LOG(ERROR, DEBUGGER) << "FunctionCoverage::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto functionCoverage = std::make_unique(); Local result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "functionName"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - functionCoverage->functionName_ = DebuggerApi::ToCString(result); + functionCoverage->functionName_ = DebuggerApi::ToStdString(result); } else { error += "'functionName' should be a String;"; } @@ -2481,14 +2481,14 @@ std::unique_ptr ScriptCoverage::Create(const EcmaVM *ecmaVm, con LOG(ERROR, DEBUGGER) << "ScriptCoverage::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto scriptCoverage = std::make_unique(); Local result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "scriptId"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - scriptCoverage->scriptId_ = DebuggerApi::ToCString(result); + scriptCoverage->scriptId_ = DebuggerApi::ToStdString(result); } else { error += "'scriptId' should be a String;"; } @@ -2498,7 +2498,7 @@ std::unique_ptr ScriptCoverage::Create(const EcmaVM *ecmaVm, con result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "url"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - scriptCoverage->url_ = DebuggerApi::ToCString(result); + scriptCoverage->url_ = DebuggerApi::ToStdString(result); } else { error += "'url' should be a String;"; } @@ -2555,14 +2555,14 @@ std::unique_ptr TypeObject::Create(const EcmaVM *ecmaVm, const Local LOG(ERROR, DEBUGGER) << "TypeObject::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto typeObject = std::make_unique(); Local result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "name"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - typeObject->name_ = DebuggerApi::ToCString(result); + typeObject->name_ = DebuggerApi::ToStdString(result); } else { error += "'name' should be a String;"; } @@ -2591,7 +2591,7 @@ std::unique_ptr TypeProfileEntry::Create(const EcmaVM *ecmaVm, LOG(ERROR, DEBUGGER) << "TypeProfileEntry::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto typeProfileEntry = std::make_unique(); Local result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "offset"))); @@ -2651,14 +2651,14 @@ std::unique_ptr ScriptTypeProfile::Create(const EcmaVM *ecmaV LOG(ERROR, DEBUGGER) << "ScriptTypeProfile::Create params is nullptr"; return nullptr; } - CString error; + std::string error; auto scriptTypeProfile = std::make_unique(); Local result = Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "scriptId"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - scriptTypeProfile->scriptId_ = DebuggerApi::ToCString(result); + scriptTypeProfile->scriptId_ = DebuggerApi::ToStdString(result); } else { error += "'scriptId' should be a String;"; } @@ -2669,7 +2669,7 @@ std::unique_ptr ScriptTypeProfile::Create(const EcmaVM *ecmaV Local(params)->Get(ecmaVm, Local(StringRef::NewFromUtf8(ecmaVm, "url"))); if (!result.IsEmpty() && !result->IsUndefined()) { if (result->IsString()) { - scriptTypeProfile->url_ = DebuggerApi::ToCString(result); + scriptTypeProfile->url_ = DebuggerApi::ToStdString(result); } else { error += "'url' should be a String;"; } diff --git a/ecmascript/tooling/base/pt_types.h b/ecmascript/tooling/base/pt_types.h index c116267f48..c2257f2c67 100644 --- a/ecmascript/tooling/base/pt_types.h +++ b/ecmascript/tooling/base/pt_types.h @@ -20,8 +20,6 @@ #include #include "ecmascript/dfx/cpu_profiler/samples_record.h" -#include "ecmascript/mem/c_containers.h" -#include "ecmascript/mem/c_string.h" #include "ecmascript/tooling/backend/debugger_api.h" #include "libpandabase/macros.h" @@ -46,33 +44,33 @@ private: // ========== Debugger types begin // Debugger.BreakpointId -using BreakpointId = CString; +using BreakpointId = std::string; struct BreakpointDetails { static BreakpointId ToString(const BreakpointDetails &metaData) { - return "id:" + ToCString(metaData.line_) + ":" + ToCString(metaData.column_) + ":" + - metaData.url_; + return "id:" + std::to_string(metaData.line_) + ":" + std::to_string(metaData.column_) + ":" + + metaData.url_; } static bool ParseBreakpointId(const BreakpointId &id, BreakpointDetails *metaData) { auto lineStart = id.find(':'); - if (lineStart == CString::npos) { + if (lineStart == std::string::npos) { return false; } auto columnStart = id.find(':', lineStart + 1); - if (columnStart == CString::npos) { + if (columnStart == std::string::npos) { return false; } auto urlStart = id.find(':', columnStart + 1); - if (urlStart == CString::npos) { + if (urlStart == std::string::npos) { return false; } - CString lineStr = id.substr(lineStart + 1, columnStart - lineStart - 1); - CString columnStr = id.substr(columnStart + 1, urlStart - columnStart - 1); - CString url = id.substr(urlStart + 1); - metaData->line_ = DebuggerApi::CStringToInt(lineStr); - metaData->column_ = DebuggerApi::CStringToInt(columnStr); + std::string lineStr = id.substr(lineStart + 1, columnStart - lineStart - 1); + std::string columnStr = id.substr(columnStart + 1, urlStart - columnStart - 1); + std::string url = id.substr(urlStart + 1); + metaData->line_ = std::stoi(lineStr); + metaData->column_ = std::stoi(columnStr); metaData->url_ = url; return true; @@ -80,7 +78,7 @@ struct BreakpointDetails { int32_t line_ {0}; int32_t column_ {0}; - CString url_ {}; + std::string url_ {}; }; // Debugger.CallFrameId @@ -98,7 +96,7 @@ using RemoteObjectId = uint32_t; using ExecutionContextId = int32_t; // Runtime.UnserializableValue -using UnserializableValue = CString; +using UnserializableValue = std::string; // Runtime.UniqueDebuggerId using UniqueDebuggerId = uint32_t; @@ -116,12 +114,12 @@ public: /* * @see {#ObjectType} */ - const CString &GetType() const + const std::string &GetType() const { return type_; } - RemoteObject &SetType(const CString &type) + RemoteObject &SetType(const std::string &type) { type_ = type; return *this; @@ -129,12 +127,12 @@ public: /* * @see {#ObjectSubType} */ - const CString &GetSubType() const + const std::string &GetSubType() const { return subtype_.value(); } - RemoteObject &SetSubType(const CString &type) + RemoteObject &SetSubType(const std::string &type) { subtype_ = type; return *this; @@ -145,12 +143,12 @@ public: return subtype_.has_value(); } - const CString &GetClassName() const + const std::string &GetClassName() const { return className_.value(); } - RemoteObject &SetClassName(const CString &className) + RemoteObject &SetClassName(const std::string &className) { className_ = className; return *this; @@ -193,12 +191,12 @@ public: return unserializableValue_.has_value(); } - const CString &GetDescription() const + const std::string &GetDescription() const { return description_.value(); } - RemoteObject &SetDescription(const CString &description) + RemoteObject &SetDescription(const std::string &description) { description_ = description; return *this; @@ -226,16 +224,16 @@ public: } struct TypeName { - static const CString Object; // NOLINT (readability-identifier-naming) - static const CString Function; // NOLINT (readability-identifier-naming) - static const CString Undefined; // NOLINT (readability-identifier-naming) - static const CString String; // NOLINT (readability-identifier-naming) - static const CString Number; // NOLINT (readability-identifier-naming) - static const CString Boolean; // NOLINT (readability-identifier-naming) - static const CString Symbol; // NOLINT (readability-identifier-naming) - static const CString Bigint; // NOLINT (readability-identifier-naming) - static const CString Wasm; // NOLINT (readability-identifier-naming) - static bool Valid(const CString &type) + static const std::string Object; // NOLINT (readability-identifier-naming) + static const std::string Function; // NOLINT (readability-identifier-naming) + static const std::string Undefined; // NOLINT (readability-identifier-naming) + static const std::string String; // NOLINT (readability-identifier-naming) + static const std::string Number; // NOLINT (readability-identifier-naming) + static const std::string Boolean; // NOLINT (readability-identifier-naming) + static const std::string Symbol; // NOLINT (readability-identifier-naming) + static const std::string Bigint; // NOLINT (readability-identifier-naming) + static const std::string Wasm; // NOLINT (readability-identifier-naming) + static bool Valid(const std::string &type) { return type == Object || type == Function || type == Undefined || type == String || type == Number || type == Boolean || type == Symbol || type == Bigint || type == Wasm; @@ -243,30 +241,30 @@ public: }; struct SubTypeName { - static const CString Array; // NOLINT (readability-identifier-naming) - static const CString Null; // NOLINT (readability-identifier-naming) - static const CString Node; // NOLINT (readability-identifier-naming) - static const CString Regexp; // NOLINT (readability-identifier-naming) - static const CString Date; // NOLINT (readability-identifier-naming) - static const CString Map; // NOLINT (readability-identifier-naming) - static const CString Set; // NOLINT (readability-identifier-naming) - static const CString Weakmap; // NOLINT (readability-identifier-naming) - static const CString Weakset; // NOLINT (readability-identifier-naming) - static const CString Iterator; // NOLINT (readability-identifier-naming) - static const CString Generator; // NOLINT (readability-identifier-naming) - static const CString Error; // NOLINT (readability-identifier-naming) - static const CString Proxy; // NOLINT (readability-identifier-naming) - static const CString Promise; // NOLINT (readability-identifier-naming) - static const CString Typedarray; // NOLINT (readability-identifier-naming) - static const CString Arraybuffer; // NOLINT (readability-identifier-naming) - static const CString Dataview; // NOLINT (readability-identifier-naming) - static const CString I32; // NOLINT (readability-identifier-naming) - static const CString I64; // NOLINT (readability-identifier-naming) - static const CString F32; // NOLINT (readability-identifier-naming) - static const CString F64; // NOLINT (readability-identifier-naming) - static const CString V128; // NOLINT (readability-identifier-naming) - static const CString Externref; // NOLINT (readability-identifier-naming) - static bool Valid(const CString &type) + static const std::string Array; // NOLINT (readability-identifier-naming) + static const std::string Null; // NOLINT (readability-identifier-naming) + static const std::string Node; // NOLINT (readability-identifier-naming) + static const std::string Regexp; // NOLINT (readability-identifier-naming) + static const std::string Date; // NOLINT (readability-identifier-naming) + static const std::string Map; // NOLINT (readability-identifier-naming) + static const std::string Set; // NOLINT (readability-identifier-naming) + static const std::string Weakmap; // NOLINT (readability-identifier-naming) + static const std::string Weakset; // NOLINT (readability-identifier-naming) + static const std::string Iterator; // NOLINT (readability-identifier-naming) + static const std::string Generator; // NOLINT (readability-identifier-naming) + static const std::string Error; // NOLINT (readability-identifier-naming) + static const std::string Proxy; // NOLINT (readability-identifier-naming) + static const std::string Promise; // NOLINT (readability-identifier-naming) + static const std::string Typedarray; // NOLINT (readability-identifier-naming) + static const std::string Arraybuffer; // NOLINT (readability-identifier-naming) + static const std::string Dataview; // NOLINT (readability-identifier-naming) + static const std::string I32; // NOLINT (readability-identifier-naming) + static const std::string I64; // NOLINT (readability-identifier-naming) + static const std::string F32; // NOLINT (readability-identifier-naming) + static const std::string F64; // NOLINT (readability-identifier-naming) + static const std::string V128; // NOLINT (readability-identifier-naming) + static const std::string Externref; // NOLINT (readability-identifier-naming) + static bool Valid(const std::string &type) { return type == Array || type == Null || type == Node || type == Regexp || type == Map || type == Set || type == Weakmap || type == Iterator || type == Generator || type == Error || type == Proxy || @@ -275,27 +273,27 @@ public: } }; struct ClassName { - static const CString Object; // NOLINT (readability-identifier-naming) - static const CString Function; // NOLINT (readability-identifier-naming) - static const CString Array; // NOLINT (readability-identifier-naming) - static const CString Regexp; // NOLINT (readability-identifier-naming) - static const CString Date; // NOLINT (readability-identifier-naming) - static const CString Map; // NOLINT (readability-identifier-naming) - static const CString Set; // NOLINT (readability-identifier-naming) - static const CString Weakmap; // NOLINT (readability-identifier-naming) - static const CString Weakset; // NOLINT (readability-identifier-naming) - static const CString ArrayIterator; // NOLINT (readability-identifier-naming) - static const CString StringIterator; // NOLINT (readability-identifier-naming) - static const CString SetIterator; // NOLINT (readability-identifier-naming) - static const CString MapIterator; // NOLINT (readability-identifier-naming) - static const CString Iterator; // NOLINT (readability-identifier-naming) - static const CString Error; // NOLINT (readability-identifier-naming) - static const CString Proxy; // NOLINT (readability-identifier-naming) - static const CString Promise; // NOLINT (readability-identifier-naming) - static const CString Typedarray; // NOLINT (readability-identifier-naming) - static const CString Arraybuffer; // NOLINT (readability-identifier-naming) - static const CString Global; // NOLINT (readability-identifier-naming) - static bool Valid(const CString &type) + static const std::string Object; // NOLINT (readability-identifier-naming) + static const std::string Function; // NOLINT (readability-identifier-naming) + static const std::string Array; // NOLINT (readability-identifier-naming) + static const std::string Regexp; // NOLINT (readability-identifier-naming) + static const std::string Date; // NOLINT (readability-identifier-naming) + static const std::string Map; // NOLINT (readability-identifier-naming) + static const std::string Set; // NOLINT (readability-identifier-naming) + static const std::string Weakmap; // NOLINT (readability-identifier-naming) + static const std::string Weakset; // NOLINT (readability-identifier-naming) + static const std::string ArrayIterator; // NOLINT (readability-identifier-naming) + static const std::string StringIterator; // NOLINT (readability-identifier-naming) + static const std::string SetIterator; // NOLINT (readability-identifier-naming) + static const std::string MapIterator; // NOLINT (readability-identifier-naming) + static const std::string Iterator; // NOLINT (readability-identifier-naming) + static const std::string Error; // NOLINT (readability-identifier-naming) + static const std::string Proxy; // NOLINT (readability-identifier-naming) + static const std::string Promise; // NOLINT (readability-identifier-naming) + static const std::string Typedarray; // NOLINT (readability-identifier-naming) + static const std::string Arraybuffer; // NOLINT (readability-identifier-naming) + static const std::string Global; // NOLINT (readability-identifier-naming) + static bool Valid(const std::string &type) { return type == Object || type == Array || type == Regexp || type == Date || type == Map || type == Set || type == Weakmap || type == Weakset || type == ArrayIterator || type == StringIterator || @@ -303,27 +301,27 @@ public: type == Promise || type == Typedarray || type == Arraybuffer || type == Function; } }; - static const CString ObjectDescription; // NOLINT (readability-identifier-naming) - static const CString GlobalDescription; // NOLINT (readability-identifier-naming) - static const CString ProxyDescription; // NOLINT (readability-identifier-naming) - static const CString PromiseDescription; // NOLINT (readability-identifier-naming) - static const CString ArrayIteratorDescription; // NOLINT (readability-identifier-naming) - static const CString StringIteratorDescription; // NOLINT (readability-identifier-naming) - static const CString SetIteratorDescription; // NOLINT (readability-identifier-naming) - static const CString MapIteratorDescription; // NOLINT (readability-identifier-naming) - static const CString WeakMapDescription; // NOLINT (readability-identifier-naming) - static const CString WeakSetDescription; // NOLINT (readability-identifier-naming) + static const std::string ObjectDescription; // NOLINT (readability-identifier-naming) + static const std::string GlobalDescription; // NOLINT (readability-identifier-naming) + static const std::string ProxyDescription; // NOLINT (readability-identifier-naming) + static const std::string PromiseDescription; // NOLINT (readability-identifier-naming) + static const std::string ArrayIteratorDescription; // NOLINT (readability-identifier-naming) + static const std::string StringIteratorDescription; // NOLINT (readability-identifier-naming) + static const std::string SetIteratorDescription; // NOLINT (readability-identifier-naming) + static const std::string MapIteratorDescription; // NOLINT (readability-identifier-naming) + static const std::string WeakMapDescription; // NOLINT (readability-identifier-naming) + static const std::string WeakSetDescription; // NOLINT (readability-identifier-naming) private: NO_COPY_SEMANTIC(RemoteObject); NO_MOVE_SEMANTIC(RemoteObject); - CString type_ {}; - std::optional subtype_ {}; - std::optional className_ {}; + std::string type_ {}; + std::optional subtype_ {}; + std::optional className_ {}; std::optional> value_ {}; std::optional unserializableValue_ {}; - std::optional description_ {}; + std::optional description_ {}; std::optional objectId_ {}; }; @@ -351,7 +349,7 @@ public: ~SymbolRemoteObject() override = default; private: - CString DescriptionForSymbol(const EcmaVM *ecmaVm, const Local &tagged) const; + std::string DescriptionForSymbol(const EcmaVM *ecmaVm, const Local &tagged) const; }; class FunctionRemoteObject final : public RemoteObject { @@ -365,19 +363,19 @@ public: ~FunctionRemoteObject() override = default; private: - CString DescriptionForFunction(const EcmaVM *ecmaVm, const Local &tagged) const; + std::string DescriptionForFunction(const EcmaVM *ecmaVm, const Local &tagged) const; }; class ObjectRemoteObject final : public RemoteObject { public: - explicit ObjectRemoteObject(const EcmaVM *ecmaVm, const Local &tagged, const CString &classname) + explicit ObjectRemoteObject(const EcmaVM *ecmaVm, const Local &tagged, const std::string &classname) { SetType(RemoteObject::TypeName::Object) .SetClassName(classname) .SetDescription(DescriptionForObject(ecmaVm, tagged)); } - explicit ObjectRemoteObject(const EcmaVM *ecmaVm, const Local &tagged, const CString &classname, - const CString &subtype) + explicit ObjectRemoteObject(const EcmaVM *ecmaVm, const Local &tagged, const std::string &classname, + const std::string &subtype) { SetType(RemoteObject::TypeName::Object) .SetSubType(subtype) @@ -385,16 +383,16 @@ public: .SetDescription(DescriptionForObject(ecmaVm, tagged)); } ~ObjectRemoteObject() override = default; - static CString DescriptionForObject(const EcmaVM *ecmaVm, const Local &tagged); + static std::string DescriptionForObject(const EcmaVM *ecmaVm, const Local &tagged); private: - static CString DescriptionForArray(const EcmaVM *ecmaVm, const Local &tagged); - static CString DescriptionForRegexp(const EcmaVM *ecmaVm, const Local &tagged); - static CString DescriptionForDate(const EcmaVM *ecmaVm, const Local &tagged); - static CString DescriptionForMap(const Local &tagged); - static CString DescriptionForSet(const Local &tagged); - static CString DescriptionForError(const EcmaVM *ecmaVm, const Local &tagged); - static CString DescriptionForArrayBuffer(const EcmaVM *ecmaVm, const Local &tagged); + static std::string DescriptionForArray(const EcmaVM *ecmaVm, const Local &tagged); + static std::string DescriptionForRegexp(const EcmaVM *ecmaVm, const Local &tagged); + static std::string DescriptionForDate(const EcmaVM *ecmaVm, const Local &tagged); + static std::string DescriptionForMap(const Local &tagged); + static std::string DescriptionForSet(const Local &tagged); + static std::string DescriptionForError(const EcmaVM *ecmaVm, const Local &tagged); + static std::string DescriptionForArrayBuffer(const EcmaVM *ecmaVm, const Local &tagged); }; // Runtime.ExceptionDetails @@ -416,12 +414,12 @@ public: return *this; } - const CString &GetText() const + const std::string &GetText() const { return text_; } - ExceptionDetails &SetText(const CString &text) + ExceptionDetails &SetText(const std::string &text) { text_ = text; return *this; @@ -465,12 +463,12 @@ public: return scriptId_.has_value(); } - const CString &GetUrl() const + const std::string &GetUrl() const { return url_.value(); } - ExceptionDetails &SetUrl(const CString &url) + ExceptionDetails &SetUrl(const std::string &url) { url_ = url; return *this; @@ -521,11 +519,11 @@ private: NO_MOVE_SEMANTIC(ExceptionDetails); int32_t exceptionId_ {0}; - CString text_ {}; + std::string text_ {}; int32_t line_ {0}; int32_t column_ {0}; std::optional scriptId_ {}; - std::optional url_ {}; + std::optional url_ {}; std::optional> exception_ {}; std::optional executionContextId_ {0}; }; @@ -539,12 +537,12 @@ public: static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const + std::string GetName() const { return name_; } - InternalPropertyDescriptor &SetName(const CString &name) + InternalPropertyDescriptor &SetName(const std::string &name) { name_ = name; return *this; @@ -573,7 +571,7 @@ private: NO_COPY_SEMANTIC(InternalPropertyDescriptor); NO_MOVE_SEMANTIC(InternalPropertyDescriptor); - CString name_ {}; + std::string name_ {}; std::optional> value_ {}; }; @@ -586,12 +584,12 @@ public: static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const + std::string GetName() const { return name_; } - PrivatePropertyDescriptor &SetName(const CString &name) + PrivatePropertyDescriptor &SetName(const std::string &name) { name_ = name; return *this; @@ -658,7 +656,7 @@ private: NO_COPY_SEMANTIC(PrivatePropertyDescriptor); NO_MOVE_SEMANTIC(PrivatePropertyDescriptor); - CString name_ {}; + std::string name_ {}; std::optional> value_ {}; std::optional> get_ {}; std::optional> set_ {}; @@ -675,12 +673,12 @@ public: static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); Local ToObject(const EcmaVM *ecmaVm) const override; - CString GetName() const + std::string GetName() const { return name_; } - PropertyDescriptor &SetName(const CString &name) + PropertyDescriptor &SetName(const std::string &name) { name_ = name; return *this; @@ -836,7 +834,7 @@ private: NO_COPY_SEMANTIC(PropertyDescriptor); NO_MOVE_SEMANTIC(PropertyDescriptor); - CString name_ {}; + std::string name_ {}; std::optional> value_ {}; std::optional writable_ {}; std::optional> get_ {}; @@ -917,15 +915,15 @@ private: // ========== Debugger types begin // Debugger.ScriptLanguage struct ScriptLanguage { - static bool Valid(const CString &language) + static bool Valid(const std::string &language) { return language == JavaScript() || language == WebAssembly(); } - static CString JavaScript() + static std::string JavaScript() { return "JavaScript"; } - static CString WebAssembly() + static std::string WebAssembly() { return "WebAssembly"; } @@ -1039,7 +1037,7 @@ private: NO_MOVE_SEMANTIC(SearchMatch); int32_t lineNumber_ {0}; - CString lineContent_ {}; + std::string lineContent_ {}; }; // Debugger.LocationRange @@ -1143,12 +1141,12 @@ public: /* * @see {#BreakType} */ - const CString &GetType() const + const std::string &GetType() const { return type_.value(); } - BreakLocation &SetType(const CString &type) + BreakLocation &SetType(const std::string &type) { type_ = type; return *this; @@ -1160,19 +1158,19 @@ public: } struct Type { - static bool Valid(const CString &type) + static bool Valid(const std::string &type) { return type == DebuggerStatement() || type == Call() || type == Return(); } - static CString DebuggerStatement() + static std::string DebuggerStatement() { return "debuggerStatement"; } - static CString Call() + static std::string Call() { return "call"; } - static CString Return() + static std::string Return() { return "return"; } @@ -1185,7 +1183,7 @@ private: ScriptId scriptId_ {}; int32_t line_ {0}; std::optional column_ {}; - std::optional type_ {}; + std::optional type_ {}; }; using BreakType = BreakLocation::Type; @@ -1214,12 +1212,12 @@ public: /* * @see {#Scope::Type} */ - const CString &GetType() const + const std::string &GetType() const { return type_; } - Scope &SetType(const CString &type) + Scope &SetType(const std::string &type) { type_ = type; return *this; @@ -1236,12 +1234,12 @@ public: return *this; } - const CString &GetName() const + const std::string &GetName() const { return name_.value(); } - Scope &SetName(const CString &name) + Scope &SetName(const std::string &name) { name_ = name; return *this; @@ -1291,49 +1289,49 @@ public: } struct Type { - static bool Valid(const CString &type) + static bool Valid(const std::string &type) { return type == Global() || type == Local() || type == With() || type == Closure() || type == Catch() || type == Block() || type == Script() || type == Eval() || type == Module() || type == WasmExpressionStack(); } - static CString Global() + static std::string Global() { return "global"; } - static CString Local() + static std::string Local() { return "local"; } - static CString With() + static std::string With() { return "with"; } - static CString Closure() + static std::string Closure() { return "closure"; } - static CString Catch() + static std::string Catch() { return "catch"; } - static CString Block() + static std::string Block() { return "block"; } - static CString Script() + static std::string Script() { return "script"; } - static CString Eval() + static std::string Eval() { return "eval"; } - static CString Module() + static std::string Module() { return "module"; } - static CString WasmExpressionStack() + static std::string WasmExpressionStack() { return "wasm-expression-stack"; } @@ -1343,9 +1341,9 @@ private: NO_COPY_SEMANTIC(Scope); NO_MOVE_SEMANTIC(Scope); - CString type_ {}; + std::string type_ {}; std::unique_ptr object_ {nullptr}; - std::optional name_ {}; + std::optional name_ {}; std::optional> startLocation_ {}; std::optional> endLocation_ {}; }; @@ -1370,12 +1368,12 @@ public: return *this; } - const CString &GetFunctionName() const + const std::string &GetFunctionName() const { return functionName_; } - CallFrame &SetFunctionName(const CString &functionName) + CallFrame &SetFunctionName(const std::string &functionName) { functionName_ = functionName; return *this; @@ -1411,23 +1409,23 @@ public: return *this; } - const CString &GetUrl() const + const std::string &GetUrl() const { return url_; } - CallFrame &SetUrl(const CString &url) + CallFrame &SetUrl(const std::string &url) { url_ = url; return *this; } - const CVector> *GetScopeChain() const + const std::vector> *GetScopeChain() const { return &scopeChain_; } - CallFrame &SetScopeChain(CVector> scopeChain) + CallFrame &SetScopeChain(std::vector> scopeChain) { scopeChain_ = std::move(scopeChain); return *this; @@ -1467,11 +1465,11 @@ private: NO_MOVE_SEMANTIC(CallFrame); CallFrameId callFrameId_ {}; - CString functionName_ {}; + std::string functionName_ {}; std::optional> functionLocation_ {}; std::unique_ptr location_ {nullptr}; - CString url_ {}; - CVector> scopeChain_ {}; + std::string url_ {}; + std::vector> scopeChain_ {}; std::unique_ptr this_ {nullptr}; std::optional> returnValue_ {}; }; @@ -1537,35 +1535,35 @@ public: static std::unique_ptr FromFrameInfo(const FrameInfo &cpuFrameInfo); Local ToObject(const EcmaVM *ecmaVm) const override; - RuntimeCallFrame &SetFunctionName(const CString &functionName) + RuntimeCallFrame &SetFunctionName(const std::string &functionName) { functionName_ = functionName; return *this; } - const CString &GetFunctionName() const + const std::string &GetFunctionName() const { return functionName_; } - RuntimeCallFrame &SetScriptId(const CString &scriptId) + RuntimeCallFrame &SetScriptId(const std::string &scriptId) { scriptId_ = scriptId; return *this; } - const CString &GetScriptId() const + const std::string &GetScriptId() const { return scriptId_; } - RuntimeCallFrame &SetUrl(const CString &url) + RuntimeCallFrame &SetUrl(const std::string &url) { url_ = url; return *this; } - const CString &GetUrl() const + const std::string &GetUrl() const { return url_; } @@ -1596,9 +1594,9 @@ private: NO_COPY_SEMANTIC(RuntimeCallFrame); NO_MOVE_SEMANTIC(RuntimeCallFrame); - CString functionName_ {}; - CString scriptId_ {}; - CString url_ {}; + std::string functionName_ {}; + std::string scriptId_ {}; + std::string url_ {}; int32_t lineNumber_ {}; int32_t columnNumber_ {}; }; @@ -1643,13 +1641,13 @@ public: return id_; } - SamplingHeapProfileNode &SetChildren(CVector> children) + SamplingHeapProfileNode &SetChildren(std::vector> children) { children_ = std::move(children); return *this; } - const CVector> *GetChildren() const + const std::vector> *GetChildren() const { return &children_; } @@ -1661,7 +1659,7 @@ private: std::unique_ptr callFrame_ {nullptr}; size_t selfSize_ {}; int32_t id_ {}; - CVector> children_ {}; + std::vector> children_ {}; }; class SamplingHeapProfile final : public PtBaseTypes { @@ -1682,13 +1680,13 @@ public: return head_.get(); } - SamplingHeapProfile &SetSamples(CVector> samples) + SamplingHeapProfile &SetSamples(std::vector> samples) { samples_ = std::move(samples); return *this; } - const CVector> *GetSamples() const + const std::vector> *GetSamples() const { return &samples_; } @@ -1698,7 +1696,7 @@ private: NO_MOVE_SEMANTIC(SamplingHeapProfile); std::unique_ptr head_ {nullptr}; - CVector> samples_ {}; + std::vector> samples_ {}; }; // ========== Profiler types begin @@ -1787,7 +1785,7 @@ public: return hitCount_.has_value(); } - const CVector *GetChildren() const + const std::vector *GetChildren() const { if (children_) { return &children_.value(); @@ -1795,7 +1793,7 @@ public: return nullptr; } - ProfileNode &SetChildren(CVector children) + ProfileNode &SetChildren(std::vector children) { children_ = std::move(children); return *this; @@ -1806,7 +1804,7 @@ public: return children_.has_value(); } - const CVector> *GetPositionTicks() const + const std::vector> *GetPositionTicks() const { if (positionTicks_) { return &positionTicks_.value(); @@ -1814,7 +1812,7 @@ public: return nullptr; } - ProfileNode &SetPositionTicks(CVector> positionTicks) + ProfileNode &SetPositionTicks(std::vector> positionTicks) { positionTicks_ = std::move(positionTicks); return *this; @@ -1825,12 +1823,12 @@ public: return positionTicks_.has_value(); } - const CString &GetDeoptReason() const + const std::string &GetDeoptReason() const { return deoptReason_.value(); } - ProfileNode &SetDeoptReason(const CString &deoptReason) + ProfileNode &SetDeoptReason(const std::string &deoptReason) { deoptReason_ = deoptReason; return *this; @@ -1847,9 +1845,9 @@ private: int32_t id_ {0}; std::unique_ptr callFrame_ {nullptr}; std::optional hitCount_ {0}; - std::optional> children_ {}; - std::optional>> positionTicks_ {}; - std::optional deoptReason_ {}; + std::optional> children_ {}; + std::optional>> positionTicks_ {}; + std::optional deoptReason_ {}; }; // Profiler.Profile @@ -1884,18 +1882,18 @@ public: return *this; } - const CVector> *GetNodes() const + const std::vector> *GetNodes() const { return &nodes_; } - Profile &SetNodes(CVector> nodes) + Profile &SetNodes(std::vector> nodes) { nodes_ = std::move(nodes); return *this; } - const CVector *GetSamples() const + const std::vector *GetSamples() const { if (samples_) { return &samples_.value(); @@ -1903,7 +1901,7 @@ public: return nullptr; } - Profile &SetSamples(CVector samples) + Profile &SetSamples(std::vector samples) { samples_ = std::move(samples); return *this; @@ -1914,7 +1912,7 @@ public: return samples_.has_value(); } - const CVector *GetTimeDeltas() const + const std::vector *GetTimeDeltas() const { if (timeDeltas_) { return &timeDeltas_.value(); @@ -1922,7 +1920,7 @@ public: return nullptr; } - Profile &SetTimeDeltas(CVector timeDeltas) + Profile &SetTimeDeltas(std::vector timeDeltas) { timeDeltas_ = std::move(timeDeltas); return *this; @@ -1939,9 +1937,9 @@ private: int64_t startTime_ {0}; int64_t endTime_ {0}; - CVector> nodes_ {}; - std::optional> samples_ {}; - std::optional> timeDeltas_ {}; + std::vector> nodes_ {}; + std::optional> samples_ {}; + std::optional> timeDeltas_ {}; }; // Profiler.Coverage @@ -2004,23 +2002,23 @@ public: static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); Local ToObject(const EcmaVM *ecmaVm) const override; - const CString &GetFunctionName() const + const std::string &GetFunctionName() const { return functionName_; } - FunctionCoverage &SetFunctionName(const CString &functionName) + FunctionCoverage &SetFunctionName(const std::string &functionName) { functionName_ = functionName; return *this; } - const CVector> *GetRanges() const + const std::vector> *GetRanges() const { return &ranges_; } - FunctionCoverage &SetFunctions(CVector> ranges) + FunctionCoverage &SetFunctions(std::vector> ranges) { ranges_ = std::move(ranges); return *this; @@ -2041,8 +2039,8 @@ private: NO_COPY_SEMANTIC(FunctionCoverage); NO_MOVE_SEMANTIC(FunctionCoverage); - CString functionName_ {}; - CVector> ranges_ {}; + std::string functionName_ {}; + std::vector> ranges_ {}; bool isBlockCoverage_ {}; }; @@ -2056,34 +2054,34 @@ public: static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); Local ToObject(const EcmaVM *ecmaVm) const override; - const CString &GetScriptId() const + const std::string &GetScriptId() const { return scriptId_; } - ScriptCoverage &SetScriptId(const CString &scriptId) + ScriptCoverage &SetScriptId(const std::string &scriptId) { scriptId_ = scriptId; return *this; } - const CString &GetUrl() const + const std::string &GetUrl() const { return url_; } - ScriptCoverage &SetUrl(const CString &url) + ScriptCoverage &SetUrl(const std::string &url) { url_ = url; return *this; } - const CVector> *GetFunctions() const + const std::vector> *GetFunctions() const { return &functions_; } - ScriptCoverage &SetFunctions(CVector> functions) + ScriptCoverage &SetFunctions(std::vector> functions) { functions_ = std::move(functions); return *this; @@ -2093,9 +2091,9 @@ private: NO_COPY_SEMANTIC(ScriptCoverage); NO_MOVE_SEMANTIC(ScriptCoverage); - CString scriptId_ {}; - CString url_ {}; - CVector> functions_ {}; + std::string scriptId_ {}; + std::string url_ {}; + std::vector> functions_ {}; }; // Profiler.TypeObject @@ -2106,12 +2104,12 @@ public: static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); Local ToObject(const EcmaVM *ecmaVm) const override; - const CString &GetName() const + const std::string &GetName() const { return name_; } - TypeObject &SetName(const CString &name) + TypeObject &SetName(const std::string &name) { name_ = name; return *this; @@ -2121,7 +2119,7 @@ private: NO_COPY_SEMANTIC(TypeObject); NO_MOVE_SEMANTIC(TypeObject); - CString name_ {}; + std::string name_ {}; }; // Profiler.TypeProfileEntry @@ -2143,12 +2141,12 @@ public: return *this; } - const CVector> *GetTypes() const + const std::vector> *GetTypes() const { return &types_; } - TypeProfileEntry &SetTypes(CVector> types) + TypeProfileEntry &SetTypes(std::vector> types) { types_ = std::move(types); return *this; @@ -2159,7 +2157,7 @@ private: NO_MOVE_SEMANTIC(TypeProfileEntry); size_t offset_ {0}; - CVector> types_ {}; + std::vector> types_ {}; }; // Profiler.ScriptTypeProfile @@ -2170,34 +2168,34 @@ public: static std::unique_ptr Create(const EcmaVM *ecmaVm, const Local ¶ms); Local ToObject(const EcmaVM *ecmaVm) const override; - const CString &GetScriptId() const + const std::string &GetScriptId() const { return scriptId_; } - ScriptTypeProfile &SetScriptId(const CString &scriptId) + ScriptTypeProfile &SetScriptId(const std::string &scriptId) { scriptId_ = scriptId; return *this; } - const CString &GetUrl() const + const std::string &GetUrl() const { return url_; } - ScriptTypeProfile &SetUrl(const CString &url) + ScriptTypeProfile &SetUrl(const std::string &url) { url_ = url; return *this; } - const CVector> *GetEntries() const + const std::vector> *GetEntries() const { return &entries_; } - ScriptTypeProfile &SetEntries(CVector> entries) + ScriptTypeProfile &SetEntries(std::vector> entries) { entries_ = std::move(entries); return *this; @@ -2207,9 +2205,9 @@ private: NO_COPY_SEMANTIC(ScriptTypeProfile); NO_MOVE_SEMANTIC(ScriptTypeProfile); - CString scriptId_ {}; - CString url_ {}; - CVector> entries_ {}; + std::string scriptId_ {}; + std::string url_ {}; + std::vector> entries_ {}; }; } // namespace panda::ecmascript::tooling #endif diff --git a/ecmascript/tooling/debugger_service.cpp b/ecmascript/tooling/debugger_service.cpp index a8173fa9a6..1e91a31d30 100644 --- a/ecmascript/tooling/debugger_service.cpp +++ b/ecmascript/tooling/debugger_service.cpp @@ -40,7 +40,7 @@ void DispatchProtocolMessage(const ::panda::ecmascript::EcmaVM *vm, const std::s { ProtocolHandler *handler = vm->GetJsDebuggerManager()->GetDebuggerHandler(); if (handler != nullptr) { - handler->ProcessCommand(message.c_str()); + handler->ProcessCommand(message); } } } // namespace panda::ecmascript::tooling \ No newline at end of file diff --git a/ecmascript/tooling/dispatcher.cpp b/ecmascript/tooling/dispatcher.cpp index 6b22f2ee91..d272755629 100644 --- a/ecmascript/tooling/dispatcher.cpp +++ b/ecmascript/tooling/dispatcher.cpp @@ -24,7 +24,7 @@ #include "ecmascript/tooling/protocol_channel.h" namespace panda::ecmascript::tooling { -DispatchRequest::DispatchRequest(const EcmaVM *ecmaVm, const CString &message) : ecmaVm_(ecmaVm) +DispatchRequest::DispatchRequest(const EcmaVM *ecmaVm, const std::string &message) : ecmaVm_(ecmaVm) { Local msgValue = JSON::Parse(ecmaVm, StringRef::NewFromUtf8(ecmaVm, message.c_str())); if (msgValue->IsException()) { @@ -65,11 +65,11 @@ DispatchRequest::DispatchRequest(const EcmaVM *ecmaVm, const CString &message) : LOG(ERROR, DEBUGGER) << "method format error"; return; } - CString wholeMethod = DebuggerApi::ToCString(methodResult); - CString::size_type length = wholeMethod.length(); - CString::size_type indexPoint; + std::string wholeMethod = DebuggerApi::ToStdString(methodResult); + std::string::size_type length = wholeMethod.length(); + std::string::size_type indexPoint; indexPoint = wholeMethod.find_first_of('.', 0); - if (indexPoint == CString::npos || indexPoint == 0 || indexPoint == length - 1) { + if (indexPoint == std::string::npos || indexPoint == 0 || indexPoint == length - 1) { code_ = RequestCode::METHOD_FORMAT_ERROR; LOG(ERROR, DEBUGGER) << "method format error: " << wholeMethod; return; @@ -94,7 +94,7 @@ DispatchRequest::DispatchRequest(const EcmaVM *ecmaVm, const CString &message) : params_ = paramsValue; } -DispatchResponse DispatchResponse::Create(ResponseCode code, const CString &msg) +DispatchResponse DispatchResponse::Create(ResponseCode code, const std::string &msg) { DispatchResponse response; response.code_ = code; @@ -102,7 +102,7 @@ DispatchResponse DispatchResponse::Create(ResponseCode code, const CString &msg) return response; } -DispatchResponse DispatchResponse::Create(std::optional error) +DispatchResponse DispatchResponse::Create(std::optional error) { DispatchResponse response; if (error.has_value()) { @@ -117,7 +117,7 @@ DispatchResponse DispatchResponse::Ok() return DispatchResponse(); } -DispatchResponse DispatchResponse::Fail(const CString &message) +DispatchResponse DispatchResponse::Fail(const std::string &message) { DispatchResponse response; response.code_ = ResponseCode::NOK; @@ -158,7 +158,7 @@ void Dispatcher::Dispatch(const DispatchRequest &request) LOG(ERROR, DEBUGGER) << "Unknown request"; return; } - const CString &domain = request.GetDomain(); + const std::string &domain = request.GetDomain(); auto dispatcher = dispatchers_.find(domain); if (dispatcher != dispatchers_.end()) { dispatcher->second->Dispatch(request); diff --git a/ecmascript/tooling/dispatcher.h b/ecmascript/tooling/dispatcher.h index 3138dacacb..d8c43788bd 100644 --- a/ecmascript/tooling/dispatcher.h +++ b/ecmascript/tooling/dispatcher.h @@ -19,8 +19,6 @@ #include #include -#include "ecmascript/mem/c_containers.h" -#include "ecmascript/mem/c_string.h" #include "ecmascript/napi/include/jsnapi.h" #include "ecmascript/tooling/backend/js_debugger_interface.h" #include "ecmascript/tooling/base/pt_returns.h" @@ -49,7 +47,7 @@ enum class ResponseCode : uint8_t { OK, NOK }; class DispatchRequest { public: - explicit DispatchRequest(const EcmaVM *ecmaVm, const CString &message); + explicit DispatchRequest(const EcmaVM *ecmaVm, const std::string &message); bool IsValid() const { @@ -63,11 +61,11 @@ public: { return params_; } - const CString &GetDomain() const + const std::string &GetDomain() const { return domain_; } - const CString &GetMethod() const + const std::string &GetMethod() const { return method_; } @@ -81,11 +79,11 @@ public: private: const EcmaVM *ecmaVm_ {nullptr}; int32_t callId_ {-1}; - CString domain_ {}; - CString method_ {}; + std::string domain_ {}; + std::string method_ {}; Local params_ {}; RequestCode code_ {RequestCode::OK}; - CString errorMsg_ {}; + std::string errorMsg_ {}; }; class DispatchResponse { @@ -100,15 +98,15 @@ public: return code_; } - const CString &GetMessage() const + const std::string &GetMessage() const { return errorMsg_; } - static DispatchResponse Create(ResponseCode code, const CString &msg = ""); - static DispatchResponse Create(std::optional error); + static DispatchResponse Create(ResponseCode code, const std::string &msg = ""); + static DispatchResponse Create(std::optional error); static DispatchResponse Ok(); - static DispatchResponse Fail(const CString &message); + static DispatchResponse Fail(const std::string &message); ~DispatchResponse() = default; @@ -116,7 +114,7 @@ private: DispatchResponse() = default; ResponseCode code_ {ResponseCode::OK}; - CString errorMsg_ {}; + std::string errorMsg_ {}; }; class DispatcherBase { @@ -146,7 +144,7 @@ public: void Dispatch(const DispatchRequest &request); private: - CUnorderedMap> dispatchers_ {}; + std::unordered_map> dispatchers_ {}; NO_COPY_SEMANTIC(Dispatcher); NO_MOVE_SEMANTIC(Dispatcher); diff --git a/ecmascript/tooling/interface/file_stream.cpp b/ecmascript/tooling/interface/file_stream.cpp index 6cd5a7f424..6c02144bdb 100644 --- a/ecmascript/tooling/interface/file_stream.cpp +++ b/ecmascript/tooling/interface/file_stream.cpp @@ -19,7 +19,6 @@ #include #include "ecmascript/ecma_macros.h" -#include "ecmascript/mem/c_string.h" #include "libpandabase/utils/logger.h" namespace panda::ecmascript { @@ -106,7 +105,7 @@ bool FileDescriptorStream::WriteChunk(char *data, int size) return false; } - CString str; + std::string str; str.resize(size); for (int i = 0; i < size; ++i) { str[i] = data[i]; diff --git a/ecmascript/tooling/protocol_handler.cpp b/ecmascript/tooling/protocol_handler.cpp index ca045d52a3..48e18a060f 100644 --- a/ecmascript/tooling/protocol_handler.cpp +++ b/ecmascript/tooling/protocol_handler.cpp @@ -34,7 +34,7 @@ void ProtocolHandler::RunIfWaitingForDebugger() waitingForDebugger_ = false; } -void ProtocolHandler::ProcessCommand(const CString &msg) +void ProtocolHandler::ProcessCommand(const std::string &msg) { LOG(DEBUG, DEBUGGER) << "ProtocolHandler::ProcessCommand: " << msg; [[maybe_unused]] LocalScope scope(vm_); diff --git a/ecmascript/tooling/protocol_handler.h b/ecmascript/tooling/protocol_handler.h index d4141ed72f..cffaf53efe 100644 --- a/ecmascript/tooling/protocol_handler.h +++ b/ecmascript/tooling/protocol_handler.h @@ -31,7 +31,7 @@ public: void WaitForDebugger() override; void RunIfWaitingForDebugger() override; - void ProcessCommand(const CString &msg); + void ProcessCommand(const std::string &msg); void SendResponse(const DispatchRequest &request, const DispatchResponse &response, const PtBaseReturns &result) override; void SendNotification(const PtBaseEvents &events) override; diff --git a/ecmascript/tooling/test/debugger_entry_test.cpp b/ecmascript/tooling/test/debugger_entry_test.cpp index f910bd1be6..ed893fee2e 100644 --- a/ecmascript/tooling/test/debugger_entry_test.cpp +++ b/ecmascript/tooling/test/debugger_entry_test.cpp @@ -53,7 +53,7 @@ public: HWTEST_P_L0(DebuggerEntryTest, DebuggerSuite) { - CString testName = GetCurrentTestName(); + std::string testName = GetCurrentTestName(); std::cout << "Running " << testName << std::endl; ASSERT_NE(instance, nullptr); auto [pandaFile, entryPoint] = GetTestEntryPoint(testName); diff --git a/ecmascript/tooling/test/debugger_events_test.cpp b/ecmascript/tooling/test/debugger_events_test.cpp index 84fb2af0f5..2470553b31 100644 --- a/ecmascript/tooling/test/debugger_events_test.cpp +++ b/ecmascript/tooling/test/debugger_events_test.cpp @@ -62,7 +62,6 @@ protected: HWTEST_F_L0(DebuggerEventsTest, BreakpointResolvedToObjectTest) { - CString msg; BreakpointResolved breakpointResolved; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); @@ -79,7 +78,7 @@ HWTEST_F_L0(DebuggerEventsTest, BreakpointResolvedToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("00", DebuggerApi::ToCString(result)); + EXPECT_EQ("00", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "location"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); @@ -90,16 +89,11 @@ HWTEST_F_L0(DebuggerEventsTest, BreakpointResolvedToObjectTest) HWTEST_F_L0(DebuggerEventsTest, PausedToObjectTest) { - CString msg; Paused paused; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params": - {"callFrames":[{"callFrameId":"10","functionName":"name0", - "location":{"scriptId":"5","lineNumber":19},"url":"url7", - "scopeChain":[{"type":"global","object":{"type":"object"}}, {"type":"local","object":{"type":"object"}}], - "this":{"type":"object","subtype":"v128"}}],"reason":"exception"}})"; - paused.SetCallFrames(CVector>{}) + std::vector> v; + paused.SetCallFrames(std::move(v)) .SetReason(PauseReason::EXCEPTION); Local object1 = paused.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); @@ -111,7 +105,7 @@ HWTEST_F_L0(DebuggerEventsTest, PausedToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("exception", DebuggerApi::ToCString(result)); + EXPECT_EQ("exception", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "callFrames"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); @@ -122,7 +116,6 @@ HWTEST_F_L0(DebuggerEventsTest, PausedToObjectTest) HWTEST_F_L0(DebuggerEventsTest, ResumedToObjectTest) { - CString msg; Resumed resumed; Local tmpStr; @@ -132,7 +125,7 @@ HWTEST_F_L0(DebuggerEventsTest, ResumedToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); Local result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(resumed.GetName(), DebuggerApi::ToCString(result)); + EXPECT_EQ(resumed.GetName(), DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); @@ -143,7 +136,6 @@ HWTEST_F_L0(DebuggerEventsTest, ResumedToObjectTest) HWTEST_F_L0(DebuggerEventsTest, ScriptFailedToParseToObjectTest) { - CString msg; ScriptFailedToParse parsed; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); @@ -172,13 +164,13 @@ HWTEST_F_L0(DebuggerEventsTest, ScriptFailedToParseToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("100", DebuggerApi::ToCString(result)); + EXPECT_EQ("100", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "url"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("use/test.js", DebuggerApi::ToCString(result)); + EXPECT_EQ("use/test.js", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "startLine"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); @@ -214,7 +206,7 @@ HWTEST_F_L0(DebuggerEventsTest, ScriptFailedToParseToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("hash0001", DebuggerApi::ToCString(result)); + EXPECT_EQ("hash0001", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "executionContextAuxData"); ASSERT_FALSE(object->Has(ecmaVm, tmpStr)); @@ -223,7 +215,7 @@ HWTEST_F_L0(DebuggerEventsTest, ScriptFailedToParseToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("usr/", DebuggerApi::ToCString(result)); + EXPECT_EQ("usr/", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "hasSourceURL"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); @@ -253,18 +245,17 @@ HWTEST_F_L0(DebuggerEventsTest, ScriptFailedToParseToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("JavaScript", DebuggerApi::ToCString(result)); + EXPECT_EQ("JavaScript", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "embedderName"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("hh", DebuggerApi::ToCString(result)); + EXPECT_EQ("hh", DebuggerApi::ToStdString(result)); } HWTEST_F_L0(DebuggerEventsTest, ScriptParsedToObjectTest) { - CString msg; ScriptParsed parsed; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); @@ -294,13 +285,13 @@ HWTEST_F_L0(DebuggerEventsTest, ScriptParsedToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("10", DebuggerApi::ToCString(result)); + EXPECT_EQ("10", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "url"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("use/test.js", DebuggerApi::ToCString(result)); + EXPECT_EQ("use/test.js", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "startLine"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); @@ -336,7 +327,7 @@ HWTEST_F_L0(DebuggerEventsTest, ScriptParsedToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("hash0001", DebuggerApi::ToCString(result)); + EXPECT_EQ("hash0001", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "executionContextAuxData"); ASSERT_FALSE(object->Has(ecmaVm, tmpStr)); @@ -351,7 +342,7 @@ HWTEST_F_L0(DebuggerEventsTest, ScriptParsedToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("usr/", DebuggerApi::ToCString(result)); + EXPECT_EQ("usr/", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "hasSourceURL"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); @@ -381,29 +372,29 @@ HWTEST_F_L0(DebuggerEventsTest, ScriptParsedToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("JavaScript", DebuggerApi::ToCString(result)); + EXPECT_EQ("JavaScript", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "embedderName"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("hh", DebuggerApi::ToCString(result)); + EXPECT_EQ("hh", DebuggerApi::ToStdString(result)); } HWTEST_F_L0(DebuggerEventsTest, ConsoleProfileFinishedToObjectTest) { - CString msg; ConsoleProfileFinished consoleProfileFinished; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); auto location = std::make_unique(); location->SetScriptId(13).SetLine(20); + std::vector> v; auto profile = std::make_unique(); - profile->SetNodes(CVector>{}) + profile->SetNodes(std::move(v)) .SetStartTime(0) .SetEndTime(15) - .SetSamples(CVector{}) - .SetTimeDeltas(CVector{}); + .SetSamples(std::vector{}) + .SetTimeDeltas(std::vector{}); consoleProfileFinished.SetId("11").SetLocation(std::move(location)).SetProfile(std::move(profile)).SetTitle("001"); Local object1 = consoleProfileFinished.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); @@ -415,7 +406,7 @@ HWTEST_F_L0(DebuggerEventsTest, ConsoleProfileFinishedToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(result), "11"); + EXPECT_EQ(DebuggerApi::ToStdString(result), "11"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "location"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); @@ -433,12 +424,11 @@ HWTEST_F_L0(DebuggerEventsTest, ConsoleProfileFinishedToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(result), "001"); + EXPECT_EQ(DebuggerApi::ToStdString(result), "001"); } HWTEST_F_L0(DebuggerEventsTest, ConsoleProfileStartedToObjectTest) { - CString msg; ConsoleProfileStarted consoleProfileStarted; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); @@ -455,14 +445,14 @@ HWTEST_F_L0(DebuggerEventsTest, ConsoleProfileStartedToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(result), "12"); + EXPECT_EQ(DebuggerApi::ToStdString(result), "12"); Local tmpObject = consoleProfileStarted.GetLocation()->ToObject(ecmaVm); tmpStr = StringRef::NewFromUtf8(ecmaVm, "scriptId"); ASSERT_TRUE(tmpObject->Has(ecmaVm, tmpStr)); Local tmpResult = tmpObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!tmpResult.IsEmpty() && !tmpResult->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(tmpResult), "17"); + EXPECT_EQ(DebuggerApi::ToStdString(tmpResult), "17"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "lineNumber"); ASSERT_TRUE(tmpObject->Has(ecmaVm, tmpStr)); tmpResult = tmpObject->Get(ecmaVm, tmpStr); @@ -473,17 +463,17 @@ HWTEST_F_L0(DebuggerEventsTest, ConsoleProfileStartedToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(result), "002"); + EXPECT_EQ(DebuggerApi::ToStdString(result), "002"); } HWTEST_F_L0(DebuggerEventsTest, PreciseCoverageDeltaUpdateToObjectTest) { - CString msg; PreciseCoverageDeltaUpdate preciseCoverageDeltaUpdate; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); + std::vector> v; preciseCoverageDeltaUpdate.SetOccasion("percise") - .SetResult(CVector>{}) + .SetResult(std::move(v)) .SetTimestamp(77); Local object1 = preciseCoverageDeltaUpdate.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); @@ -500,7 +490,7 @@ HWTEST_F_L0(DebuggerEventsTest, PreciseCoverageDeltaUpdateToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(result), "percise"); + EXPECT_EQ(DebuggerApi::ToStdString(result), "percise"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "result"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -510,11 +500,10 @@ HWTEST_F_L0(DebuggerEventsTest, PreciseCoverageDeltaUpdateToObjectTest) HWTEST_F_L0(DebuggerEventsTest, HeapStatsUpdateToObjectTest) { - CString msg; HeapStatsUpdate heapStatsUpdate; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); - heapStatsUpdate.SetStatsUpdate(CVector {}); + heapStatsUpdate.SetStatsUpdate(std::vector {}); Local object1 = heapStatsUpdate.ToObject(ecmaVm); Local result = object1->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); @@ -530,7 +519,6 @@ HWTEST_F_L0(DebuggerEventsTest, HeapStatsUpdateToObjectTest) HWTEST_F_L0(DebuggerEventsTest, LastSeenObjectIdToObjectTest) { - CString msg; LastSeenObjectId lastSeenObjectId; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); @@ -555,7 +543,6 @@ HWTEST_F_L0(DebuggerEventsTest, LastSeenObjectIdToObjectTest) HWTEST_F_L0(DebuggerEventsTest, ReportHeapSnapshotProgressToObjectTest) { - CString msg; ReportHeapSnapshotProgress reportHeapSnapshotProgress; Local tmpStr = StringRef::NewFromUtf8(ecmaVm, "params"); diff --git a/ecmascript/tooling/test/debugger_params_test.cpp b/ecmascript/tooling/test/debugger_params_test.cpp index 42ee1f58f0..d08694f2b0 100644 --- a/ecmascript/tooling/test/debugger_params_test.cpp +++ b/ecmascript/tooling/test/debugger_params_test.cpp @@ -67,43 +67,43 @@ protected: HWTEST_F_L0(DebuggerParamsTest, StartSamplingParamsCreateTest) { - CString msg; + std::string msg; std::unique_ptr startSamplingData; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; startSamplingData = StartSamplingParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(startSamplingData, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; startSamplingData = StartSamplingParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(startSamplingData, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; startSamplingData = StartSamplingParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(startSamplingData, nullptr); EXPECT_EQ(startSamplingData->GetSamplingInterval(), 32768); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; startSamplingData = StartSamplingParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(startSamplingData, nullptr); EXPECT_EQ(startSamplingData->GetSamplingInterval(), 32768); // abnormal params of params.sub-key=["samplingInterval":true] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"samplingInterval":true}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"samplingInterval":true}})"; startSamplingData = StartSamplingParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(startSamplingData, nullptr); // abnormal params of params.sub-key=["samplingInterval":true] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"samplingInterval":"Test"}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"samplingInterval":"Test"}})"; startSamplingData = StartSamplingParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(startSamplingData, nullptr); // abnormal params of params.sub-key = [ "size"=100,"nodeId"=1,"ordinal"=10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"samplingInterval":1000}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"samplingInterval":1000}})"; startSamplingData = StartSamplingParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(startSamplingData, nullptr); EXPECT_EQ(startSamplingData->GetSamplingInterval(), 1000); @@ -111,11 +111,11 @@ HWTEST_F_L0(DebuggerParamsTest, StartSamplingParamsCreateTest) HWTEST_F_L0(DebuggerParamsTest, StartSamplingParamsToObjectTest) { - CString msg; + std::string msg; std::unique_ptr startSamplingData; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"samplingInterval":1000}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"samplingInterval":1000}})"; startSamplingData = StartSamplingParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(startSamplingData, nullptr); Local object = startSamplingData->ToObject(ecmaVm); @@ -129,43 +129,43 @@ HWTEST_F_L0(DebuggerParamsTest, StartSamplingParamsToObjectTest) HWTEST_F_L0(DebuggerParamsTest, StartTrackingHeapObjectsParamsCreateTest) { - CString msg; + std::string msg; std::unique_ptr objectData; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; objectData = StartTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; objectData = StartTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; objectData = StartTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); ASSERT_FALSE(objectData->GetTrackAllocations()); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; objectData = StartTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); ASSERT_FALSE(objectData->GetTrackAllocations()); // abnormal params of params.sub-key=["trackAllocations":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"trackAllocations":10}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"trackAllocations":10}})"; objectData = StartTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of params.sub-key=["trackAllocations":"Test"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"trackAllocations":"Test"}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"trackAllocations":"Test"}})"; objectData = StartTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of params.sub-key=["trackAllocations":true] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"trackAllocations":true}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"trackAllocations":true}})"; objectData = StartTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); ASSERT_TRUE(objectData->GetTrackAllocations()); @@ -173,11 +173,11 @@ HWTEST_F_L0(DebuggerParamsTest, StartTrackingHeapObjectsParamsCreateTest) HWTEST_F_L0(DebuggerParamsTest, StartTrackingHeapObjectsParamsToObjectTest) { - CString msg; + std::string msg; std::unique_ptr startTrackingData; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"trackAllocations":true}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"trackAllocations":true}})"; startTrackingData = StartTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(startTrackingData, nullptr); Local object = startTrackingData->ToObject(ecmaVm); @@ -191,21 +191,21 @@ HWTEST_F_L0(DebuggerParamsTest, StartTrackingHeapObjectsParamsToObjectTest) HWTEST_F_L0(DebuggerParamsTest, StopTrackingHeapObjectsParamsCreateTest) { - CString msg; + std::string msg; std::unique_ptr objectData; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; objectData = StopTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; objectData = StopTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; objectData = StopTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); ASSERT_FALSE(objectData->GetReportProgress()); @@ -213,28 +213,28 @@ HWTEST_F_L0(DebuggerParamsTest, StopTrackingHeapObjectsParamsCreateTest) ASSERT_FALSE(objectData->GetCaptureNumericValue()); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; objectData = StopTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); ASSERT_FALSE(objectData->GetReportProgress()); ASSERT_FALSE(objectData->GetTreatGlobalObjectsAsRoots()); ASSERT_FALSE(objectData->GetCaptureNumericValue()); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "reportProgress":10, "treatGlobalObjectsAsRoots":10, "captureNumericValue":10}})"; objectData = StopTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "reportProgress":"Test", "treatGlobalObjectsAsRoots":"Test", "captureNumericValue":"Test"}})"; objectData = StopTrackingHeapObjectsParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "reportProgress":true, "treatGlobalObjectsAsRoots":true, "captureNumericValue":true}})"; @@ -247,11 +247,11 @@ HWTEST_F_L0(DebuggerParamsTest, StopTrackingHeapObjectsParamsCreateTest) HWTEST_F_L0(DebuggerParamsTest, StopTrackingHeapObjectsParamsToObjectTest) { - CString msg; + std::string msg; std::unique_ptr stopTrackingData; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "reportProgress":true, "treatGlobalObjectsAsRoots":true, "captureNumericValue":true}})"; @@ -280,41 +280,41 @@ HWTEST_F_L0(DebuggerParamsTest, StopTrackingHeapObjectsParamsToObjectTest) HWTEST_F_L0(DebuggerParamsTest, AddInspectedHeapObjectParamsCreateTest) { - CString msg; + std::string msg; std::unique_ptr objectData; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; objectData = AddInspectedHeapObjectParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; objectData = AddInspectedHeapObjectParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; objectData = AddInspectedHeapObjectParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; objectData = AddInspectedHeapObjectParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of params.sub-key=["heapObjectId":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"heapObjectId":10}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"heapObjectId":10}})"; objectData = AddInspectedHeapObjectParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of params.sub-key=["heapObjectId":true] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"heapObjectId":true}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"heapObjectId":true}})"; objectData = AddInspectedHeapObjectParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of params.sub-key=["heapObjectId":“10”] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"heapObjectId":"10"}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"heapObjectId":"10"}})"; objectData = AddInspectedHeapObjectParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); EXPECT_EQ((int)objectData->GetHeapObjectId(), 10); @@ -322,11 +322,11 @@ HWTEST_F_L0(DebuggerParamsTest, AddInspectedHeapObjectParamsCreateTest) HWTEST_F_L0(DebuggerParamsTest, AddInspectedHeapObjectParamsToObjectTest) { - CString msg; + std::string msg; std::unique_ptr objectData; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"heapObjectId":"10"}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"heapObjectId":"10"}})"; objectData = AddInspectedHeapObjectParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); Local object = objectData->ToObject(ecmaVm); @@ -335,46 +335,46 @@ HWTEST_F_L0(DebuggerParamsTest, AddInspectedHeapObjectParamsToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); Local result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(result), "10"); + EXPECT_EQ(DebuggerApi::ToStdString(result), "10"); } HWTEST_F_L0(DebuggerParamsTest, GetHeapObjectIdParamsCreateTest) { - CString msg; + std::string msg; std::unique_ptr objectData; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; objectData = GetHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; objectData = GetHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; objectData = GetHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; objectData = GetHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of params.sub-key=["objectId":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":10}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":10}})"; objectData = GetHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of params.sub-key=["objectId":true] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":true}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":true}})"; objectData = GetHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of params.sub-key=["objectId":“10”] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":"10"}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":"10"}})"; objectData = GetHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); EXPECT_EQ((int)objectData->GetObjectId(), 10); @@ -382,11 +382,11 @@ HWTEST_F_L0(DebuggerParamsTest, GetHeapObjectIdParamsCreateTest) HWTEST_F_L0(DebuggerParamsTest, GetHeapObjectIdParamsToObjectTest) { - CString msg; + std::string msg; std::unique_ptr objectData; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":"10"}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":"10"}})"; objectData = GetHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); Local object = objectData->ToObject(ecmaVm); @@ -395,52 +395,52 @@ HWTEST_F_L0(DebuggerParamsTest, GetHeapObjectIdParamsToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); Local result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(result), "10"); + EXPECT_EQ(DebuggerApi::ToStdString(result), "10"); } HWTEST_F_L0(DebuggerParamsTest, GetObjectByHeapObjectIdParamsCreateTest) { - CString msg; + std::string msg; std::unique_ptr objectData; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; objectData = GetObjectByHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; objectData = GetObjectByHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; objectData = GetObjectByHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; objectData = GetObjectByHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of params.sub-key=["objectId":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":10}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":10}})"; objectData = GetObjectByHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of params.sub-key=["objectId":true] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":"10", "objectGroup":10}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":"10", "objectGroup":10}})"; objectData = GetObjectByHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of params.sub-key=["objectId":“10”] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":"10"}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":"10"}})"; objectData = GetObjectByHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); EXPECT_EQ((int)objectData->GetObjectId(), 10); ASSERT_FALSE(objectData->HasObjectGroup()); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":"10", "objectGroup":"groupname"}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":"10", "objectGroup":"groupname"}})"; objectData = GetObjectByHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); EXPECT_EQ((int)objectData->GetObjectId(), 10); @@ -449,11 +449,11 @@ HWTEST_F_L0(DebuggerParamsTest, GetObjectByHeapObjectIdParamsCreateTest) HWTEST_F_L0(DebuggerParamsTest, GetObjectByHeapObjectIdParamsToObjectTest) { - CString msg; + std::string msg; std::unique_ptr objectData; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":"10", "objectGroup":"groupname"}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"objectId":"10", "objectGroup":"groupname"}})"; objectData = GetObjectByHeapObjectIdParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); Local object = objectData->ToObject(ecmaVm); @@ -462,55 +462,55 @@ HWTEST_F_L0(DebuggerParamsTest, GetObjectByHeapObjectIdParamsToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); Local result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(result), "10"); + EXPECT_EQ(DebuggerApi::ToStdString(result), "10"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "objectGroup"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(result), "groupname"); + EXPECT_EQ(DebuggerApi::ToStdString(result), "groupname"); } HWTEST_F_L0(DebuggerParamsTest, StartPreciseCoverageParamCreateTest) { - CString msg; + std::string msg; std::unique_ptr objectData; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; objectData = StartPreciseCoverageParam::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; objectData = StartPreciseCoverageParam::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; objectData = StartPreciseCoverageParam::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; objectData = StartPreciseCoverageParam::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callCount":8, "detailed":8, "allowTriggeredUpdates":8}})"; objectData = StartPreciseCoverageParam::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callCount":"Test", "detailed":"Test", "allowTriggeredUpdates":"Test"}})"; objectData = StartPreciseCoverageParam::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callCount":true, "detailed":true, "allowTriggeredUpdates":true}})"; @@ -523,11 +523,11 @@ HWTEST_F_L0(DebuggerParamsTest, StartPreciseCoverageParamCreateTest) HWTEST_F_L0(DebuggerParamsTest, StartPreciseCoverageParamToObjectTest) { - CString msg; + std::string msg; std::unique_ptr startTrackingData; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callCount":true, "detailed":true, "allowTriggeredUpdates":true}})"; @@ -556,35 +556,35 @@ HWTEST_F_L0(DebuggerParamsTest, StartPreciseCoverageParamToObjectTest) HWTEST_F_L0(DebuggerParamsTest, SetSamplingIntervalParamsCreateTest) { - CString msg; + std::string msg; std::unique_ptr objectData; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; objectData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; objectData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; objectData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; objectData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "interval":"500"}})"; objectData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(objectData, nullptr); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"interval":500}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"interval":500}})"; objectData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(objectData, nullptr); EXPECT_EQ(objectData->GetInterval(), 500); @@ -592,11 +592,11 @@ HWTEST_F_L0(DebuggerParamsTest, SetSamplingIntervalParamsCreateTest) HWTEST_F_L0(DebuggerParamsTest, SetSamplingIntervalParamsToObjectTest) { - CString msg; + std::string msg; std::unique_ptr setSamplingIntervalData; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"interval":500}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"interval":500}})"; setSamplingIntervalData = SetSamplingIntervalParams::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(setSamplingIntervalData, nullptr); Local object = setSamplingIntervalData->ToObject(ecmaVm); diff --git a/ecmascript/tooling/test/debugger_returns_test.cpp b/ecmascript/tooling/test/debugger_returns_test.cpp index ed8a56030f..ac261edc4a 100644 --- a/ecmascript/tooling/test/debugger_returns_test.cpp +++ b/ecmascript/tooling/test/debugger_returns_test.cpp @@ -69,12 +69,12 @@ HWTEST_F_L0(DebuggerReturnsTest, EnableReturnsToObjectTest) ASSERT_TRUE(enableObject->Has(ecmaVm, tmpStr)); Local result = enableObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(CString("100"), DebuggerApi::ToCString(result)); + EXPECT_EQ(std::string("100"), DebuggerApi::ToStdString(result)); } HWTEST_F_L0(DebuggerReturnsTest, SetBreakpointByUrlReturnsToObjectTest) { - auto locations = CVector>(); + auto locations = std::vector>(); std::unique_ptr location = std::make_unique(); location->SetScriptId(1); locations.emplace_back(std::move(location)); @@ -88,7 +88,7 @@ HWTEST_F_L0(DebuggerReturnsTest, SetBreakpointByUrlReturnsToObjectTest) ASSERT_TRUE(setObject->Has(ecmaVm, tmpStr)); Local result = setObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(CString("11"), DebuggerApi::ToCString(result)); + EXPECT_EQ(std::string("11"), DebuggerApi::ToStdString(result)); } HWTEST_F_L0(DebuggerReturnsTest, EvaluateOnCallFrameReturnsToObjectTest) @@ -114,7 +114,7 @@ HWTEST_F_L0(DebuggerReturnsTest, EvaluateOnCallFrameReturnsToObjectTest) HWTEST_F_L0(DebuggerReturnsTest, GetPossibleBreakpointsReturnsToObjectTest) { - auto locations = CVector>(); + auto locations = std::vector>(); std::unique_ptr breakLocation = std::make_unique(); std::unique_ptr getPossibleBreakpointsReturns = std::make_unique (std::move(locations)); @@ -136,18 +136,18 @@ HWTEST_F_L0(DebuggerReturnsTest, GetScriptSourceReturnsToObjectTest) ASSERT_TRUE(scriptObject->Has(ecmaVm, tmpStr)); Local result = scriptObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(CString("source_1"), DebuggerApi::ToCString(result)); + EXPECT_EQ(std::string("source_1"), DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "bytecode"); ASSERT_TRUE(scriptObject->Has(ecmaVm, tmpStr)); result = scriptObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(CString("bytecode_1"), DebuggerApi::ToCString(result)); + EXPECT_EQ(std::string("bytecode_1"), DebuggerApi::ToStdString(result)); } HWTEST_F_L0(DebuggerReturnsTest, RestartFrameReturnsToObjectTest) { - auto callFrames = CVector>(); + auto callFrames = std::vector>(); std::unique_ptr callFrame = std::make_unique(); std::unique_ptr restartFrameReturns = std::make_unique (std::move(callFrames)); @@ -170,7 +170,7 @@ HWTEST_F_L0(DebuggerReturnsTest, SetBreakpointReturnsToObjectTest) ASSERT_TRUE(breakObject->Has(ecmaVm, tmpStr)); Local result = breakObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(CString("breakpointId_1"), DebuggerApi::ToCString(result)); + EXPECT_EQ(std::string("breakpointId_1"), DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "actualLocation"); ASSERT_TRUE(breakObject->Has(ecmaVm, tmpStr)); @@ -189,12 +189,12 @@ HWTEST_F_L0(DebuggerReturnsTest, SetInstrumentationBreakpointReturnsToObjectTest ASSERT_TRUE(instrumentationObject->Has(ecmaVm, tmpStr)); Local result = instrumentationObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(CString("111"), DebuggerApi::ToCString(result)); + EXPECT_EQ(std::string("111"), DebuggerApi::ToStdString(result)); } HWTEST_F_L0(DebuggerReturnsTest, SetScriptSourceReturnsToObjectTest) { - auto callFrames = CVector>(); + auto callFrames = std::vector>(); std::unique_ptr callFrame = std::make_unique(); std::unique_ptr exceptionDetails = std::make_unique(); std::unique_ptr setScriptSourceReturns = std::make_unique @@ -213,7 +213,7 @@ HWTEST_F_L0(DebuggerReturnsTest, SetScriptSourceReturnsToObjectTest) HWTEST_F_L0(DebuggerReturnsTest, GetPropertiesReturnsToObjectTest) { - auto descriptor = CVector>(); + auto descriptor = std::vector>(); std::unique_ptr propertyDescriptor = std::make_unique(); std::unique_ptr exceptionDetails = std::make_unique(); std::unique_ptr getPropertiesReturns = std::make_unique @@ -229,14 +229,14 @@ HWTEST_F_L0(DebuggerReturnsTest, GetPropertiesReturnsToObjectTest) ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); ASSERT_TRUE(result->IsArray(ecmaVm)); - auto internalDescripties = CVector>(); + auto internalDescripties = std::vector>(); std::unique_ptr internalPropertyDescriptor = std::make_unique(); internalPropertyDescriptor->SetName("filename1"); internalDescripties.emplace_back(std::move(internalPropertyDescriptor)); ASSERT_EQ(internalDescripties.back()->GetName(), "filename1"); - auto privateProperties = CVector>(); + auto privateProperties = std::vector>(); std::unique_ptr privatePropertyDescriptor = std::make_unique(); privatePropertyDescriptor->SetName("filename2"); @@ -268,7 +268,7 @@ HWTEST_F_L0(DebuggerReturnsTest, GetHeapObjectIdReturnsToObjectTest) Local result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(CString("10"), DebuggerApi::ToCString(result)); + EXPECT_EQ(std::string("10"), DebuggerApi::ToStdString(result)); } HWTEST_F_L0(DebuggerReturnsTest, GetObjectByHeapObjectIdReturnsToObjectTest) @@ -322,7 +322,7 @@ HWTEST_F_L0(DebuggerReturnsTest, GetHeapUsageReturnsToObjectTest) HWTEST_F_L0(DebuggerReturnsTest, GetBestEffortCoverageReturnsToObjectTest) { - auto result = CVector>(); + auto result = std::vector>(); std::unique_ptr scriptCoverage = std::make_unique(); std::unique_ptr getBestEffortCoverageReturns = std::make_unique(std::move(result)); @@ -349,7 +349,7 @@ HWTEST_F_L0(DebuggerReturnsTest, StartPreciseCoverageReturnsToObjectTest) HWTEST_F_L0(DebuggerReturnsTest, TakePreciseCoverageReturnsToObjectTest) { - auto coverage = CVector>(); + auto coverage = std::vector>(); std::unique_ptr takePreciseCoverageReturns = std::make_unique(std::move(coverage), 1001); ASSERT_NE(takePreciseCoverageReturns, nullptr); @@ -370,7 +370,7 @@ HWTEST_F_L0(DebuggerReturnsTest, TakePreciseCoverageReturnsToObjectTest) HWTEST_F_L0(DebuggerReturnsTest, TakeTypeProfileturnsToObjectTest) { - auto result = CVector>(); + auto result = std::vector>(); std::unique_ptr scriptTypeProfile = std::make_unique(); std::unique_ptr takeTypeProfileturns = std::make_unique (std::move(result)); diff --git a/ecmascript/tooling/test/debugger_types_test.cpp b/ecmascript/tooling/test/debugger_types_test.cpp index fe2578cab5..b7a44fe7ae 100644 --- a/ecmascript/tooling/test/debugger_types_test.cpp +++ b/ecmascript/tooling/test/debugger_types_test.cpp @@ -67,60 +67,60 @@ protected: HWTEST_F_L0(DebuggerTypesTest, RemoteObjectCreateTest) { - CString msg; + std::string msg; std::unique_ptr remoteObject; Local tmpStr; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // abnormal params of params.sub-key = [ type = 100, ] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":100}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // abnormal params of params.sub-key = [ type = [ "sub": "test" ] }, ] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":100}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // normal params of params.sub-key = [ type = "object", ] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"("}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"("}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(remoteObject, nullptr); EXPECT_EQ(ObjectType::Object, remoteObject->GetType()); // abnormal params of params.sub-key = [ type = "object", subtype = "unknown"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","subtype":"unknown"}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // abnormal params of params.sub-key = [ type = "object", subtype = 100] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","subtype":100}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // normal params of params.sub-key = [ type = "object", subtype = "array"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","subtype":")" + ObjectSubType::Array + R"("}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(remoteObject, nullptr); @@ -129,19 +129,19 @@ HWTEST_F_L0(DebuggerTypesTest, RemoteObjectCreateTest) EXPECT_EQ(ObjectSubType::Array, remoteObject->GetSubType()); // abnormal params of params.sub-key = [ type = "object", className = 100] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","className":100}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // abnormal params of params.sub-key = [ type = "object", className = {"xx":"yy"}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","className":{"xx":"yy"}}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // normal params of params.sub-key = [ type = "object", className = "TestClass"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","className":"TestClass"}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(remoteObject, nullptr); @@ -150,7 +150,7 @@ HWTEST_F_L0(DebuggerTypesTest, RemoteObjectCreateTest) EXPECT_EQ("TestClass", remoteObject->GetClassName()); // normal params of params.sub-key = [ type = "object", value = 100] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","value":100}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(remoteObject, nullptr); @@ -159,7 +159,7 @@ HWTEST_F_L0(DebuggerTypesTest, RemoteObjectCreateTest) EXPECT_EQ(Local(remoteObject->GetValue())->Value(), 100.0); // normal params of params.sub-key = [ type = "object", value = {"xx":"yy"}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","value":{"xx":"yy"}}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(remoteObject, nullptr); @@ -170,28 +170,28 @@ HWTEST_F_L0(DebuggerTypesTest, RemoteObjectCreateTest) ASSERT_TRUE(Local(remoteObject->GetValue())->Has(ecmaVm, Local(tmpStr))); // normal params of params.sub-key = [ type = "object", value = "Test"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","value":"Test"}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(remoteObject, nullptr); EXPECT_EQ(ObjectType::Object, remoteObject->GetType()); ASSERT_TRUE(remoteObject->HasValue()); - EXPECT_EQ("Test", DebuggerApi::ToCString(remoteObject->GetValue())); + EXPECT_EQ("Test", DebuggerApi::ToStdString(remoteObject->GetValue())); // abnormal params of params.sub-key = [ type = "object", unserializableValue = 100] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","unserializableValue":100}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // abnormal params of params.sub-key = [ type = "object", unserializableValue = {"xx":"yy"}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","unserializableValue":{"xx":"yy"}}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // normal params of params.sub-key = [ type = "object", unserializableValue = "TestClass"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","unserializableValue":"Test"}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(remoteObject, nullptr); @@ -200,19 +200,19 @@ HWTEST_F_L0(DebuggerTypesTest, RemoteObjectCreateTest) EXPECT_EQ("Test", remoteObject->GetUnserializableValue()); // abnormal params of params.sub-key = [ type = "object", description = 100] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","description":100}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // abnormal params of params.sub-key = [ type = "object", description = {"xx":"yy"}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","description":{"xx":"yy"}}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // normal params of params.sub-key = [ type = "object", description = "Test"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","description":"Test"}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(remoteObject, nullptr); @@ -221,19 +221,19 @@ HWTEST_F_L0(DebuggerTypesTest, RemoteObjectCreateTest) EXPECT_EQ("Test", remoteObject->GetDescription()); // abnormal params of params.sub-key = [ type = "object", objectId = 100] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","objectId":100}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // abnormal params of params.sub-key = [ type = "object", objectId = {"xx":"yy"}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","objectId":{"xx":"yy"}}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(remoteObject, nullptr); // normal params of params.sub-key = [ type = "object", objectId = "id_1"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","objectId":"1"}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(remoteObject, nullptr); @@ -244,14 +244,13 @@ HWTEST_F_L0(DebuggerTypesTest, RemoteObjectCreateTest) HWTEST_F_L0(DebuggerTypesTest, RemoteObjectToObjectTest) { - CString msg; + std::string msg; std::unique_ptr remoteObject; Local tmpStr; - msg = - CString() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + R"(","subtype":")" + - ObjectSubType::Array + - R"(","className":"TestClass","value":100,"unserializableValue":"Test","description":"Test","objectId":"1"}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"type":")" + ObjectType::Object + + R"(", "subtype":")" + ObjectSubType::Array + + R"(","className":"TestClass","value":100, "unserializableValue":"Test","description":"Test","objectId":"1"}})"; remoteObject = RemoteObject::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(remoteObject, nullptr); Local object = remoteObject->ToObject(ecmaVm); @@ -260,17 +259,17 @@ HWTEST_F_L0(DebuggerTypesTest, RemoteObjectToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); Local result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(CString(ObjectType::Object.c_str()), DebuggerApi::ToCString(result)); + EXPECT_EQ(std::string(ObjectType::Object.c_str()), DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "subtype"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(CString(ObjectSubType::Array.c_str()), DebuggerApi::ToCString(result)); + EXPECT_EQ(std::string(ObjectSubType::Array.c_str()), DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "className"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("TestClass", DebuggerApi::ToCString(result)); + EXPECT_EQ("TestClass", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "value"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -280,94 +279,94 @@ HWTEST_F_L0(DebuggerTypesTest, RemoteObjectToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("Test", DebuggerApi::ToCString(result)); + EXPECT_EQ("Test", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "description"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("Test", DebuggerApi::ToCString(result)); + EXPECT_EQ("Test", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "objectId"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("1", DebuggerApi::ToCString(result)); + EXPECT_EQ("1", DebuggerApi::ToStdString(result)); } HWTEST_F_L0(DebuggerTypesTest, ExceptionDetailsCreateTest) { - CString msg; + std::string msg; std::unique_ptr exceptionMetaData; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of params.sub-key = [ exceptionId="Test","text"="text0","lineNumber"=10,"columnNumber"=20] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":"Test","text":"text0","lineNumber":10,"columnNumber":20}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of params.sub-key = [ exceptionId={"xx":"yy"},"text"="text0","lineNumber"=10,"columnNumber"=20] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":{"xx":"yy"},"text":"text0","lineNumber":10,"columnNumber":20}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of params.sub-key = [ exceptionId=3,"text"=10,"lineNumber"=10,"columnNumber"=20] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":10,"lineNumber":10,"columnNumber":20}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of params.sub-key = [ exceptionId=3,"text"=["text0"],"lineNumber"=10,"columnNumber"=20] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":["text0"],"lineNumber":10,"columnNumber":20}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of params.sub-key = [ exceptionId=3,"text"="text0","lineNumber"="10","columnNumber"=20] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":"10","columnNumber":20}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of params.sub-key = [ exceptionId=3,"text"="text0","lineNumber"=["10"],"columnNumber"=20] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":["10"],"columnNumber":20}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of params.sub-key = [ exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"="20"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":"20"}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of params.sub-key = [ exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=["20"]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":["20"]}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // normal params of params.sub-key = [ exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=20] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":20}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(exceptionMetaData, nullptr); @@ -378,21 +377,21 @@ HWTEST_F_L0(DebuggerTypesTest, ExceptionDetailsCreateTest) // abnormal params of params.sub-key = // [exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=20,"scriptId"=10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":20,"scriptId":10}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of params.sub-key = // [exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=20,"scriptId"=["10"]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":20,"scriptId":["10"]}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // normal params of params.sub-key = // [exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=20,"scriptId"="id0"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":20,"scriptId":"0"}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(exceptionMetaData, nullptr); @@ -404,21 +403,21 @@ HWTEST_F_L0(DebuggerTypesTest, ExceptionDetailsCreateTest) // abnormal params of params.sub-key = // [exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=20,"url"=10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":20,"url":10}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of params.sub-key = // [exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=20,"url"=["10"]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":20,"url":["10"]}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // normal params of params.sub-key = // [exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=20,"url"="url0"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":20,"url":"url0"}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(exceptionMetaData, nullptr); @@ -430,21 +429,21 @@ HWTEST_F_L0(DebuggerTypesTest, ExceptionDetailsCreateTest) // abnormal params of params.sub-key = // [exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=20,"exception"=10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":20,"exception":10}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of params.sub-key = // [exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=20,"exception"=["10"]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":20,"exception":["10"]}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // normal params of params.sub-key = // [exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=20,"exception"={}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":20,"exception":{"type":")" + ObjectType::Object + R"(","subtype":")" + ObjectSubType::Error + R"("}}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -460,21 +459,21 @@ HWTEST_F_L0(DebuggerTypesTest, ExceptionDetailsCreateTest) // abnormal params of params.sub-key = // [exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=20,"executionContextId"="10"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":20,"executionContextId":"10"}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // abnormal params of params.sub-key = // [exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=20,"executionContextId"=["10"]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":20,"executionContextId":["10"]}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(exceptionMetaData, nullptr); // normal params of params.sub-key = // [exceptionId=3,"text"="text0","lineNumber"=10,"columnNumber"=20,"executionContextId"=2] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":3,"text":"text0","lineNumber":10,"columnNumber":20,"executionContextId":2}})"; exceptionMetaData = ExceptionDetails::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(exceptionMetaData, nullptr); @@ -487,11 +486,11 @@ HWTEST_F_L0(DebuggerTypesTest, ExceptionDetailsCreateTest) HWTEST_F_L0(DebuggerTypesTest, ExceptionDetailsToObjectTest) { - CString msg; + std::string msg; std::unique_ptr exceptionMetaData; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "exceptionId":5,"text":"text0","lineNumber":10,"columnNumber":20,"scriptId":"100","url":"url0", "exception":{"type":")" + ObjectType::Object + R"(","subtype":")" + ObjectSubType::Error + R"("},"executionContextId":30}})"; @@ -508,7 +507,7 @@ HWTEST_F_L0(DebuggerTypesTest, ExceptionDetailsToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("text0", DebuggerApi::ToCString(result)); + EXPECT_EQ("text0", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "lineNumber"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -523,12 +522,12 @@ HWTEST_F_L0(DebuggerTypesTest, ExceptionDetailsToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("100", DebuggerApi::ToCString(result)); + EXPECT_EQ("100", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "url"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("url0", DebuggerApi::ToCString(result)); + EXPECT_EQ("url0", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "exception"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -538,12 +537,12 @@ HWTEST_F_L0(DebuggerTypesTest, ExceptionDetailsToObjectTest) ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); Local subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectType::Object.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectType::Object.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "subtype"); ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectSubType::Error.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectSubType::Error.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "executionContextId"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -553,81 +552,81 @@ HWTEST_F_L0(DebuggerTypesTest, ExceptionDetailsToObjectTest) HWTEST_F_L0(DebuggerTypesTest, InternalPropertyDescriptorCreateTest) { - CString msg; + std::string msg; std::unique_ptr internalPropertyDescriptor; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(internalPropertyDescriptor, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(internalPropertyDescriptor, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(internalPropertyDescriptor, nullptr); // abnormal params of unknown params.sub-key=["name":"name8"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name8","value":99}})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(internalPropertyDescriptor, nullptr); // abnormal params of unknown params.sub-key=["name":"name8"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name8","value":99}})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(internalPropertyDescriptor, nullptr); // abnormal params of unknown params.sub-key=["name":"name8","value":99] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name8","value":99}})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(internalPropertyDescriptor, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(internalPropertyDescriptor, nullptr); // abnormal params of unknown params.sub-key=["name":99] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name8","value":99}})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(internalPropertyDescriptor, nullptr); // abnormal params of unknown params.sub-key=["name":[99]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name8","value":[99]}})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(internalPropertyDescriptor, nullptr); // normal params of params.sub-key=["name":"name7"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name7"}})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(internalPropertyDescriptor, nullptr); EXPECT_EQ("name7", internalPropertyDescriptor->GetName()); // abnormal params of unknown params.sub-key=["name":"name8","value":{"type":"object","subtype":"map"}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name8","value":"99"}})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(internalPropertyDescriptor, nullptr); // abnormal params of unknown params.sub-key=["name":"name8","value":{"type":"object","subtype":"wrong"}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name8","value":{"type":")" + ObjectType::Object + R"(","subtype":"wrong"}}})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(internalPropertyDescriptor, nullptr); // normal params of params.sub-key=["name":"name8","value":{"type":"object","subtype":"map"}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name8","value":{"type":")" + ObjectType::Object + R"(","subtype":")" + ObjectSubType::Map + R"("}}})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -642,11 +641,11 @@ HWTEST_F_L0(DebuggerTypesTest, InternalPropertyDescriptorCreateTest) HWTEST_F_L0(DebuggerTypesTest, InternalPropertyDescriptorToObjectTest) { - CString msg; + std::string msg; std::unique_ptr internalPropertyDescriptor; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name8","value":{"type":")" + ObjectType::Object + R"(","subtype":")" + ObjectSubType::Map + R"("}}})"; internalPropertyDescriptor = InternalPropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -657,7 +656,7 @@ HWTEST_F_L0(DebuggerTypesTest, InternalPropertyDescriptorToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); Local result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("name8", DebuggerApi::ToCString(result)); + EXPECT_EQ("name8", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "value"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -667,89 +666,89 @@ HWTEST_F_L0(DebuggerTypesTest, InternalPropertyDescriptorToObjectTest) ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); Local subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectType::Object.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectType::Object.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "subtype"); ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectSubType::Map.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectSubType::Map.c_str()), DebuggerApi::ToStdString(subResult)); } HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorCreateTest) { - CString msg; + std::string msg; std::unique_ptr propertyDescriptor; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":10,"configurable":true,"enumerable":true] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":10,"configurable":true,"enumerable":true,"value":10}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":["name85"],"configurable":true,"enumerable":true] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":["name85"],"configurable":true,"enumerable":true,"value":10}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":"name8","configurable":10,"enumerable":true] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":10,"enumerable":true}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":"name8","configurable":"true","enumerable":true] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":"true","enumerable":true}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":10}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":"true"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":"true"}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"value":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"value":10}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"value":{"ee":"11"}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"value":{"ee":"11"}}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // normal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"value":{..}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"value":{"type":")" + ObjectType::Symbol + R"("}}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -762,19 +761,19 @@ HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorCreateTest) EXPECT_EQ(value->GetType(), ObjectType::Symbol); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"writable":98] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"writable":98}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"writable":[true]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"writable":[true]}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // normal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"writable":true] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"writable":true}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(propertyDescriptor, nullptr); @@ -784,19 +783,19 @@ HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorCreateTest) ASSERT_TRUE(propertyDescriptor->GetWritable()); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"get":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"get":10}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"get":[10]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"get":[10]}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // normal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"get":{}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"get":{"type":")" + ObjectType::Function + R"("}}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -809,19 +808,19 @@ HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorCreateTest) EXPECT_EQ(get->GetType(), ObjectType::Function); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"set":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"set":10}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"set":[10]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"set":[10]}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // normal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"set":{}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"set":{"type":")" + ObjectType::String + R"("}}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -834,19 +833,19 @@ HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorCreateTest) EXPECT_EQ(set->GetType(), ObjectType::String); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"wasThrown":98] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"wasThrown":98}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"wasThrown":[true]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"wasThrown":[true]}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // normal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"wasThrown":true] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"wasThrown":true}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(propertyDescriptor, nullptr); @@ -856,19 +855,19 @@ HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorCreateTest) ASSERT_TRUE(propertyDescriptor->GetWasThrown()); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"isOwn":98] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"isOwn":98}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"isOwn":[true]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"isOwn":[true]}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // normal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true,"isOwn":true] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"isOwn":true}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(propertyDescriptor, nullptr); @@ -878,19 +877,19 @@ HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorCreateTest) ASSERT_TRUE(propertyDescriptor->GetIsOwn()); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true, "symbol":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"symbol":10}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // abnormal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true, "symbol":[10]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"symbol":[10]}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(propertyDescriptor, nullptr); // normal params of params.sub-key=["name":"name8","configurable":true,"enumerable":true, "symbol":{}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name85","configurable":true,"enumerable":true,"symbol":{"type":")" + ObjectType::Wasm + R"("}}})"; propertyDescriptor = PropertyDescriptor::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -905,11 +904,11 @@ HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorCreateTest) HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorToObjectTest) { - CString msg; + std::string msg; std::unique_ptr propertyDescriptor; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "name":"name8","value":{"type":")" + ObjectType::Object + R"(","subtype":")" + ObjectSubType::Map + R"("}, "writable":true,"get":{"type":")" + @@ -925,7 +924,7 @@ HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); Local result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("name8", DebuggerApi::ToCString(result)); + EXPECT_EQ("name8", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "value"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -935,12 +934,12 @@ HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorToObjectTest) ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); Local subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectType::Object.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectType::Object.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "subtype"); ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectSubType::Map.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectSubType::Map.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "writable"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -955,12 +954,12 @@ HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorToObjectTest) ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectType::Object.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectType::Object.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "subtype"); ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectSubType::Regexp.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectSubType::Regexp.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "set"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -970,12 +969,12 @@ HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorToObjectTest) ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectType::Object.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectType::Object.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "subtype"); ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectSubType::Generator.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectSubType::Generator.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "configurable"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -1005,76 +1004,76 @@ HWTEST_F_L0(DebuggerTypesTest, PropertyDescriptorToObjectTest) ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectType::Object.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectType::Object.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "subtype"); ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectSubType::Proxy.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectSubType::Proxy.c_str()), DebuggerApi::ToStdString(subResult)); } HWTEST_F_L0(DebuggerTypesTest, LocationCreateTest) { - CString msg; + std::string msg; std::unique_ptr location; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; location = Location::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(location, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; location = Location::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(location, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; location = Location::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(location, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; location = Location::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(location, nullptr); // abnormal params of params.sub-key=["scriptId":10,"lineNumber":99] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":10,"lineNumber":99 }})"; location = Location::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(location, nullptr); // abnormal params of params.sub-key=["scriptId":["id3"],"lineNumber":99] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":["id3"],"lineNumber":99 }})"; location = Location::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(location, nullptr); // abnormal params of params.sub-key=["scriptId":"222","lineNumber":"99"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"222","lineNumber":"99" }})"; location = Location::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(location, nullptr); // abnormal params of params.sub-key=["scriptId":"222","lineNumber":[99]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"222","lineNumber":[99] }})"; location = Location::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(location, nullptr); // abnormal params of params.sub-key=["scriptId":"2","lineNumber":99,"columnNumber":"18"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"222","lineNumber":899,"columnNumber":"18" }})"; location = Location::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(location, nullptr); // normal params of params.sub-key=["scriptId":"2","lineNumber":99,"columnNumber":138] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"222","lineNumber":899,"columnNumber":138 }})"; location = Location::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -1084,7 +1083,7 @@ HWTEST_F_L0(DebuggerTypesTest, LocationCreateTest) EXPECT_EQ(location->GetColumn(), 138); // normal params of params.sub-key=["scriptId":"2122","lineNumber":8299] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"2122","lineNumber":8299 }})"; location = Location::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -1095,11 +1094,11 @@ HWTEST_F_L0(DebuggerTypesTest, LocationCreateTest) HWTEST_F_L0(DebuggerTypesTest, LocationToObjectTest) { - CString msg; + std::string msg; std::unique_ptr location; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"2","lineNumber":99,"columnNumber":18 }})"; location = Location::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -1110,7 +1109,7 @@ HWTEST_F_L0(DebuggerTypesTest, LocationToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); Local result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("2", DebuggerApi::ToCString(result)); + EXPECT_EQ("2", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "lineNumber"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -1125,80 +1124,80 @@ HWTEST_F_L0(DebuggerTypesTest, LocationToObjectTest) HWTEST_F_L0(DebuggerTypesTest, BreakLocationCreateTest) { - CString msg; + std::string msg; std::unique_ptr breakLocation; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(breakLocation, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(breakLocation, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(breakLocation, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(breakLocation, nullptr); // abnormal params of params.sub-key=["scriptId":10,"lineNumber":99] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":10,"lineNumber":99 }})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(breakLocation, nullptr); // abnormal params of params.sub-key=["scriptId":["id3"],"lineNumber":99] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":["id3"],"lineNumber":99 }})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(breakLocation, nullptr); // abnormal params of params.sub-key=["scriptId":"222","lineNumber":"99"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"222","lineNumber":"99" }})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(breakLocation, nullptr); // abnormal params of params.sub-key=["scriptId":"222","lineNumber":[99]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"222","lineNumber":[99] }})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(breakLocation, nullptr); // abnormal params of params.sub-key=["scriptId":"2","lineNumber":99,"columnNumber":"18"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"222","lineNumber":899,"columnNumber":"18" }})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(breakLocation, nullptr); // abnormal params of params.sub-key=["scriptId":"2","lineNumber":99,"columnNumber":"18","type":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"222","lineNumber":899,"columnNumber":"18","type":10 }})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(breakLocation, nullptr); // abnormal params of params.sub-key=["scriptId":"2","lineNumber":99,"columnNumber":"18","type":"ee"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"222","lineNumber":899,"columnNumber":"18","type":"ee" }})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(breakLocation, nullptr); // normal params of params.sub-key=["scriptId":"2","lineNumber":99,"columnNumber":138,"type":"return"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"222","lineNumber":899,"columnNumber":138,"type":"return" }})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -1209,7 +1208,7 @@ HWTEST_F_L0(DebuggerTypesTest, BreakLocationCreateTest) EXPECT_EQ("return", breakLocation->GetType()); // normal params of params.sub-key=["scriptId":"2122","lineNumber":8299] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"2122","lineNumber":8299 }})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -1220,11 +1219,11 @@ HWTEST_F_L0(DebuggerTypesTest, BreakLocationCreateTest) HWTEST_F_L0(DebuggerTypesTest, BreakLocationToObjectTest) { - CString msg; + std::string msg; std::unique_ptr breakLocation; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"12","lineNumber":919,"columnNumber":148,"type":"call" }})"; breakLocation = BreakLocation::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -1235,7 +1234,7 @@ HWTEST_F_L0(DebuggerTypesTest, BreakLocationToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); Local result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("12", DebuggerApi::ToCString(result)); + EXPECT_EQ("12", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "lineNumber"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -1250,77 +1249,77 @@ HWTEST_F_L0(DebuggerTypesTest, BreakLocationToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("call", DebuggerApi::ToCString(result)); + EXPECT_EQ("call", DebuggerApi::ToStdString(result)); } HWTEST_F_L0(DebuggerTypesTest, ScopeCreateTest) { - CString msg; + std::string msg; std::unique_ptr scope; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // abnormal params of params.sub-key=["type":"ss","object":{..}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "type":"ss","object":{"type":")" + ObjectType::Bigint + R"("}}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // abnormal params of params.sub-key=["type":12,"object":{..}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "type":12,"object":{"type":")" + ObjectType::Bigint + R"("}}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // abnormal params of params.sub-key=["type":"global","object":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "type":"global","object":10}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // abnormal params of params.sub-key=["type":"global","object":{..}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "type":"global","object":{"ww":")" + ObjectType::Bigint + R"("}}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // abnormal params of params.sub-key=["type":"global","object":{..},"name":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "type":"global","object":{"type":")" + ObjectType::Bigint + R"("},"name":10}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // abnormal params of params.sub-key=["type":"global","object":{..},"name":["10"]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "type":"global","object":{"type":")" + ObjectType::Bigint + R"("},"name":["10"]}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // normal params of params.sub-key=["type":"global","object":{..},"name":"name128"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "type":"global","object":{"type":")" + ObjectType::Bigint + R"("},"name":"name117"}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -1328,35 +1327,35 @@ HWTEST_F_L0(DebuggerTypesTest, ScopeCreateTest) EXPECT_EQ("name117", scope->GetName()); // abnormal params of params.sub-key=["type":"global","object":{..},"startLocation":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "type":"global","object":{"type":")" + ObjectType::Bigint + R"("},"startLocation":10}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // abnormal params of params.sub-key=["type":"global","object":{..},"startLocation":{"12":"34"}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "type":"global","object":{"type":")" + ObjectType::Bigint + R"("},"startLocation":{"12":"34"}}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // abnormal params of params.sub-key=["type":"global","object":{..},"endLocation":10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "type":"global","object":{"type":")" + ObjectType::Bigint + R"("},"endLocation":10}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // abnormal params of params.sub-key=["type":"global","object":{..},"endLocation":{"12":"34"}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "type":"global","object":{"type":")" + ObjectType::Bigint + R"("},"endLocation":{"12":"34"}}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scope, nullptr); // normal params of params.sub-key=["type":"global","object":{..}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "type":"global","object":{"type":")" + ObjectType::Bigint + R"("}}})"; scope = Scope::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); @@ -1369,11 +1368,11 @@ HWTEST_F_L0(DebuggerTypesTest, ScopeCreateTest) HWTEST_F_L0(DebuggerTypesTest, ScopeToObjectTest) { - CString msg; + std::string msg; std::unique_ptr scope; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "type":"global","object":{"type":")" + ObjectType::Object + R"(","subtype":")" + ObjectSubType::Dataview + R"("},"name":"name9", "startLocation":{"scriptId":"2","lineNumber":99}, @@ -1387,7 +1386,7 @@ HWTEST_F_L0(DebuggerTypesTest, ScopeToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); Local result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("global", DebuggerApi::ToCString(result)); + EXPECT_EQ("global", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "object"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -1397,17 +1396,17 @@ HWTEST_F_L0(DebuggerTypesTest, ScopeToObjectTest) ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); Local subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectType::Object.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectType::Object.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "subtype"); ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectSubType::Dataview.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectSubType::Dataview.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "name"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("name9", DebuggerApi::ToCString(result)); + EXPECT_EQ("name9", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "startLocation"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -1417,7 +1416,7 @@ HWTEST_F_L0(DebuggerTypesTest, ScopeToObjectTest) ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ("2", DebuggerApi::ToCString(subResult)); + EXPECT_EQ("2", DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "lineNumber"); ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); @@ -1432,7 +1431,7 @@ HWTEST_F_L0(DebuggerTypesTest, ScopeToObjectTest) ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ("13", DebuggerApi::ToCString(subResult)); + EXPECT_EQ("13", DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "lineNumber"); ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); @@ -1442,31 +1441,31 @@ HWTEST_F_L0(DebuggerTypesTest, ScopeToObjectTest) HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) { - CString msg; + std::string msg; std::unique_ptr callFrame; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; callFrame = CallFrame::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(callFrame, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; callFrame = CallFrame::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(callFrame, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; callFrame = CallFrame::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(callFrame, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; callFrame = CallFrame::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":10,"functionName":"name0", "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1476,7 +1475,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":["0"],"functionName":"name0", "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1486,7 +1485,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":10, "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1496,7 +1495,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":["name0"], "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1506,7 +1505,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0","functionLocation":10, "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1516,7 +1515,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0","functionLocation":{"scriptId11":"id5","lineNumber":19}, "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1526,7 +1525,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0", "location":{"scriptId2":"id5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1536,7 +1535,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0", "location":10,"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1546,7 +1545,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0", "location":{"scriptId":"5","lineNumber":19},"url":10,"scopeChain": [{"type":"global","object":{"type":")" + @@ -1556,7 +1555,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0", "location":{"scriptId":"5","lineNumber":19},"url":{"url":"url7"},"scopeChain": [{"type":"global","object":{"type":")" + @@ -1566,7 +1565,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0", "location":{"scriptId":"5","lineNumber":19}, "url":"url7","scopeChain":10,"this":{"type":")" + ObjectType::Object + R"(","subtype":")" + ObjectSubType::V128 + R"("}}})"; @@ -1574,7 +1573,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0", "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": {"type":"22","object":{"type":")" + @@ -1584,7 +1583,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0", "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1594,7 +1593,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0", "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1604,7 +1603,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0", "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1615,7 +1614,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0", "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1626,7 +1625,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(callFrame, nullptr); // normal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0", "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1641,7 +1640,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) EXPECT_EQ(5U, location->GetScriptId()); EXPECT_EQ(location->GetLine(), 19); EXPECT_EQ("url7", callFrame->GetUrl()); - const CVector> *scopeChain = callFrame->GetScopeChain(); + const std::vector> *scopeChain = callFrame->GetScopeChain(); EXPECT_EQ(scopeChain->size(), 2U); RemoteObject *thisObj = callFrame->GetThis(); ASSERT_NE(thisObj, nullptr); @@ -1650,7 +1649,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) ASSERT_FALSE(callFrame->HasReturnValue()); // normal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"10","functionName":"name0","functionLocation":{"scriptId":"3","lineNumber":16}, "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1682,11 +1681,11 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameCreateTest) HWTEST_F_L0(DebuggerTypesTest, CallFrameToObjectTest) { - CString msg; + std::string msg; std::unique_ptr callFrame; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrameId":"0","functionName":"name0","functionLocation":{"scriptId":"3","lineNumber":16}, "location":{"scriptId":"5","lineNumber":19},"url":"url7","scopeChain": [{"type":"global","object":{"type":")" + @@ -1701,12 +1700,12 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); Local result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("0", DebuggerApi::ToCString(result)); + EXPECT_EQ("0", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "functionName"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("name0", DebuggerApi::ToCString(result)); + EXPECT_EQ("name0", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "functionLocation"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -1716,7 +1715,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameToObjectTest) ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); Local subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ("3", DebuggerApi::ToCString(subResult)); + EXPECT_EQ("3", DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "lineNumber"); ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); @@ -1731,7 +1730,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameToObjectTest) ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ("5", DebuggerApi::ToCString(subResult)); + EXPECT_EQ("5", DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "lineNumber"); ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); @@ -1741,7 +1740,7 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ("url7", DebuggerApi::ToCString(result)); + EXPECT_EQ("url7", DebuggerApi::ToStdString(result)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "scopeChain"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -1758,12 +1757,12 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameToObjectTest) ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectType::Object.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectType::Object.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "subtype"); ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectSubType::Iterator.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectSubType::Iterator.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "returnValue"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -1773,53 +1772,53 @@ HWTEST_F_L0(DebuggerTypesTest, CallFrameToObjectTest) ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectType::Object.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectType::Object.c_str()), DebuggerApi::ToStdString(subResult)); tmpStr = StringRef::NewFromUtf8(ecmaVm, "subtype"); ASSERT_TRUE(Local(result)->Has(ecmaVm, Local(tmpStr))); subResult = Local(result)->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(CString(ObjectSubType::I64.c_str()), DebuggerApi::ToCString(subResult)); + EXPECT_EQ(std::string(ObjectSubType::I64.c_str()), DebuggerApi::ToStdString(subResult)); } HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileSampleCreateTest) { - CString msg; + std::string msg; std::unique_ptr object; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; object = SamplingHeapProfileSample::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; object = SamplingHeapProfileSample::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; object = SamplingHeapProfileSample::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; object = SamplingHeapProfileSample::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); // abnormal params of params.sub-key = [ "size"="Test","nodeId"="Test","ordinal"="Test"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "size":"Test","nodeId":"Test","ordinal":"Test"}})"; object = SamplingHeapProfileSample::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); // abnormal params of params.sub-key = [ "size"={"xx":"yy"},"nodeId"={"xx":"yy"},"ordinal"={"xx":"yy"}] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "size":{"xx":"yy"},"nodeId":{"xx":"yy"},"ordinal":{"xx":"yy"}}})"; object = SamplingHeapProfileSample::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); // abnormal params of params.sub-key = [ "size"=100,"nodeId"=1,"ordinal"=10] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"size":100,"nodeId":1,"ordinal":10}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"size":100,"nodeId":1,"ordinal":10}})"; object = SamplingHeapProfileSample::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(object, nullptr); EXPECT_EQ(object->GetSize(), 100); @@ -1829,11 +1828,11 @@ HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileSampleCreateTest) HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileSampleToObjectTest) { - CString msg; + std::string msg; std::unique_ptr samplingHeapProfileSampleData; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"size":100,"nodeId":1,"ordinal":10}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"size":100,"nodeId":1,"ordinal":10}})"; samplingHeapProfileSampleData = SamplingHeapProfileSample::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(samplingHeapProfileSampleData, nullptr); Local object = samplingHeapProfileSampleData->ToObject(ecmaVm); @@ -1859,30 +1858,30 @@ HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileSampleToObjectTest) HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileNodeCreateTest) { - CString msg; + std::string msg; std::unique_ptr object; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; object = SamplingHeapProfileNode::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; object = SamplingHeapProfileNode::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; object = SamplingHeapProfileNode::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; object = SamplingHeapProfileNode::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrame": {"functionName":"Create", "scriptId":"10", "url":"url3", "lineNumber":100, "columnNumber":20}, "selfSize":10, "id":5, @@ -1900,18 +1899,18 @@ HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileNodeCreateTest) EXPECT_EQ(object->GetSelfSize(), 10); EXPECT_EQ(object->GetId(), 5); - const CVector> *children = object->GetChildren(); + const std::vector> *children = object->GetChildren(); ASSERT_NE(children, nullptr); EXPECT_EQ((int)children->size(), 0); } HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileNodeToObjectTest) { - CString msg; + std::string msg; std::unique_ptr samplingHeapProfileNode; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "callFrame": {"functionName":"Create", "scriptId":"10", "url":"url3", "lineNumber":100, "columnNumber":20}, "selfSize":10, "id":5, @@ -1930,17 +1929,17 @@ HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileNodeToObjectTest) ASSERT_TRUE(subObject->Has(ecmaVm, tmpStr)); Local subResult = subObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(subResult), "Create"); + EXPECT_EQ(DebuggerApi::ToStdString(subResult), "Create"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "scriptId"); ASSERT_TRUE(subObject->Has(ecmaVm, tmpStr)); subResult = subObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(subResult), "10"); + EXPECT_EQ(DebuggerApi::ToStdString(subResult), "10"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "url"); ASSERT_TRUE(subObject->Has(ecmaVm, tmpStr)); subResult = subObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(subResult), "url3"); + EXPECT_EQ(DebuggerApi::ToStdString(subResult), "url3"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "selfSize"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); @@ -1963,30 +1962,30 @@ HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileNodeToObjectTest) HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileCreateTest) { - CString msg; + std::string msg; std::unique_ptr object; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; object = SamplingHeapProfile::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; object = SamplingHeapProfile::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; object = SamplingHeapProfile::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; object = SamplingHeapProfile::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(object, nullptr); - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "head": { "callFrame": {"functionName":"Create", "scriptId":"10", "url":"url3", "lineNumber":100, "columnNumber":20}, "selfSize":10, @@ -2010,11 +2009,11 @@ HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileCreateTest) EXPECT_EQ(head->GetSelfSize(), 10); EXPECT_EQ(head->GetId(), 5); - const CVector> *children = head->GetChildren(); + const std::vector> *children = head->GetChildren(); ASSERT_NE(children, nullptr); EXPECT_EQ((int)children->size(), 0); - const CVector> *samples = object->GetSamples(); + const std::vector> *samples = object->GetSamples(); ASSERT_NE(samples, nullptr); EXPECT_EQ((int)samples->size(), 1); EXPECT_EQ(samples->data()->get()->GetSize(), 100); @@ -2024,11 +2023,11 @@ HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileCreateTest) HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileToObjectTest) { - CString msg; + std::string msg; std::unique_ptr samplingHeapProfile; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "head": { "callFrame": {"functionName":"Create", "scriptId":"10", "url":"url3", "lineNumber":100, "columnNumber":20}, "selfSize":10, @@ -2058,17 +2057,17 @@ HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileToObjectTest) ASSERT_TRUE(callFrameObject->Has(ecmaVm, tmpStr)); Local subResult = callFrameObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(subResult), "Create"); + EXPECT_EQ(DebuggerApi::ToStdString(subResult), "Create"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "scriptId"); ASSERT_TRUE(callFrameObject->Has(ecmaVm, tmpStr)); subResult = callFrameObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(subResult), "10"); + EXPECT_EQ(DebuggerApi::ToStdString(subResult), "10"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "url"); ASSERT_TRUE(callFrameObject->Has(ecmaVm, tmpStr)); subResult = callFrameObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!subResult.IsEmpty() && !subResult->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(subResult), "url3"); + EXPECT_EQ(DebuggerApi::ToStdString(subResult), "url3"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "selfSize"); ASSERT_TRUE(headObject->Has(ecmaVm, tmpStr)); @@ -2116,49 +2115,49 @@ HWTEST_F_L0(DebuggerTypesTest, SamplingHeapProfileToObjectTest) HWTEST_F_L0(DebuggerTypesTest, PositionTickInfoCreateTest) { - CString msg; + std::string msg; std::unique_ptr positionTickInfo; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; positionTickInfo = PositionTickInfo::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(positionTickInfo, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; positionTickInfo = PositionTickInfo::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(positionTickInfo, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; positionTickInfo = PositionTickInfo::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(positionTickInfo, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; positionTickInfo = PositionTickInfo::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(positionTickInfo, nullptr); // abnormal params of params.sub-key=["line":11,"ticks":99] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "line":"11","ticks":99}})"; positionTickInfo = PositionTickInfo::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(positionTickInfo, nullptr); // abnormal params of params.sub-key=["line":"11","ticks":"99"] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "line":"11","ticks":"99"}})"; positionTickInfo = PositionTickInfo::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(positionTickInfo, nullptr); // abnormal params of params.sub-key=["line":[11],"ticks":[99]] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "line":[11],"ticks":[99]}})"; positionTickInfo = PositionTickInfo::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(positionTickInfo, nullptr); // normal params of params.sub-key=["line":11,"ticks":99] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"line":1,"ticks":0}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"line":1,"ticks":0}})"; positionTickInfo = PositionTickInfo::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(positionTickInfo, nullptr); EXPECT_EQ(positionTickInfo->GetLine(), 1); @@ -2168,11 +2167,11 @@ HWTEST_F_L0(DebuggerTypesTest, PositionTickInfoCreateTest) HWTEST_F_L0(DebuggerTypesTest, PositionTickInfoToObjectTest) { - CString msg; + std::string msg; std::unique_ptr positionTickInfo; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "line":1,"ticks":0,}})"; positionTickInfo = PositionTickInfo::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(positionTickInfo, nullptr); @@ -2193,31 +2192,31 @@ HWTEST_F_L0(DebuggerTypesTest, PositionTickInfoToObjectTest) HWTEST_F_L0(DebuggerTypesTest, ProfileNodeCreateTest) { - CString msg; + std::string msg; std::unique_ptr profileNode; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; profileNode = ProfileNode::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(profileNode, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; profileNode = ProfileNode::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(profileNode, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; profileNode = ProfileNode::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(profileNode, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; profileNode = ProfileNode::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(profileNode, nullptr); // normal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "id":10, "callFrame": {"functionName":"name0", "scriptId":"12", "url":"url15", "lineNumber":11, "columnNumber":20}, "hitCount":15,"children":[],"positionTicks":[],"deoptReason":"yyy"}})"; @@ -2239,11 +2238,11 @@ HWTEST_F_L0(DebuggerTypesTest, ProfileNodeCreateTest) HWTEST_F_L0(DebuggerTypesTest, ProfileNodeToObjectTest) { - CString msg; + std::string msg; std::unique_ptr profilenode; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "id":10, "callFrame": {"functionName":"name0", "scriptId":"12", "url":"url15", "lineNumber":11, "columnNumber":20}, "hitCount":15,"children":[],"positionTicks":[],"deoptReason":"yyy"}})"; @@ -2267,17 +2266,17 @@ HWTEST_F_L0(DebuggerTypesTest, ProfileNodeToObjectTest) ASSERT_TRUE(tmpObject->Has(ecmaVm, tmpStr)); Local tmpResult = tmpObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!tmpResult.IsEmpty() && !tmpResult->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(tmpResult), "name0"); + EXPECT_EQ(DebuggerApi::ToStdString(tmpResult), "name0"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "scriptId"); ASSERT_TRUE(tmpObject->Has(ecmaVm, tmpStr)); tmpResult = tmpObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!tmpResult.IsEmpty() && !tmpResult->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(tmpResult), "12"); + EXPECT_EQ(DebuggerApi::ToStdString(tmpResult), "12"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "url"); ASSERT_TRUE(tmpObject->Has(ecmaVm, tmpStr)); tmpResult = tmpObject->Get(ecmaVm, tmpStr); ASSERT_TRUE(!tmpResult.IsEmpty() && !tmpResult->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(tmpResult), "url15"); + EXPECT_EQ(DebuggerApi::ToStdString(tmpResult), "url15"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "lineNumber"); ASSERT_TRUE(tmpObject->Has(ecmaVm, tmpStr)); tmpResult = tmpObject->Get(ecmaVm, tmpStr); @@ -2299,54 +2298,54 @@ HWTEST_F_L0(DebuggerTypesTest, ProfileNodeToObjectTest) ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(result), "yyy"); + EXPECT_EQ(DebuggerApi::ToStdString(result), "yyy"); } HWTEST_F_L0(DebuggerTypesTest, ProfileCreateTest) { - CString msg; + std::string msg; std::unique_ptr profile; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; profile = Profile::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(profile, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; profile = Profile::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(profile, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; profile = Profile::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(profile, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; profile = Profile::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(profile, nullptr); // abnormal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "startTime":10,"endTime":25,"nodes":[],"samples":[],"timeDeltas":[]}})"; profile = Profile::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(profile, nullptr); EXPECT_EQ(profile->GetStartTime(), 10LL); EXPECT_EQ(profile->GetEndTime(), 25LL); - const CVector> *profileNode = profile->GetNodes(); + const std::vector> *profileNode = profile->GetNodes(); ASSERT_NE(profileNode, nullptr); EXPECT_EQ((int)profileNode->size(), 0); } HWTEST_F_L0(DebuggerTypesTest, ProfileToObjectTest) { - CString msg; + std::string msg; std::unique_ptr profile; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "startTime":10,"endTime":25,"nodes":[],"samples":[],"timeDeltas":[]}})"; profile = Profile::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(profile, nullptr); @@ -2372,31 +2371,31 @@ HWTEST_F_L0(DebuggerTypesTest, ProfileToObjectTest) HWTEST_F_L0(DebuggerTypesTest, CoverageCreateTest) { - CString msg; + std::string msg; std::unique_ptr coverage; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; coverage = Coverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(coverage, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; coverage = Coverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(coverage, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; coverage = Coverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(coverage, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; coverage = Coverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(coverage, nullptr); // normal params of params.sub-key=["startOffset":0,"endOffset":5,"count":13] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "startOffset":0,"endOffset":13,"count":13}})"; coverage = Coverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(coverage, nullptr); @@ -2407,11 +2406,11 @@ HWTEST_F_L0(DebuggerTypesTest, CoverageCreateTest) HWTEST_F_L0(DebuggerTypesTest, CoverageToObjectTest) { - CString msg; + std::string msg; std::unique_ptr coverage; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "startOffset":0,"endOffset":13,"count":13}})"; coverage = Coverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(coverage, nullptr); @@ -2439,37 +2438,37 @@ HWTEST_F_L0(DebuggerTypesTest, CoverageToObjectTest) HWTEST_F_L0(DebuggerTypesTest, FunctionCoverageCreateTest) { - CString msg; + std::string msg; std::unique_ptr functionCoverage; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; functionCoverage = FunctionCoverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(functionCoverage, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; functionCoverage = FunctionCoverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(functionCoverage, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; functionCoverage = FunctionCoverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(functionCoverage, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; functionCoverage = FunctionCoverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(functionCoverage, nullptr); // normal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "functionName":"Create0","ranges":[],"isBlockCoverage":true}})"; functionCoverage = FunctionCoverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(functionCoverage, nullptr); EXPECT_EQ(functionCoverage->GetFunctionName(), "Create0"); - const CVector> *ranges = functionCoverage->GetRanges(); + const std::vector> *ranges = functionCoverage->GetRanges(); ASSERT_NE(ranges, nullptr); EXPECT_EQ((int)ranges->size(), 0); ASSERT_TRUE(functionCoverage->GetIsBlockCoverage()); @@ -2477,11 +2476,11 @@ HWTEST_F_L0(DebuggerTypesTest, FunctionCoverageCreateTest) HWTEST_F_L0(DebuggerTypesTest, FunctionCoverageToObjectTest) { - CString msg; + std::string msg; std::unique_ptr functionCoverage; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "functionName":"Create0","ranges":[],"isBlockCoverage":true}})"; functionCoverage = FunctionCoverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(functionCoverage, nullptr); @@ -2491,7 +2490,7 @@ HWTEST_F_L0(DebuggerTypesTest, FunctionCoverageToObjectTest) Local result = object->Get(ecmaVm, tmpStr); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(result), "Create0"); + EXPECT_EQ(DebuggerApi::ToStdString(result), "Create0"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "ranges"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); @@ -2506,48 +2505,48 @@ HWTEST_F_L0(DebuggerTypesTest, FunctionCoverageToObjectTest) HWTEST_F_L0(DebuggerTypesTest, ScriptCoverageCreateTest) { - CString msg; + std::string msg; std::unique_ptr scriptCoverage; // abnormal params of null msg - msg = CString() + R"({})"; + msg = std::string() + R"({})"; scriptCoverage = ScriptCoverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scriptCoverage, nullptr); // abnormal params of unexist key params - msg = CString() + R"({"id":0,"method":"Debugger.Test"})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test"})"; scriptCoverage = ScriptCoverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scriptCoverage, nullptr); // abnormal params of null params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{}})"; scriptCoverage = ScriptCoverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scriptCoverage, nullptr); // abnormal params of unknown params.sub-key - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{"unknownKey":100}})"; scriptCoverage = ScriptCoverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); EXPECT_EQ(scriptCoverage, nullptr); // normal params of params.sub-key=[..] - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"1001","url":"url17","functions":[]}})"; scriptCoverage = ScriptCoverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(scriptCoverage, nullptr); EXPECT_EQ(scriptCoverage->GetScriptId(), "1001"); EXPECT_EQ(scriptCoverage->GetUrl(), "url17"); - const CVector> *functions = scriptCoverage->GetFunctions(); + const std::vector> *functions = scriptCoverage->GetFunctions(); ASSERT_NE(functions, nullptr); EXPECT_EQ((int)functions->size(), 0); } HWTEST_F_L0(DebuggerTypesTest, ScriptCoverageToObjectTest) { - CString msg; + std::string msg; std::unique_ptr scriptCoverage; Local tmpStr; - msg = CString() + R"({"id":0,"method":"Debugger.Test","params":{ + msg = std::string() + R"({"id":0,"method":"Debugger.Test","params":{ "scriptId":"1001","url":"url17","functions":[]}})"; scriptCoverage = ScriptCoverage::Create(ecmaVm, DispatchRequest(ecmaVm, msg).GetParams()); ASSERT_NE(scriptCoverage, nullptr); @@ -2557,12 +2556,12 @@ HWTEST_F_L0(DebuggerTypesTest, ScriptCoverageToObjectTest) Local result = object->Get(ecmaVm, tmpStr); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(result), "1001"); + EXPECT_EQ(DebuggerApi::ToStdString(result), "1001"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "url"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); ASSERT_TRUE(!result.IsEmpty() && !result->IsUndefined()); - EXPECT_EQ(DebuggerApi::ToCString(result), "url17"); + EXPECT_EQ(DebuggerApi::ToStdString(result), "url17"); tmpStr = StringRef::NewFromUtf8(ecmaVm, "functions"); ASSERT_TRUE(object->Has(ecmaVm, tmpStr)); result = object->Get(ecmaVm, tmpStr); diff --git a/ecmascript/tooling/test/utils/test_entry.cpp b/ecmascript/tooling/test/utils/test_entry.cpp index 511105fe17..5e3d90b47b 100644 --- a/ecmascript/tooling/test/utils/test_entry.cpp +++ b/ecmascript/tooling/test/utils/test_entry.cpp @@ -26,7 +26,7 @@ static std::unique_ptr g_hooks = nullptr; bool StartDebuggerImpl([[maybe_unused]] const std::string &name, EcmaVM *vm, [[maybe_unused]] bool isDebugMode) { - CString testName = GetCurrentTestName(); + std::string testName = GetCurrentTestName(); g_hooks = std::make_unique(testName, vm); g_debuggerThread = std::thread([] { TestUtil::WaitForInit(); diff --git a/ecmascript/tooling/test/utils/test_events.h b/ecmascript/tooling/test/utils/test_events.h index 17236c9dc7..54e41ba60d 100644 --- a/ecmascript/tooling/test/utils/test_events.h +++ b/ecmascript/tooling/test/utils/test_events.h @@ -59,7 +59,7 @@ struct TestEvents { TestEvents(); virtual ~TestEvents() = default; - virtual std::pair GetEntryPoint() = 0; + virtual std::pair GetEntryPoint() = 0; }; } // namespace panda::ecmascript::tooling::test diff --git a/ecmascript/tooling/test/utils/test_extractor.h b/ecmascript/tooling/test/utils/test_extractor.h index 4cf68e4f2e..5cc9bedc5c 100644 --- a/ecmascript/tooling/test/utils/test_extractor.h +++ b/ecmascript/tooling/test/utils/test_extractor.h @@ -23,7 +23,7 @@ using EntityId = panda_file::File::EntityId; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) struct SourceLocation { - CString path; // NOLINT(misc-non-private-member-variables-in-classes) + std::string path; // NOLINT(misc-non-private-member-variables-in-classes) int32_t line; // NOLINT(misc-non-private-member-variables-in-classes) int32_t column; diff --git a/ecmascript/tooling/test/utils/test_hooks.h b/ecmascript/tooling/test/utils/test_hooks.h index c5adf6c373..e5fa79c77b 100644 --- a/ecmascript/tooling/test/utils/test_hooks.h +++ b/ecmascript/tooling/test/utils/test_hooks.h @@ -23,7 +23,7 @@ namespace panda::ecmascript::tooling::test { class TestHooks : public PtHooks { public: - TestHooks(const CString &testName, const EcmaVM *vm) : vm_(vm) + TestHooks(const std::string &testName, const EcmaVM *vm) : vm_(vm) { runtime_ = std::make_unique(vm, nullptr); debugger_ = std::make_unique(vm, nullptr, runtime_.get()); @@ -113,7 +113,7 @@ private: std::unique_ptr runtime_ {nullptr}; std::unique_ptr debugger_ {nullptr}; JSDebugger *debugInterface_; - CString testName_; + std::string testName_; TestEvents *test_; }; } // namespace panda::ecmascript::tooling::test diff --git a/ecmascript/tooling/test/utils/test_util.h b/ecmascript/tooling/test/utils/test_util.h index 4186834b40..993826daaa 100644 --- a/ecmascript/tooling/test/utils/test_util.h +++ b/ecmascript/tooling/test/utils/test_util.h @@ -26,16 +26,16 @@ namespace panda::ecmascript::tooling::test { template, class KeyEqual = std::equal_to> using CUnorderedMap = panda::ecmascript::CUnorderedMap; -using TestMap = CUnorderedMap>; +using TestMap = CUnorderedMap>; class TestUtil { public: - static void RegisterTest(const CString &testName, std::unique_ptr test) + static void RegisterTest(const std::string &testName, std::unique_ptr test) { testMap_.insert({testName, std::move(test)}); } - static TestEvents *GetTest(const CString &name) + static TestEvents *GetTest(const std::string &name) { auto iter = std::find_if(testMap_.begin(), testMap_.end(), [&name](auto &it) { return it.first == name; diff --git a/ecmascript/tooling/test/utils/testcases/js_breakpoint_arrow_test.h b/ecmascript/tooling/test/utils/testcases/js_breakpoint_arrow_test.h index 9ce610f248..e502c037e4 100644 --- a/ecmascript/tooling/test/utils/testcases/js_breakpoint_arrow_test.h +++ b/ecmascript/tooling/test/utils/testcases/js_breakpoint_arrow_test.h @@ -66,15 +66,15 @@ public: }; } - std::pair GetEntryPoint() override + std::pair GetEntryPoint() override { return {pandaFile_, entryPoint_}; } ~JsBreakpointArrowTest() = default; private: - CString pandaFile_ = DEBUGGER_ABC_DIR "ArrowFunc.abc"; - CString entryPoint_ = "_GLOBAL::func_main_0"; + std::string pandaFile_ = DEBUGGER_ABC_DIR "ArrowFunc.abc"; + std::string entryPoint_ = "_GLOBAL::func_main_0"; JSPtLocation location_ {nullptr, JSPtLocation::EntityId(0), 0}; size_t breakpointCounter_ = 0; bool flag_ = true; diff --git a/ecmascript/tooling/test/utils/testcases/js_breakpoint_async_test.h b/ecmascript/tooling/test/utils/testcases/js_breakpoint_async_test.h index 07d32c8708..2c90269baa 100644 --- a/ecmascript/tooling/test/utils/testcases/js_breakpoint_async_test.h +++ b/ecmascript/tooling/test/utils/testcases/js_breakpoint_async_test.h @@ -68,15 +68,15 @@ public: }; } - std::pair GetEntryPoint() override + std::pair GetEntryPoint() override { return {pandaFile_, entryPoint_}; } ~JsBreakpointAsyncTest() = default; private: - CString pandaFile_ = DEBUGGER_ABC_DIR "AsyncFunc.abc"; - CString entryPoint_ = "_GLOBAL::func_main_0"; + std::string pandaFile_ = DEBUGGER_ABC_DIR "AsyncFunc.abc"; + std::string entryPoint_ = "_GLOBAL::func_main_0"; JSPtLocation location_ {nullptr, JSPtLocation::EntityId(0), 0}; size_t breakpointCounter_ = 0; bool flag_ = true; diff --git a/ecmascript/tooling/test/utils/testcases/js_breakpoint_test.h b/ecmascript/tooling/test/utils/testcases/js_breakpoint_test.h index de9abb00e3..a598d26166 100644 --- a/ecmascript/tooling/test/utils/testcases/js_breakpoint_test.h +++ b/ecmascript/tooling/test/utils/testcases/js_breakpoint_test.h @@ -68,15 +68,15 @@ public: }; } - std::pair GetEntryPoint() override + std::pair GetEntryPoint() override { return {pandaFile_, entryPoint_}; } ~JsBreakpointTest() = default; private: - CString pandaFile_ = DEBUGGER_ABC_DIR "Sample.abc"; - CString entryPoint_ = "_GLOBAL::func_main_0"; + std::string pandaFile_ = DEBUGGER_ABC_DIR "Sample.abc"; + std::string entryPoint_ = "_GLOBAL::func_main_0"; JSPtLocation location_ {nullptr, JSPtLocation::EntityId(0), 0}; size_t breakpointCounter_ = 0; bool flag_ = true; diff --git a/ecmascript/tooling/test/utils/testcases/js_exception_test.h b/ecmascript/tooling/test/utils/testcases/js_exception_test.h index 004eb6e14e..94b3b5317d 100644 --- a/ecmascript/tooling/test/utils/testcases/js_exception_test.h +++ b/ecmascript/tooling/test/utils/testcases/js_exception_test.h @@ -33,7 +33,7 @@ public: ASSERT_TRUE(location.GetMethodId().IsValid()); ASSERT_LOCATION_EQ(location, location_); ++breakpointCounter_; - CVector> callFrames; + std::vector> callFrames; ASSERT_TRUE(debugger_->GenerateCallFrames(&callFrames)); ASSERT_TRUE(callFrames.size() > 0); auto jsLocation = callFrames[0]->GetLocation(); @@ -49,7 +49,7 @@ public: ASSERT_EQ(sourceLocation.line, 17); ASSERT_EQ(sourceLocation.column, 27); ++exceptionCounter_; - CVector> callFrames; + std::vector> callFrames; ASSERT_TRUE(debugger_->GenerateCallFrames(&callFrames)); ASSERT_TRUE(callFrames.size() > 0); auto jsLocation = callFrames[0]->GetLocation(); @@ -92,15 +92,15 @@ public: }; } - std::pair GetEntryPoint() override + std::pair GetEntryPoint() override { return {pandaFile_, entryPoint_}; } ~JsExceptionTest() = default; private: - CString pandaFile_ = DEBUGGER_ABC_DIR "exception.abc"; - CString entryPoint_ = "_GLOBAL::func_main_0"; + std::string pandaFile_ = DEBUGGER_ABC_DIR "exception.abc"; + std::string entryPoint_ = "_GLOBAL::func_main_0"; JSPtLocation location_ {nullptr, JSPtLocation::EntityId(0), 0}; size_t breakpointCounter_ = 0; size_t exceptionCounter_ = 0; diff --git a/ecmascript/tooling/test/utils/testcases/js_single_step_test.h b/ecmascript/tooling/test/utils/testcases/js_single_step_test.h index 9888595399..08cc43d566 100644 --- a/ecmascript/tooling/test/utils/testcases/js_single_step_test.h +++ b/ecmascript/tooling/test/utils/testcases/js_single_step_test.h @@ -77,14 +77,14 @@ public: }; } - std::pair GetEntryPoint() override + std::pair GetEntryPoint() override { return {pandaFile_, entryPoint_}; } private: - CString pandaFile_ = DEBUGGER_ABC_DIR "Sample.abc"; - CString entryPoint_ = "_GLOBAL::func_main_0"; + std::string pandaFile_ = DEBUGGER_ABC_DIR "Sample.abc"; + std::string entryPoint_ = "_GLOBAL::func_main_0"; JSPtLocation locationStart_ {nullptr, JSPtLocation::EntityId(0), 0}; JSPtLocation locationEnd_ {nullptr, JSPtLocation::EntityId(0), 0}; JSPtLocation locationStep_ {nullptr, JSPtLocation::EntityId(0), 0}; diff --git a/ecmascript/tooling/test/utils/testcases/test_list.cpp b/ecmascript/tooling/test/utils/testcases/test_list.cpp index 430ac42f1b..2cb272b700 100644 --- a/ecmascript/tooling/test/utils/testcases/test_list.cpp +++ b/ecmascript/tooling/test/utils/testcases/test_list.cpp @@ -25,7 +25,7 @@ #include "js_single_step_test.h" namespace panda::ecmascript::tooling::test { -static CString g_currentTestName = ""; +static std::string g_currentTestName = ""; static void RegisterTests() { @@ -37,10 +37,10 @@ static void RegisterTests() TestUtil::RegisterTest("JsBreakpointArrowTest", GetJsBreakpointArrowTest()); } -CVector GetTestList() +std::vector GetTestList() { RegisterTests(); - CVector res; + std::vector res; auto &tests = TestUtil::GetTests(); for (const auto &entry : tests) { @@ -49,17 +49,17 @@ CVector GetTestList() return res; } -void SetCurrentTestName(const CString &testName) +void SetCurrentTestName(const std::string &testName) { g_currentTestName = testName; } -CString GetCurrentTestName() +std::string GetCurrentTestName() { return g_currentTestName; } -std::pair GetTestEntryPoint(const CString &testName) +std::pair GetTestEntryPoint(const std::string &testName) { return TestUtil::GetTest(testName)->GetEntryPoint(); } diff --git a/ecmascript/tooling/test/utils/testcases/test_list.h b/ecmascript/tooling/test/utils/testcases/test_list.h index e9a75a34b0..0409f3897f 100644 --- a/ecmascript/tooling/test/utils/testcases/test_list.h +++ b/ecmascript/tooling/test/utils/testcases/test_list.h @@ -24,12 +24,12 @@ #include "libpandafile/file_items.h" namespace panda::ecmascript::tooling::test { -CVector GetTestList(); +std::vector GetTestList(); -void SetCurrentTestName(const CString &testName); -CString GetCurrentTestName(); +void SetCurrentTestName(const std::string &testName); +std::string GetCurrentTestName(); -std::pair GetTestEntryPoint(const CString &testName); +std::pair GetTestEntryPoint(const std::string &testName); } // namespace panda::ecmascript::tooling::test #endif // ECMASCRIPT_TOOLING_TEST_UTILS_TESTCASES_TEST_LIST_H From cc68d44210c609a63da27c2c882fecc1b1ad3724 Mon Sep 17 00:00:00 2001 From: zhangyukun Date: Tue, 7 Jun 2022 16:26:22 +0800 Subject: [PATCH 34/35] Fix rsp frame on arm64 1. add call getter and setter Signed-off-by: zhangyukun Change-Id: I0ce295ec5c915d5c0e0aa724a28b6450d7fa4416 --- .../trampoline/aarch64/assembler_stubs.cpp | 167 ++++++++++++------ .../trampoline/aarch64/assembler_stubs.h | 17 +- 2 files changed, 126 insertions(+), 58 deletions(-) diff --git a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp index 741b7a525f..fd78c811f9 100644 --- a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp +++ b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.cpp @@ -669,23 +669,12 @@ void AssemblerStubs::CallRuntimeWithArgv(ExtendedAssembler *assembler) void AssemblerStubs::AsmInterpreterEntry(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(AsmInterpreterEntry)); - __ CalleeSave(); - Register glueRegister(X0); - Register spRegister(SP); - // caller save reg - __ Str(glueRegister, MemoryOperand(spRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - // push asm interpreter entry frame - Register frameTypeRegister(X3); - Register prevFrameRegister(X4); - Register pcRegister(X21); - PushAsmInterpEntryFrame(assembler, frameTypeRegister, prevFrameRegister, pcRegister); + + PushAsmInterpEntryFrame(assembler, true); __ CallAssemblerStub(RTSTUB_ID(JSCallDispatch), false); - PopAsmInterpEntryFrame(assembler, prevFrameRegister); - __ Ldr(glueRegister, MemoryOperand(spRegister, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); - __ Str(prevFrameRegister, MemoryOperand(glueRegister, JSThread::GlueData::GetLeaveFrameOffset(false))); - __ CalleeRestore(); + PopAsmInterpEntryFrame(assembler, true); __ Ret(); } @@ -1221,7 +1210,7 @@ void AssemblerStubs::ResumeRspAndDispatch(ExtendedAssembler *assembler) __ Br(bcStub); } -void AssemblerStubs::ResumeRspAndReturn([[maybe_unused]] ExtendedAssembler *assembler) +void AssemblerStubs::ResumeRspAndReturn(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(ResumeRspAndReturn)); Register sp(SP); @@ -1295,16 +1284,81 @@ void AssemblerStubs::ResumeUncaughtFrameAndReturn(ExtendedAssembler *assembler) __ Ret(); } -void AssemblerStubs::CallGetter([[maybe_unused]] ExtendedAssembler *assembler) +// c++ calling convention +// X0 - glue +// X1 - callTarget +// X2 - method +// X3 - callField +// X4 - receiver +// X5 - value +void AssemblerStubs::CallGetter(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(CallGetter)); + Label target; + + PushAsmInterpEntryFrame(assembler, false); + __ Bl(&target); + PopAsmInterpEntryFrame(assembler, false); __ Ret(); + __ Bind(&target); + { + __ PushFpAndLr(); + JSCallCommonEntry(assembler, JSCallMode::CALL_GETTER, CallGetterEntry, CallGetterSlow); + } } -void AssemblerStubs::CallSetter([[maybe_unused]] ExtendedAssembler *assembler) +void AssemblerStubs::CallGetterEntry(ExtendedAssembler *assembler) +{ + Register receiverRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0); + PushCallThis(assembler, receiverRegister, false); // receiver +} + +void AssemblerStubs::CallGetterSlow(ExtendedAssembler *assembler) +{ + JSCallCommonSlowPath(assembler, JSCallMode::CALL_GETTER, CallGetterEntry, CallGetterEntry); +} + +void AssemblerStubs::CallSetter(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(CallSetter)); + Label target; + PushAsmInterpEntryFrame(assembler, false); + __ Bl(&target); + PopAsmInterpEntryFrame(assembler, false); __ Ret(); + __ Bind(&target); + { + __ PushFpAndLr(); + JSCallCommonEntry(assembler, JSCallMode::CALL_SETTER, CallSetterEntry, CallSetterSlow); + } +} + +void AssemblerStubs::CallSetterEntry(ExtendedAssembler *assembler) +{ + Register receiverRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0); + Register valueRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1); + __ Str(valueRegister, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // arg0 + PushCallThis(assembler, receiverRegister, false); // receiver +} + +void AssemblerStubs::CallNoExtraSetterEntry(ExtendedAssembler *assembler) +{ + constexpr int32_t argc = 1; + Register declaredNumArgsRegister = __ AvailableRegister2(); + Label callargs0NoExtraEntry; + __ Cmp(declaredNumArgsRegister.W(), Immediate(argc)); + __ B(Condition::LO, &callargs0NoExtraEntry); + Register valueRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG1); + __ Str(valueRegister, MemoryOperand(Register(SP), -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // arg0 + // fall through + __ Bind(&callargs0NoExtraEntry); + Register receiverRegister = __ CallDispatcherArgument(kungfu::CallDispatchInputs::ARG0); + PushCallThis(assembler, receiverRegister, false); // receiver +} + +void AssemblerStubs::CallSetterSlow(ExtendedAssembler *assembler) +{ + JSCallCommonSlowPath(assembler, JSCallMode::CALL_SETTER, CallNoExtraSetterEntry, CallSetterEntry); } // Generate code for generator re-entering asm interpreter @@ -1314,18 +1368,13 @@ void AssemblerStubs::CallSetter([[maybe_unused]] ExtendedAssembler *assembler) void AssemblerStubs::GeneratorReEnterAsmInterp(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(GeneratorReEnterAsmInterp)); - __ CalleeSave(); Label pushFrameState; - Register glue(X0); + Register glue = __ GlueRegister(); Register contextRegister(X1); Register spRegister(SP); - // caller save reg - __ Str(glue, MemoryOperand(spRegister, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - // push asm interpreter entry frame - Register frameTypeRegister(X2); - Register prevFrameRegister(X3); Register pc(X21); - PushAsmInterpEntryFrame(assembler, frameTypeRegister, prevFrameRegister, pc); + + PushAsmInterpEntryFrame(assembler, true); Register prevSpRegister(FP); Register callTarget(X4); @@ -1347,16 +1396,12 @@ void AssemblerStubs::GeneratorReEnterAsmInterp(ExtendedAssembler *assembler) __ Bind(&pushFrameState); __ Mov(newSp, spRegister); // push frame state - PushGeneratorFrameState(assembler, frameTypeRegister, prevSpRegister, fpRegister, callTarget, - method, contextRegister, pc, temp); + PushGeneratorFrameState(assembler, prevSpRegister, fpRegister, callTarget, method, contextRegister, pc, temp); // call bc stub CallBCStub(assembler, newSp, glue, callTarget, method, pc, temp); - PopAsmInterpEntryFrame(assembler, prevFrameRegister); - __ Ldr(glue, MemoryOperand(spRegister, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); - __ Str(prevFrameRegister, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); - __ CalleeRestore(); + PopAsmInterpEntryFrame(assembler, true); __ Ret(); } @@ -1398,6 +1443,7 @@ void AssemblerStubs::PushCallThis(ExtendedAssembler *assembler, Register thisReg [[maybe_unused]] TempRegister1Scope scope1(assembler); Register tempRegister = __ TempRegister1(); __ Mov(tempRegister, Immediate(JSTaggedValue::VALUE_UNDEFINED)); + __ Str(tempRegister, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); } else { __ Str(thisRegister, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); } @@ -1616,58 +1662,75 @@ void AssemblerStubs::StackOverflowCheck([[maybe_unused]] ExtendedAssembler *asse { } -void AssemblerStubs::PushAsmInterpEntryFrame(ExtendedAssembler *assembler, Register &frameTypeRegister, - Register &prevFrameRegister, Register &pcRegister) +void AssemblerStubs::PushAsmInterpEntryFrame(ExtendedAssembler *assembler, bool saveLeave) { - __ SaveFpAndLr(); - // construct asm interpreter entry frame - Register glue(X0); + Register glue = __ GlueRegister(); Register sp(SP); + + __ CalleeSave(); + + [[maybe_unused]] TempRegister1Scope scope1(assembler); + Register prevFrameRegister = __ TempRegister1(); + [[maybe_unused]] TempRegister2Scope scope2(assembler); + Register frameTypeRegister = __ TempRegister2(); + + if (saveLeave) { + __ Str(glue, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + // prev managed fp is leave frame or nullptr(the first frame) + __ Ldr(prevFrameRegister, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); + } else { + __ Mov(prevFrameRegister, Register(FP)); + } + __ SaveFpAndLr(); __ Mov(frameTypeRegister, Immediate(static_cast(FrameType::ASM_INTERPRETER_ENTRY_FRAME))); - // prev managed fp is leave frame or nullptr(the first frame) - __ Ldr(prevFrameRegister, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); + // 2 : 2 means pair __ Stp(prevFrameRegister, frameTypeRegister, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); - __ Mov(pcRegister, Immediate(0)); - // pc - __ Str(pcRegister, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + __ Str(Register(Zero), MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // pc } -void AssemblerStubs::PopAsmInterpEntryFrame(ExtendedAssembler *assembler, Register &prevFrameRegister) +void AssemblerStubs::PopAsmInterpEntryFrame(ExtendedAssembler *assembler, bool saveLeave) { + Register glue = __ GlueRegister(); Register sp(SP); + + [[maybe_unused]] TempRegister1Scope scope1(assembler); + Register prevFrameRegister = __ TempRegister1(); // skip pc __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE)); __ Ldr(prevFrameRegister, MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); // skip frame type __ Add(sp, sp, Immediate(FRAME_SLOT_SIZE)); + __ RestoreFpAndLr(); + if (saveLeave) { + __ Ldr(glue, MemoryOperand(sp, FRAME_SLOT_SIZE, AddrMode::POSTINDEX)); + __ Str(prevFrameRegister, MemoryOperand(glue, JSThread::GlueData::GetLeaveFrameOffset(false))); + } + __ CalleeRestore(); } -void AssemblerStubs::PushGeneratorFrameState(ExtendedAssembler *assembler, Register &frameTypeRegister, - Register &prevSpRegister, Register &fpRegister, Register &callTargetRegister, Register &methodRegister, +void AssemblerStubs::PushGeneratorFrameState(ExtendedAssembler *assembler, Register &prevSpRegister, + Register &fpRegister, Register &callTargetRegister, Register &methodRegister, Register &contextRegister, Register &pcRegister, Register &operatorRegister) { Register sp(SP); - __ Mov(frameTypeRegister, Immediate(static_cast(FrameType::ASM_INTERPRETER_FRAME))); - // frameType and prevSp - // 2 : 2 means pair - __ Stp(prevSpRegister, frameTypeRegister, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + __ Mov(operatorRegister, Immediate(static_cast(FrameType::ASM_INTERPRETER_FRAME))); + // 2 : frameType and prevSp + __ Stp(prevSpRegister, operatorRegister, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); __ Ldr(pcRegister, MemoryOperand(methodRegister, JSMethod::GetBytecodeArrayOffset(false))); __ Ldr(operatorRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_BC_OFFSET_OFFSET)); __ Add(pcRegister, operatorRegister, pcRegister); __ Add(pcRegister, pcRegister, Immediate(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_V8_V8))); // pc and fp __ Stp(fpRegister, pcRegister, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); // 2 : 2 means pair - __ Mov(operatorRegister, Immediate(0)); // jumpSizeAfterCall - __ Str(operatorRegister, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); + __ Str(Register(Zero), MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); __ Ldr(operatorRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_LEXICALENV_OFFSET)); // env __ Str(operatorRegister, MemoryOperand(sp, -FRAME_SLOT_SIZE, AddrMode::PREINDEX)); __ Ldr(operatorRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_ACC_OFFSET)); - // acc and callTarget - // 2 : 2 means pair + // 2 : acc and callTarget __ Stp(callTargetRegister, operatorRegister, MemoryOperand(sp, -2 * FRAME_SLOT_SIZE, AddrMode::PREINDEX)); } diff --git a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h index 11d09bd59b..6859813d31 100644 --- a/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h +++ b/ecmascript/compiler/trampoline/aarch64/assembler_stubs.h @@ -168,14 +168,13 @@ private: static void StackOverflowCheck([[maybe_unused]] ExtendedAssembler *assembler); - static void PushAsmInterpEntryFrame(ExtendedAssembler *assembler, Register &frameTypeRegister, - Register &prevFrameRegister, Register &pcRegister); + static void PushAsmInterpEntryFrame(ExtendedAssembler *assembler, bool saveLeave); - static void PopAsmInterpEntryFrame(ExtendedAssembler *assembler, Register &prevFrameRegister); + static void PopAsmInterpEntryFrame(ExtendedAssembler *assembler, bool saveLeave); - static void PushGeneratorFrameState(ExtendedAssembler *assembler, Register &frameTypeRegister, - Register &prevSpRegister, Register &fpRegister, Register &callTargetRegister, Register &methodRegister, - Register &contextRegister, Register &pcRegister, Register &operatorRegister); + static void PushGeneratorFrameState(ExtendedAssembler *assembler, Register &prevSpRegister, Register &fpRegister, + Register &callTargetRegister, Register &methodRegister, Register &contextRegister, Register &pcRegister, + Register &operatorRegister); static void CallBCStub(ExtendedAssembler *assembler, Register &newSp, Register &glue, Register &callTarget, Register &method, Register &pc, Register &temp); @@ -189,6 +188,12 @@ private: static void PushArgsSlowPath(ExtendedAssembler *assembler, Register &glueRegister, Register &declaredNumArgsRegister, Register &argcRegister, Register &argvRegister, Register &callTargetRegister, Register &methodRegister, Register &prevSpRegister, Register &callFieldRegister); + + static void CallGetterSlow(ExtendedAssembler *assembler); + static void CallSetterSlow(ExtendedAssembler *assembler); + static void CallGetterEntry(ExtendedAssembler *assembler); + static void CallSetterEntry(ExtendedAssembler *assembler); + static void CallNoExtraSetterEntry(ExtendedAssembler *assembler); }; } // namespace panda::ecmascript::x64 #endif // ECMASCRIPT_COMPILER_ASSEMBLER_MODULE_X64_H From 930d4337849f0637e92baf80b487f17d92e39a5f Mon Sep 17 00:00:00 2001 From: xliu Date: Tue, 7 Jun 2022 19:58:20 +0800 Subject: [PATCH 35/35] fix string trim Description fix string trim of empty string. Issue: #I5B6S0:fix string trim Signed-off-by: xliu Change-Id: Ia1b6274252536ecc8ffd62d2459f8ab6f5ba8335 --- ecmascript/builtins/builtins_string.cpp | 4 ++-- ecmascript/ecma_string-inl.h | 30 +++++++++++++++---------- ecmascript/ecma_string.cpp | 4 ---- ecmascript/ecma_string.h | 4 ++-- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/ecmascript/builtins/builtins_string.cpp b/ecmascript/builtins/builtins_string.cpp index 97c055f851..eb0b462fa1 100644 --- a/ecmascript/builtins/builtins_string.cpp +++ b/ecmascript/builtins/builtins_string.cpp @@ -1543,14 +1543,14 @@ JSTaggedValue BuiltinsString::Trim(EcmaRuntimeCallInfo *argv) Span data(reinterpret_cast(thisHandle->GetData()), thisLen); uint32_t start = base::StringHelper::GetStart(data, thisLen); uint32_t end = base::StringHelper::GetEnd(data, start, thisLen); - EcmaString *res = EcmaString::FastSubUtf8String(thread->GetEcmaVM(), thisHandle, start, end - start + 1); + EcmaString *res = EcmaString::FastSubUtf8String(thread->GetEcmaVM(), thisHandle, start, end + 1 - start); return JSTaggedValue(res); } Span data(thisHandle->GetData(), thisLen); uint32_t start = base::StringHelper::GetStart(data, thisLen); uint32_t end = base::StringHelper::GetEnd(data, start, thisLen); - EcmaString *res = EcmaString::FastSubUtf16String(thread->GetEcmaVM(), thisHandle, start, end - start + 1); + EcmaString *res = EcmaString::FastSubUtf16String(thread->GetEcmaVM(), thisHandle, start, end + 1 - start); return JSTaggedValue(res); } diff --git a/ecmascript/ecma_string-inl.h b/ecmascript/ecma_string-inl.h index faffbca895..099eb51aed 100644 --- a/ecmascript/ecma_string-inl.h +++ b/ecmascript/ecma_string-inl.h @@ -192,13 +192,16 @@ void EcmaString::WriteData(char src, uint32_t start) /* static */ EcmaString *EcmaString::FastSubUtf8String(const EcmaVM *vm, const JSHandle &src, uint32_t start, - uint32_t utf16Len) + uint32_t length) { - auto string = AllocStringObject(utf16Len, true, vm); + if (length == 0) { + return *vm->GetFactory()->GetEmptyString(); + } + auto string = AllocStringObject(length, true, vm); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - Span dst(string->GetDataUtf8Writable(), utf16Len); - Span source(src->GetDataUtf8() + start, utf16Len); - EcmaString::StringCopy(dst, utf16Len, source, utf16Len); + Span dst(string->GetDataUtf8Writable(), length); + Span source(src->GetDataUtf8() + start, length); + EcmaString::StringCopy(dst, length, source, length); ASSERT_PRINT(CanBeCompressed(string), "canBeCompresse does not match the real value!"); return string; @@ -206,18 +209,21 @@ EcmaString *EcmaString::FastSubUtf8String(const EcmaVM *vm, const JSHandle &src, uint32_t start, - uint32_t utf16Len) + uint32_t length) { - bool canBeCompressed = CanBeCompressed(src->GetDataUtf16() + start, utf16Len); - auto string = AllocStringObject(utf16Len, canBeCompressed, vm); + if (length == 0) { + return *vm->GetFactory()->GetEmptyString(); + } + bool canBeCompressed = CanBeCompressed(src->GetDataUtf16() + start, length); + auto string = AllocStringObject(length, canBeCompressed, vm); if (canBeCompressed) { // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - CopyUtf16AsUtf8(src->GetDataUtf16() + start, string->GetDataUtf8Writable(), utf16Len); + CopyUtf16AsUtf8(src->GetDataUtf16() + start, string->GetDataUtf8Writable(), length); } else { - uint32_t len = utf16Len * (sizeof(uint16_t) / sizeof(uint8_t)); + uint32_t len = length * (sizeof(uint16_t) / sizeof(uint8_t)); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - Span dst(string->GetDataUtf16Writable(), utf16Len); - Span source(src->GetDataUtf16() + start, utf16Len); + Span dst(string->GetDataUtf16Writable(), length); + Span source(src->GetDataUtf16() + start, length); EcmaString::StringCopy(dst, len, source, len); } ASSERT_PRINT(canBeCompressed == CanBeCompressed(string), "canBeCompresse does not match the real value!"); diff --git a/ecmascript/ecma_string.cpp b/ecmascript/ecma_string.cpp index 1f116a8d4d..9219f0a79e 100644 --- a/ecmascript/ecma_string.cpp +++ b/ecmascript/ecma_string.cpp @@ -80,10 +80,6 @@ EcmaString *EcmaString::Concat(const JSHandle &str1Handle, const JSH EcmaString *EcmaString::FastSubString(const JSHandle &src, uint32_t start, uint32_t utf16Len, const EcmaVM *vm) { - if (utf16Len == 0) { - return vm->GetFactory()->GetEmptyString().GetObject(); - } - if (src->IsUtf8()) { return FastSubUtf8String(vm, src, start, utf16Len); } diff --git a/ecmascript/ecma_string.h b/ecmascript/ecma_string.h index 8ec521fb8b..ee6ef7e3ef 100644 --- a/ecmascript/ecma_string.h +++ b/ecmascript/ecma_string.h @@ -315,9 +315,9 @@ public: static constexpr size_t DATA_OFFSET = SIZE; // DATA_OFFSET equal to Empty String size static inline EcmaString *FastSubUtf8String(const EcmaVM *vm, const JSHandle &src, uint32_t start, - uint32_t utf16Len); + uint32_t length); static inline EcmaString *FastSubUtf16String(const EcmaVM *vm, const JSHandle &src, uint32_t start, - uint32_t utf16Len); + uint32_t length); private: void SetLength(uint32_t length, bool compressed = false) {